thedmd / imgui-node-editor

Node Editor built using Dear ImGui
MIT License
3.48k stars 527 forks source link

Using ImGui::BeginHorizontal in a node #284

Closed pthom closed 3 months ago

pthom commented 3 months ago

Hello,

I would like more information about the usage of your horizontal layout utilities inside a node.

I made some test with the following simple code:

void gui()
{
    static float minWidth = 70.f;

    ed::Begin("Node Editor");

    constexpr int node_id = 1;

    ed::BeginNode(node_id);

    // A dummy item to set the node min width
    ImGui::Dummy(ImVec2(minWidth, 10));

    // Test different values of the horizontalLayout width
    float horizontalLayoutWidth;

    // With this, the right label is not aligned to the right of the node
    horizontalLayoutWidth = 0.f;

    // With the, the node width changes when dragged with the mouse to the left
    // horizontalLayoutWidth = ImGui::GetContentRegionAvail().x;

    // With this, the right alignment "almost works", except it resizes the node only on the first frame
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f;

    // With this, the node size will increase frame by frame
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f + 1.f;

    // With this, the right label is not taken into account in the node size
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f - 1.f;

    // Display an horizontal layout with two labels separated by a spring
    ImGui::BeginHorizontal("Hor", ImVec2(horizontalLayoutWidth, 0.f));
    ImGui::Text("LEFT LABEL");
    ImGui::Spring();
    ImGui::Text("RIGHT LABEL");
    ImGui::EndHorizontal();

    // Edit the min width
    ImGui::Text("Min Width");
    ImGui::SetNextItemWidth(70.f);
    ImGui::SliderFloat("##minWidth", &minWidth, 0.f, 600.f);

    ed::EndNode();

    ed::End();
}

With horizontalLayoutWidth = 0.f, I have the following result:

image

(i.e. the right label is not aligned to the right)

I tested different other possibilities, but did not find the correct one, I guess:

    // Test different values of the horizontalLayout width
    float horizontalLayoutWidth;

    // With this, the right label is not aligned to the right of the node
    horizontalLayoutWidth = 0.f;

    // With the, the node width changes when dragged with the mouse to the left
    // horizontalLayoutWidth = ImGui::GetContentRegionAvail().x;

    // With this, the right alignment "almost works", except it resizes the node only on the first frame
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f;

    // With this, the node size will increase frame by frame
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f + 1.f;

    // With this, the right label is not taken into account in the node size
    // horizontalLayoutWidth = ed::GetNodeSize(node_id).x - ImGui::GetStyle().ItemSpacing.x * 2.f - 1.f;

Here is a quick video of what I observed (1 minute long)

https://github.com/thedmd/imgui-node-editor/assets/7694091/18f61b4c-6b70-46a8-9c1b-0ef598f912b6

Am I missing something?

Many thanks for your hard work!

pthom commented 3 months ago

Closing this, the solution is that once you use ImGui::BeginHorizontal in a given window, you should also use ImGui::BeginVertical (so that the vertical layout width is transferred to its child horizontal layout).

And the code could for example be:

    ed::BeginNode(node_id);

    // A vertical layout that will contain the horizontal layout as a child
    ImGui::BeginVertical("Vertical");
    {
        // A dummy item to set the node min width
        ImGui::Dummy(ImVec2(minWidth, 0));

        // Edit the min width
        ImGui::Text("Min Width");
        ImGui::SetNextItemWidth(70.f);
        ImGui::SliderFloat("##minWidth", &minWidth, 0.f, 600.f);

        // The horizontal child layout
        ImGui::BeginHorizontal("Hor");
        {
            ImGui::Text("LEFT LABEL");
            ImGui::Spring();
            ImGui::Text("RIGHT LABEL");
        }
        ImGui::EndHorizontal();
    }
    ImGui::EndVertical();

    ed::EndNode();

I think it could be worse it to add a succinct doc to imgui_stacklayout.h in the future. If you are interested, I could try to propose something.

Thanks!