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

Having trouble understanding how to pre-dock windows. #5778

Open
antrwells opened this issue Oct 15, 2022 · 7 comments
Open

Having trouble understanding how to pre-dock windows. #5778

antrwells opened this issue Oct 15, 2022 · 7 comments
Labels

Comments

@antrwells
Copy link

Hi,

I am writing an app in C++, and I can't seem to understand how to pre-dock windows. I can drag and dock just fine, but that's all.

Here is a small bit of code,

ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());

which enables docking. I can drag and drop any of my windows properly. But I can't figure out how to make them docked at first. My windows code is quite simple.

`if (!mSGF) {

	ImGui::SetNextWindowPos(mSceneGraphPos);
	ImGui::SetNextWindowSize(mSceneGraphSize);
	mSGF = true;
	ImGui::SetNextWindowDockID(ImGui::GetWindowDockID(), ImGuiDir_Right);
}




ImGui::Begin("Scene Graph", &mSceneGraphOpen, ImGuiWindowFlags_MenuBar);
`

Can you point me to an example of how to achieve this?

@antrwells
Copy link
Author

Btw, by predocking, I mean docking the scene graph to the left, the content to the bottom, the editor to the right, and the viewport to central node. I've been searching for hours, but to no avail.

@ocornut
Copy link
Owner

ocornut commented Oct 15, 2022

In pseudo code you tried to write should look more like:

ImGuiID my_dockspace = ImGui::DockspaceOverViewport(…);
…
ImGui::SetNextWindowDockID(my_dockspace, ImGuiCond_Once);

(GetWindowDockID() gets the dock node id of the current window which is undefined in your snippet (and likely is the implicit/hidden “Debug” window))

However that api doesn’t allow any form of splitting.
There is a wip DockBuilderXXX api in imgui_internal.h for that.

@ocornut
Copy link
Owner

ocornut commented Oct 15, 2022

Also you shouldn’t call SetNextWindowPos/Size along with SetNextWindowDockID(), the earlier two will undock the window.

@JerryYan97
Copy link

JerryYan97 commented Oct 17, 2022

Hi, it looks like I am also facing a similar problem with predocking/initial docking. With the code below, it looks like the text in the window cannot be rendered out.

...
ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::DockBuilderRemoveNodeChildNodes(dockspace_id); // clear any previous layout
ImGuiID dock_id_left, dock_id_right;
        
ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.5f, &dock_id_left, &dock_id_right);

ImGui::Begin("Window_1", &open, 0);
ImGui::Text("Text 1");
ImGui::End();

ImGui::Begin("Window_2", &open, 0);
ImGui::Text("Text 2");
ImGui::End();

ImGui::DockBuilderDockWindow("Window_1", dock_id_left);
ImGui::DockBuilderDockWindow("Window_2", dock_id_right);

ImGui::DockBuilderFinish(dockspace_id);
...

image

Please let me know if there is anything wrong with my code/usage. I have spent quite a bit of my time on reading previous issues relating to create such a window but it looks like they are too old for the API now.😄
It would also be helpful if you can point me to some up-to-dated examples with such functionalities. (I believe the current docking example in the imgui_demo doesn't have such demonstration for splitting)

@JerryYan97
Copy link

JerryYan97 commented Oct 18, 2022

Hi, sorry for bothering. It looks like this issue maybe helpful: #4033

In general, the strategy here can be different. Instead of using the BuildDockSplit(), we can just use the .ini format to do the pre-docking. This .ini can be created manually beforehand.

E.g. This works for me:

const char myLayout[] = 
"[Window][DockSpaceViewport_11111111]\n\
Pos=0,0\n\
Size=1280,640\n\
Collapsed=0\n\
\n\
[Window][Debug##Default]\n\
Pos=60,60\n\
Size=400,400\n\
Collapsed=0\n\
\n\
[Window][Window 1]\n\
Pos=0,0\n\
Size=637,640\n\
Collapsed=0\n\
DockId=0x00000001,0\n\
\n\
[Window][Window 2]\n\
Pos=639,0\n\
Size=641,640\n\
Collapsed=0\n\
DockId=0x00000002,0\n\
\n\
DockSpace   ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,0 Size=1280,640 Split=X Selected=0x82C5531C\n\
  DockNode  ID = 0x00000001 Parent = 0x8B93E3BD SizeRef = 637, 640 Selected = 0xC56529CC\n\
  DockNode  ID = 0x00000002 Parent = 0x8B93E3BD SizeRef = 641, 640 CentralNode = 1 Selected = 0x82C5531C";

...

ImGui::LoadIniSettingsFromMemory(myLayout);

...

ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();

...

Hopefully this can be helpful.
Besides, I am thinking this maybe worth to be mentioned in the docking Wiki because this functionality is really attractive to docking users and it would take people some time to figure this out if people are relatively new to the Dear ImGUI.

Btw, the .ini file is automatically generated by default by the Dear ImGUI.

@ocornut
Copy link
Owner

ocornut commented Oct 18, 2022

Please let me know if there is anything wrong with my code/usage.

ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::DockBuilderRemoveNodeChildNodes(dockspace_id); // clear any previous layout

You are killing and recreating the docking setup every frame, preventing any interactions with the docking system.
You need to create layout once e.g. on init.
Basically you can use e.g. DockBuilderGetNode(id) and only create layout if this doesn't exist.

I don't think you can use DockSpaceOverViewport() because it doesn't allow you to get the dockspace ID BEFORE creating.
So instead

  • Create a full-viewport window (like DockSpaceOverViewport() does)
  • Get your dockspace id.
  • If DockBuilderGetNode(dockspace_id) == NULL then you can create the layout and map window.

Hopefully this can be helpful.
Besides, I am thinking this maybe worth to be mentioned in the docking Wiki because this functionality is really attractive to docking users and it would take people some time to figure this out if people are relatively new to the Dear ImGUI.

I disagree. This is a XY Solution and dead-end, people are misunderstanding and underestimating the details of what it means to have a long term persist layout. Even I haven't cracked the correct model for it (may need to put an emphase on linking new window to an existing window instead of a node, so occasional windows don't have to be setup ahead of time).
Please use the dock builder and I simultaneously agree the API needs to be reworked and improved.

@lambwheit
Copy link

lambwheit commented Apr 19, 2023

Hi, i don't know if you still need this but here is working code that solves your issue, you only have to init the nodes once

...
    ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
    static bool init = true;
    ImGuiID dock_id_left, dock_id_right;
    if (init) {
        init = false;
        ImGui::DockBuilderRemoveNode(dockspace_id);
        ImGui::DockBuilderAddNode(dockspace_id);
        ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size);

    	ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.5f, &dock_id_left, &dock_id_right);
        ImGui::DockBuilderDockWindow("Window_1", dock_id_left);
        ImGui::DockBuilderDockWindow("Window_2", dock_id_right);

        ImGui::DockBuilderFinish(dockspace_id);
    }
    ImGui::Begin("Window_1");
    ImGui::Text("Text 1");
    ImGui::End();
    ImGui::Begin("Window_2");
    ImGui::Text("Text 2");
    ImGui::End();
...

image

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

4 participants