imgui-node-editor icon indicating copy to clipboard operation
imgui-node-editor copied to clipboard

ImGui::ColorEdit4 popups don't work inside a node

Open brunopj1 opened this issue 2 years ago • 10 comments

I have a node that has an ImGui::ColorEdit4 inside its body.

The number input fields work normally, but the tooltip, color picker and right click option popups don't work. They get positioned in the wrong place and have weird interactions with the mouse.

I know that in order to make the popups work, I should suspend the editor before rendering them, but these popups are handled inside the ImGui::ColorEdit4 function, and I can't call this outside the node.

Is there any way to make these popups work?

brunopj1 avatar Jul 07 '23 14:07 brunopj1

You can have bool openPopup and do something like this:

inside of the node's body

openPopup = ImGui::Button("OpenPopup");

outside of the node's body

ed::Suspend();
if(openPopup) {
    ImGui::OpenPopup("picker");
}
ed::Resume();

ed::Suspend();
if(ImGui::BeginPopup("picker")) {

//...

ImGui::EndPopup();
}
ed::Resume();

SC5Shout avatar Jul 17 '23 20:07 SC5Shout

The same thing has to be done for combo widgets. It starts being annoying. And for the combo popups, I don't think it works. The popup window position is weird, probably because I've done something wrong. @thedmd any idea how to bypass it?

SC5Shout avatar Jul 19 '23 13:07 SC5Shout

To "fix" this properly ImGui modification is needed right now. I did it by adding 2 new ImGui hooks: ImGuiContextHookType_BeginWindow, ImGuiContextHookType_EndWindow that are called on start of ImGui::Begin and end of ImGui::End

bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
...
    CallContextHooks(&g, ImGuiContextHookType_BeginWindow);
 ...
 }
bool ImGui::End()
{
...
    CallContextHooks(&g, ImGuiContextHookType_EndWindow);
...
}

and registering/unregistering them in ImGuiEx::Canvas::Begin/End

bool ImGuiEx::Canvas::Begin(ImGuiID id, const ImVec2& size)
{
...
    auto beginWindowHook = ImGuiContextHook{};
    beginWindowHook.UserData = this;
    beginWindowHook.Type = ImGuiContextHookType_BeginWindow;
    beginWindowHook.Callback = []( ImGuiContext * context, ImGuiContextHook * hook )
    {
        //ImGui::SetNextWindowViewport( ImGui::GetCurrentWindow()->Viewport->ID );

        auto canvas = reinterpret_cast< Canvas * >( hook->UserData );
        if ( canvas->m_SuspendCounter == 0 )
        {
            if ( ( context->NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos ) != 0 )
            {
                auto pos = canvas->FromLocal( context->NextWindowData.PosVal );
                ImGui::SetNextWindowPos( pos, context->NextWindowData.PosCond, context->NextWindowData.PosPivotVal );
            }

            if ( context->BeginPopupStack.size() )
            {
                auto & popup = context->BeginPopupStack.back();
                popup.OpenPopupPos = canvas->FromLocal( popup.OpenPopupPos );
                popup.OpenMousePos = canvas->FromLocal( popup.OpenMousePos );
            }

            if ( context->OpenPopupStack.size() )
            {
                auto & popup = context->OpenPopupStack.back();
                popup.OpenPopupPos = canvas->FromLocal( popup.OpenPopupPos );
                popup.OpenMousePos = canvas->FromLocal( popup.OpenMousePos );
            }

        }
        canvas->m_BeginWindowCursorBackup = ImGui::GetCursorScreenPos();
        canvas->Suspend();
    };

    m_beginWindowHook = ImGui::AddContextHook( ImGui::GetCurrentContext(), &beginWindowHook );

    auto endWindowHook = ImGuiContextHook{};
    endWindowHook.UserData = this;
    endWindowHook.Type = ImGuiContextHookType_EndWindow;
    endWindowHook.Callback = []( ImGuiContext * ctx, ImGuiContextHook * hook )
    {
        auto canvas = reinterpret_cast< Canvas * >( hook->UserData );
        canvas->Resume();
        ImGui::SetCursorScreenPos( canvas->m_BeginWindowCursorBackup );
        ImGui::GetCurrentWindow()->DC.IsSetPos = false;
    };

    m_endWindowHook = ImGui::AddContextHook( ImGui::GetCurrentContext(), &endWindowHook );

    return true;
}

void ImGuiEx::Canvas::End()
{
...
    m_InBeginEnd = false;

    ImGui::RemoveContextHook( ImGui::GetCurrentContext(), m_beginWindowHook );
    ImGui::RemoveContextHook( ImGui::GetCurrentContext(), m_endWindowHook );
}

Now tooltips and other spawned windows withing Canvas context work semi properly

image

lukaasm avatar Aug 17 '23 07:08 lukaasm

I can confirm the above fixes the issue, would love to see this merged somehow

lapinozz avatar Jul 04 '24 19:07 lapinozz

What can I say. Idea of using hooks will do the trick. I will look into that. This might solve whole bunch of issues. And if child windows will be taken into account maybe all related issues could be resolved.

thedmd avatar Jul 05 '24 10:07 thedmd