Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hitting: IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode()); #3340

Closed
gmagno opened this issue Jul 6, 2020 · 4 comments
Labels

Comments

@gmagno
Copy link

gmagno commented Jul 6, 2020

Hello,

This is a crosspost from a message in discord.

Version/Branch of Dear ImGui:

Version: 4f5aac3
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Operating System: Arch Linux 5.6.19.a-1-hardened #1 SMP PREEMPT Sat, 20 Jun 2020 15:16:50 +0000 x86_64 GNU/Linux

My Issue/Question:

I'm hitting an IM_ASSERT when doing the following:

assert

Am I doing something wrong? Is this an known issue? The IM_ASSERT is preceded by a FIXME-DOCK comment:

    // FIXME-DOCK: When we are trying to dock an existing single-window node into a loose window, transfer Node ID as well
    // When processing an interactive split, usually LastFrameAlive will be < g.FrameCount. But DockBuilder operations can make it ==.
    if (node)
        IM_ASSERT(node->LastFrameAlive <= g.FrameCount);
    if (node && target_window && node == target_window->DockNodeAsHost)
        IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode());  // <------

Standalone, minimal, complete and verifiable example:

// Some code to reproduce the issue
void DockSpace(bool *p_open)
{
    static int initialized = 1;

    static bool opt_fullscreen_persistant = true;
    bool opt_fullscreen = opt_fullscreen_persistant;
    static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
    dockspace_flags |= ImGuiDockNodeFlags_PassthruCentralNode;
    // dockspace_flags |= ImGuiDockNodeFlags_AutoHideTabBar;

    // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
    // because it would be confusing to have two docking targets within each others.
    ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;
    if (opt_fullscreen)
    {
        ImGuiViewport *viewport = ImGui::GetMainViewport();
        ImGui::SetNextWindowPos(viewport->GetWorkPos());
        ImGui::SetNextWindowSize(viewport->GetWorkSize());
        ImGui::SetNextWindowViewport(viewport->ID);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
        window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
        window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
        window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
    }

    // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
    // and handle the pass-thru hole, so we ask Begin() to not render a background.
    if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
        window_flags |= ImGuiWindowFlags_NoBackground;

    // Important: note that we proceed even if Begin() returns false (aka window is collapsed).
    // This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
    // all active windows docked into it will lose their parent and become undocked.
    // We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
    // any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
    ImGui::Begin("DockSpace", p_open, window_flags);

    ImGui::PopStyleVar();

    if (opt_fullscreen)
        ImGui::PopStyleVar(2);

    // DockSpace
    ImGuiIO &io = ImGui::GetIO();
    ImGuiID dockspace_id = 0;
    if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
    {
        dockspace_id = ImGui::GetID("MyDockSpace");

        if (initialized == 1)
        {
            initialized = 2;
            ImGuiContext *ctx = ImGui::GetCurrentContext();
            ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
            ImGui::DockBuilderAddNode(dockspace_id);    // Add empty node

            ImGuiID dock_main_id = dockspace_id; // This variable will track the document node, however we are not using it here as we aren't docking anything into it.
            ImGuiID dock_id_left = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.20f, NULL, &dock_main_id);
            ImGuiID dock_id_bottom = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, 0.20f, NULL, &dock_main_id);

            ImGui::DockBuilderDockWindow("Center", dock_main_id);
            ImGui::DockBuilderDockWindow("Left", dock_id_left);
            ImGui::DockBuilderDockWindow("Bottom", dock_id_bottom);
            ImGui::DockBuilderFinish(dockspace_id);
        }

        ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);

        if (initialized == 2)
        {
            ImGui::Begin("Center");
            ImGui::End();

            ImGui::Begin("Left");
            ImGui::End();

            ImGui::Begin("Bottom");
            ImGui::End();
        }
    }
    else
    {
        ShowDockingDisabledMessage();
    }

    ImGui::End();

}
@ocornut
Copy link
Owner

ocornut commented Jul 10, 2020

Thank you @gmagno for your report, I started looking into it.

@ocornut
Copy link
Owner

ocornut commented Jul 10, 2020

Am I doing something wrong?

The issue if you are creating a floating node if you call DockBuilderAddNode() without the ImGuiDockNodeFlags_DockSpace flag.

// - To create a DockSpace() node, make sure to set the ImGuiDockNodeFlags_DockSpace flag when calling DockBuilderAddNode().
//   You can create dockspace nodes (attached to a window) _or_ floating nodes (carry its own window) with this API.

An empty DockSpace has a node tagged "Central node" which keeps existing when it has no window, so any empty dockspace is generally a single "central node". Whereas floating node (e.g. when merging two floating windows) will cease to exist when the windows are undocked from it.

In this case it's a contradiction to create the node without the ImGuiDockNodeFlags_DockSpace flag and then calling DockSpace, but for various subtle reasons it's not easy at the moment to report a clear error. Going to investigate ways the error handling could be improved here.

@ocornut ocornut removed the bug label Jul 10, 2020
@gmagno
Copy link
Author

gmagno commented Jul 10, 2020

That fixed it. Many thanks for the quick reply.
I am taking the liberty of closing this issue.

@gmagno gmagno closed this as completed Jul 10, 2020
ocornut added a commit that referenced this issue Jul 10, 2020
@ocornut
Copy link
Owner

ocornut commented Jul 10, 2020

I pushed cbade7b which I think should help against this.
I think down the line we need to redesign the concept of _CentralNode as it currently has too many holes.

Mernion pushed a commit to Mernion/imgui that referenced this issue Aug 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants