thedmd / imgui-node-editor

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

Proposal fix for ImGui::TextWrapped() and ImGui::Separator(), ImGui::SliderXXX inside Nodes #298

Open pthom opened 1 week ago

pthom commented 1 week ago

By default, ImGui::TextWrapped() and ImGui::Separator(), ImGui::SliderXXX will not work in a Node because they will not respect the node's bounds. Instead, they will use the bounds of the whole window.

I worked on a fix which changes the node below, which uses ImGui::Separator, Slider, and TextWrapped

from this:

image

to this:

image

You can find details on how I did it here: https://github.com/pthom/imgui-node-editor/commit/44ee0e6dbf644e46b4406624aa44ad9e5d85fac1

This implementation is not meant to be final, as it is implemented mainly as a workaround inside Dear ImGui Bundle. But it might be a source of inspiration. Please ping me if you are interested.

I studied a solution to fix: we have to fix several elements in the current window data:

pthom commented 1 week ago

Here is the test code I used:

#include "imgui-node-editor/imgui_node_editor.h"
#include "imgui_internal.h"

// Specific to ImGui Bundle (replace this by another runner if desired)
#include "imgui_md_wrapper.h"
#include "immapp/immapp.h"

namespace ed = ax::NodeEditor;

int main()
{
   // Specific to ImGui Bundle (replace this by another runner if desired)
    HelloImGui::RunnerParams runnerParams;

    runnerParams.callbacks.ShowGui = [&]()
    {
       // This whole function is using only ImGui and ImGui Node editor
        ed::Begin("My Editor");

        ed::BeginNode(1);

        // Test ImGui::Separator: it should use the actual node width.
        ImGui::TextWrapped("Below is a separator and a separator text. They should use the actual node width.");
        ImGui::Separator();
        ImGui::SeparatorText("Hello");

        //
        // A dummy button, to artificially set the node width
        //
        static ImVec2 dummyButtonSize(100, 20);
        ImGui::SeparatorText("Dummy Button");
        ImGui::TextWrapped(R"(
This is a dummy button, to artificially set the node width.
Below it is a fixed width slider, which enables to set this button's width.
)");
        ImGui::Button("Dummy", dummyButtonSize);
        // With a fixed width slider, so that we can set the node width.
        ImGui::SetNextItemWidth(200.f);
        ImGui::SliderFloat("width", &dummyButtonSize.x, 0, 700);

        //
        // Test ImGui::TextWrapped: it should use the actual node width.
        //
        // Notes:
        // * If using the slider to make the node wider, the wrapped text with will adapt.
        // * After that if you try to reduce the node width, The wrapped text with will not reduce
        //   (This is because the node caches its previous size, and the wrapped text will use it.
        //   This is okay.)
        ImGui::SeparatorText("Test TextWrapped");
        ImGui::TextWrapped(R"(
Note:
    * If using the slider to make the node wider, the wrapped text with will adapt.
    * After that if you try to reduce the node width, The wrapped text with will not reduce (This is because the node caches its previous size, and the wrapped text will use it. This is okay.)
)");

        //
        // Test ImGui::SliderFloat: it should use the actual node width.
        //
        ImGui::SeparatorText("Slider with default width");
        ImGui::TextWrapped("Below is a slider using the default width. It should be the same width as the node (There is a hard code max label size, which corresponds to 4 wide characters)." );
        ImGui::TextWrapped("Move this slider to see the node width change." );
        ImGui::SliderFloat("width##2", &dummyButtonSize.x, 0, 700);

        ed::EndNode();

        ed::End();

    };

    // Specific to ImGui Bundle (replace this by another runner if desired)
    ImmApp::AddOnsParams addOnsParams;
    addOnsParams.withNodeEditor = true;

    // Change the node editor config to force ImGui to use the node width.
    addOnsParams.withNodeEditorConfig = ed::Config();
    addOnsParams.withNodeEditorConfig->ForceWindowContentWidthToNodeWidth = true;

    addOnsParams.withMarkdown = true;

    ImmApp::Run(runnerParams, addOnsParams);
}