ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.96k stars 9.93k forks source link

Dock window on first open #4829

Open caxapexac opened 2 years ago

caxapexac commented 2 years ago

Version/Branch of Dear ImGui:

Version: 1.86 Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: webGL Compiler: em++ Operating System: V8

My Issue/Question:

DockBuilder: https://github.com/ocornut/imgui/issues/2109#issuecomment-426204357 ImGuiCond: https://github.com/ocornut/imgui/issues/2554#issuecomment-492253636

How to use it together?

Example: I have button 'open window_X' which sets window_X flag to true I need to have window_X docked at the right side of my root docking space and use 20% of screen if it was opened for the first time Just like ImGuiCond_FirstUseEver

So in my mind it will be:

ImGuiID window_X_id = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.10f, NULL, &dock_main_id, ImGuiCond_FirstUseEver);
ImGui::DockBuilderDockWindow("Window_X", window_X_id , ImGuiCond_FirstUseEver);

or something like this

Are there any workarounds?

MStachowicz commented 3 months ago

Hey @ocornut, I managed to implement a solution to this problem. I manually construct my dock nodes as such (ImGui v 1.89.5):

ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();

// At the start of an ImGui frame, push a window the size of viewport to allow docking other ImGui windows to.
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowViewport(viewport->ID);

ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));

auto imgui_window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar
    | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove
    | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus;

ImGui::Begin("root_dock", nullptr, imgui_window_flags);
ImGui::PopStyleVar(3);

ImGuiID dockspace_id = ImGui::GetID("root_dock");
ImGui::DockSpace(dockspace_id, ImVec2(0.f, 0.f), ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_NoDockingInCentralNode);

static bool first_time = true;
if (first_time)
{
    first_time = false;
    ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_AutoHideTabBar;

    ImGui::DockBuilderRemoveNode(dockspace_id); // clear any previous layout
    ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace);
    ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);

    // Split the dockspace into 2 nodes -- DockBuilderSplitNode takes in the following args in the following order
    ImGuiID dock_id_left, dock_id_right;
    ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.2f, &dock_id_left, &dock_id_right);
    LOG("dock_id_left: {} dock_id_right: {}", dock_id_left, dock_id_right);
    ImGuiID dock_id_down, dock_id_up;
    ImGui::DockBuilderSplitNode(dock_id_right, ImGuiDir_Down, 0.15f, &dock_id_down, &dock_id_up);
    LOG("dock_id_down: {} dock_id_up: {}", dock_id_down, dock_id_up);

    ImGui::DockBuilderFinish(dock_id_up);
}

dock_id_left is set to 1, further along I create a window as such, asking it to dock to the left node from above on first use:

ImGui::SetNextWindowDockID(1, ImGuiCond_FirstUseEver);

if (ImGui::Begin("Entities", &m_windows_to_display.Entity))
{
    ...
}

This works perfectly on first run. On second run, the saved window DockId is reset and the window is floating using the exact size and pos of the original dock node 1.

Any ideas why the saved .ini DockId=0x00000001,0 for [Window][Entities] is reset on second launch?

FYI if I dont set a condition and force the DockId every run, it is correctly docked on launch evert time:

ImGui::SetNextWindowDockID(1, 0);
MStachowicz commented 3 months ago

UPDATE By using: ImGui::SetNextWindowDockID(1, ImGuiCond_Once);

I am able to have the windows dock correctly on first run AND on successive runs they are not undocked and hovering with the same pos and size as above. This does mean that every single launch the layout is reset for the windows since this doesn't match the ImGuiCond_FirstUseEver functionality I'm looking for but it feels less buggy so will go with this for now.

(ImGui v 1.89.5)