Open ocornut opened 6 years ago
@damqui
for some usage, I needed to programmatically be able to make a tabbed window selected. I didn't find something in the API to do this.
As discussed off-line: if you want to select the tab and make the window focused, you can use SetWindowFocus(const char* name)
. Docked windows are trying to behave the same as normal windows so this should work just as well.
If you are trying to select the tab in its current tab bar (to make it visible) but without taking focus, your function above SetTabbedWindowSelected()
will be useful and we could introduce the feature eventually.
Hi, another tab/docking related question :
In our editor app, we have various ui areas (corresponding to docknodes) (ex : one on the left for file broswer or other game module uis, one on the bottom for log, etc).
In our previous (non-imgui) app, we had hotkeys to hide/show those areas (ex : to switch between "fullscreen view" and "windowed view") : not closing the windows, but just hiding/showing the areas. How to implement this behaviour ?
I know I can close all windows on the "fullscreen view" command, and it will make docknode disappear (hide), but if I want to open those windows again on the "Editor view" command, I have to keep track of what was closed "in order to hide the area" and what was closed "because the user wanted".
To summarize : is there a way of "hiding" a docknode without closing all its docked windows ?
Thanks !
I know I can close all windows on the "fullscreen view" command, and it will make docknode disappear (hide), but if I want to open those windows again on the "Editor view" command, I have to keep track of what was closed "in order to hide the area" and what was closed "because the user wanted". To summarize : is there a way of "hiding" a docknode without closing all its docked windows ?
Not really. There is a ImGuiDockNodeFlags_KeepAliveOnly
flag to Dockspace() that doesn't display the dockspace without detaching any window docked into it (so they'll be hidden if submitted) however that wouldn't solve your issue if any of your windows are NOT docked into this dockspace (e.g. if they are loose floating windows).
In fact, once you consider the possibility that you have any floating window, your problem is not a docking-specific problem at all.
I have to keep track of what was closed "in order to hide the area" and what was closed "because the user wanted".
That should be trivial, e.g. have a global bool show_tools
flag and test this flag before testing the per-window visibility flag..
if (show_tools && show_browser_tool) ImGui::Begin("Browser", &show_browser_tool) ...
The global hotkey will toggle show_tools
and closing a window manually will close the window specific flag.. This should be non-problem AFAIK..
well yes, that's so simple.. ! thanks ! (and sorry)
One problem you will run into with this approach is that you will lose the relative z-order of floating windows compared to each others. If this is important to you please open a separate issue. When using Docking it is less of an issue because most of your windows will be docked anyway.
Hi Omar, really enjoying the docking feature!
I ran into a problem with using the animated title bars (###) which we use for translating window titles. Changing the display text part appears to have randomish behavior:
To be clear: Using stock imgui, calling Begin() with "Object Properties###somedeterministicid" one frame and "Translated###somedeterministicid" the next
It appears to only update the title bar if a window is docked into the same space as it
@eclbtownsend I pushed a fix for it! Next time please provide a helper repro to save me time. Here's a repro:
static bool toggle = false;
if (ImGui::IsMouseClicked(2))
toggle = !toggle;
ImGui::Begin(toggle ? "Object Properties###somedeterministicid" : "Translated###somedeterministicid");
ImGui::Text(toggle ? "Object Properties###somedeterministicid" : "Translated###somedeterministicid");
ImGui::End();
The bug would happen on leaf node with a single window (there's a small side-effect/bug in DockNodeUpdate which resets window->DockIsActive, I've added a comment about it too).
Thank you! WIll provide repros going forward ^^
Quick bug report: modal windows should have docking disabled (IMO). At this point the controls were unresponsive and had to restart the app :D
PS: sorry if it has been posted elsewhere already
@r-lyeh
Quick bug report: modal windows should have docking disabled (IMO).
Correct, nice catch! Fixed in 33994bbf.
@rokups I forgot to reply to the (older) code you posted in https://github.com/ocornut/imgui/issues/2109#issuecomment-426539279. The reason it is wrong is that you are trying to dock into the root node which has already been split. That's illegal.
Awesome! The docking works very well, but I'm having issues wrapping my head around how to correctly define a docking layout by code. I've picked up some stuff from this thread and tried to figure something out, but I've failed :(
Would be nice if I could get a tip or two :) So, this my function doing all the stuff:
void pms::ProgramManager::drawTestDock()
{
bool open = true;
if (ImGui::DockBuilderGetNode(ImGui::GetID("MyDockspace")) == NULL)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
ImGui::DockBuilderAddNode(dockspace_id, viewport->Size); // 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_top = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, 0.80f, NULL, &dock_main_id);
ImGuiID dock_id_right = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 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("James_1", dock_id_left);
ImGui::DockBuilderDockWindow("James_2", dock_id_top);
ImGui::DockBuilderDockWindow("James_3", dock_id_right);
ImGui::DockBuilderDockWindow("James_4", dock_id_bottom);
ImGui::DockBuilderFinish(dockspace_id);
}
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", &open, window_flags);
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
ImGui::PushStyleColor(ImGuiCol_DockingEmptyBg, sf::Color::Red);
ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), 0);
ImGui::PopStyleColor();
ImGui::End();
ImGui::Begin("James_1", &open, 0);
ImGui::Text("Text 1");
ImGui::End();
ImGui::Begin("James_2", &open, 0);
ImGui::Text("Text 2");
ImGui::End();
ImGui::Begin("James_3", &open, 0);
ImGui::Text("Text 3");
ImGui::End();
ImGui::Begin("James_4", &open, 0);
ImGui::Text("Text 4");
ImGui::End();
}
Of course there is something off with the code above, I just cannot figure out what :(
This is what I get (All the "forms" are in the upper left corner):
This is what I want to achieve:
Any help would be greatly appreciated :)
When you configure the dockspace layout, you still haven't created your window "DockSpace Demo", so you configure a dockspace "MyDockspace" out of the window, not your dockspace "MyDockspace" inside the window.
This should work:
void pms::ProgramManager::drawTestDock()
{
bool open = true;
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", &open, window_flags);
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
if (ImGui::DockBuilderGetNode(ImGui::GetID("MyDockspace")) == NULL)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
ImGui::DockBuilderAddNode(dockspace_id, viewport->Size); // 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_right = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 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("James_1", dock_id_left);
ImGui::DockBuilderDockWindow("James_2", dock_main_id);
ImGui::DockBuilderDockWindow("James_3", dock_id_right);
ImGui::DockBuilderDockWindow("James_4", dock_id_bottom);
ImGui::DockBuilderFinish(dockspace_id);
}
ImGui::PushStyleColor(ImGuiCol_DockingEmptyBg, sf::Color::Red);
ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), 0);
ImGui::PopStyleColor();
ImGui::End();
ImGui::Begin("James_1", &open, 0);
ImGui::Text("Text 1");
ImGui::End();
ImGui::Begin("James_2", &open, 0);
ImGui::Text("Text 2");
ImGui::End();
ImGui::Begin("James_3", &open, 0);
ImGui::Text("Text 3");
ImGui::End();
ImGui::Begin("James_4", &open, 0);
ImGui::Text("Text 4");
ImGui::End();
}
Moved the conditional dockspace configuration after the window begin and also slightly modified the dockspace config block so there is no empty docking space as on your picture.
@pinam45 : Thank you very much! Worked like a charm! :smile:
I was giving imgui some stress test (sorry! :) with most of widgets in the Wiki, and found that the plot widgets from the main imgui demo have lost their avail width after some heaving docking. The plot widgets seem to stick to a very thin width for some reason (check region at top-right-center image):
Ideas?
PS: Other than that the docking branch seems good to go! Congrats :D
After upgrading to the docking branch, window settings don't seem to save to the ini file anymore. Any ideas?
The file only seems to contain one line:
[Docking][Data]
How to use this to make a spliter view? That is disable user to change the docking layout, and disable showing the top tab bar.
And I think ImGuiWindowFlags_NoDocking
should split to ImGuiWindowFlags_NoDockingToAnother
and ImGuiWindowFlags_NoBeingDocked
Two bugs:
Assertion failed: draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w, file imgui_draw.cpp, line 420
edit: highlighted overlap conflicts.
@codecat
After upgrading to the docking branch, window settings don't seem to save to the ini file anymore. Any ideas?
Do some debugger stepping in SaveIniSettingsToMemory()
to find what's wrong. I suspect you might be doing something fishy either with the context either with settings.
@r-lyeh
The plot widgets seem to stick to a very thin width for some reason (check region at top-right-center image):
How are the other widgets? That doesn't seem to be a plot widget issue but we cannot see the other widgets in your screenshot.
The imgui_demo.cpp code does:
ImGui::PushItemWidth(ImGui::GetFontSize() * -12)
Which depending on your font may remove more or less space (we should probably have some sort of font helper to retrieve the width of "M" or average width of characters?).
Tweak a color widget on the right side of the screen, so the popup appears like a native/floating window. Then close the app (while the popup is being displayed). Next time you open the app it will crash.
I can't seem to repro this. Do you have a callstack and can you try to make a repro?
Window contents are overlapping docked tab regions sometimes (see 1st and 2nd images). It is not a problem until the overlapping area contains a menu which causes logic hovering to malfunction (see 2nd image). Note: no rendering/logic problems when viewed as regular windows.
Would also need a repro (probably relate to your style setting).
Ok, looks like it's only saving if the docking flag is set: (I suppose that's intentional for now?)
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
return;
@ocornut ah good catches!
PS: (*) I will edit this post when i recap some more info.
Edit: 2. The problem is: tab caption font face does not match content font face actually, but regular window captions do. Ie, hexeditor & texteditor use the monospaced font, all the other windows use a variable width font. See attached pic. Tab caption is variable width and tab content is monospaced, as opposed to regular windows which use same font uniformly and got aligned. Increasing FramePadding.Y fixes the issue for now.
// repro: configure a very large font at slot #0 then:
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]);
static MemoryEditor mem_edit_1;
char *mem_block = "oh lala"; size_t mem_block_size = strlen(mem_block) + 1;
mem_edit_1.DrawWindow("Memory Editor", mem_block, mem_block_size, 0x0000);
ImGui::PopFont();
@r-lyeh FWIW, "M" is a typographical standard for layout calculations - https://en.wikipedia.org/wiki/Em_(typography)
@codecat
Ok, looks like it's only saving if the docking flag is set: (I suppose that's intentional for now?)
That's totally a bug, this test was added in the wrong function. Fixed now.
@r-lyeh
It is a little tricky but at the moment Docking doesn't allow altering per-window title bar style. The docking nodes are processed in NewFrame()
or DockSpace()
. This specific bug is a little curious but it won't work either way: what would happen if you dock two windows with different title font with each others? It's an open problem.
@heroboy
How to use this to make a spliter view? That is disable user to change the docking layout, and disable showing the top tab bar. And I think ImGuiWindowFlags_NoDocking should split to ImGuiWindowFlags_NoDockingToAnother and ImGuiWindowFlags_NoBeingDocked
It's not possible at the moment but I would like to allow it.
It wouldn't use the ImGuiWindowFlags_NoDocking
flag, rather then dockspace itself would have something eg. ImGuiDockFlags_Locked
so you can't change it's layout, and the window would be docked programmatically at the spot you want.
It's not possible at the moment but I would like to allow it. It wouldn't use the
ImGuiWindowFlags_NoDocking
flag, rather then dockspace itself would have something eg.ImGuiDockFlags_Locked
so you can't change it's layout, and the window would be docked programmatically at the spot you want.
This sounds great! Any idea on the timeframe or priority of this feature compared to everything else?
Awesome, very easy to use. but it sames modal popup window is not top most when ImGuiConfigFlags_ViewportsNoMerge flag has been set.
More feedback,
I am trying to create a dockable toolbar (by creating a window with NoTitlebar flag), however, the toolbar titlebar is always visible no matter what flags I set up. I understand this is a design decision, since the titlebar is needed to drag the docked tabs, but... if we can move regular windows by dragging their contents, why dont we allow to move tabs by dragging contents as well !? :)
PS: maybe to keep things compatible as they currently are we might: 1) If NoTitlebar is set, allow user to move tabs by dragging content only. 2) If NoTitlebar is unset, allow user to move tabs by dragging titlebars only.
It would be a good idea to add a button to hide the tab bar when there is only 1 tab in it, like in the unreal engine editor
On Tue, Nov 6, 2018 at 11:52 PM r-lyeh notifications@github.com wrote:
More feedback,
I am trying to create a dockable toolbar (by creating a window with NoTitlebar flag), however, the toolbar titlebar is always visible no matter what flags I set up. I understand this is a design decision, since the titlebar is needed to move the docked tabs, but... if we can move windows by dragging their contents, why dont we allow to drag contents to move tabs as well !? :)
[image: image] https://user-images.githubusercontent.com/35402248/48065303-9a1c7600-e1ca-11e8-8f61-8ce763cf46f0.png
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ocornut/imgui/issues/2109#issuecomment-436241650, or mute the thread https://github.com/notifications/unsubscribe-auth/AGQa7Qsx7qN0uHH5_t5elnY2-qYCNhniks5usYXvgaJpZM4XCbmM .
For reference, this is what UE4 does:
(upper: the yellow triangle is clickable and expands to bottom image; bottom: the titlebar is right-clickable and then you can click on "hide tab" to show upper image)
Thanks
On Wed, Nov 7, 2018 at 10:25 PM r-lyeh notifications@github.com wrote:
For reference, this is what UE4 does:
[image: image] https://user-images.githubusercontent.com/35402248/48128809-ea0d4280-e287-11e8-9ce8-0f274d048ada.png
(upper: the yellow triangle is clickable and expands to bottom image; bottom: the titlebar is right-clickable and then you can click on "hide tab" to show upper image)
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ocornut/imgui/issues/2109#issuecomment-436592778, or mute the thread https://github.com/notifications/unsubscribe-auth/AGQa7UaIlxYBxJkOuH0WHc_ICU9_hJDpks5ussMlgaJpZM4XCbmM .
I've just implemented this in an older project and I love it! I have hit a small issue and hopefully there's something basic I'm missing?
I'm trying to save various preset layouts to disk as .ini files and load them back at run time to change the dock layout dynamically. To do this, I'm just saving the imgui.ini file as normal and copying it/creating duplicates. All good - at first run, when the default ini is loaded, dock layouts are loaded correctly and as expected.
However calling ImGui::LoadIniSettingsFromDisk(/ini file/) will place my windows correctly but undock every window. Is there anything extra that needs to be called at this time? I threw together a bare bones test as I wanted to remove any exotic things I may have been doing otherwise to sanity check.
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::Begin("DockSpace Demo", &open, window_flags);
ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), 0);
ImGui::End();
ImGui::Begin("Win_1", &open, 0);
ImGui::Text("Text 1");
if (ImGui::Button("Load")) {
ImGui::LoadIniSettingsFromDisk(/*valid file path to a copy of a known working imgui.ini*/);
}
ImGui::End();
ImGui::Begin("Win_2", &open, 0);
ImGui::Text("Text 2");
ImGui::End();
ImGui::Begin("Win_3", &open, 0);
ImGui::Text("Text 3");
ImGui::End();
ImGui::Begin("Win_4", &open, 0);
ImGui::Text("Text 4");
ImGui::End();
From the LoadIniSettingsFrom*
documentation: call after CreateContext() and before the first call to NewFrame()
seems to imply that what you are trying to achieve cannot be done atm.
ah, my bad. I missed that when looking through. Thanks for the reply
Just a question, but is it possible to "restrict" which docks windows can be attached to? Dumb example: Say I want to restrict a few different windows to only being dock-able on the top or the bottom, not the sides.
@moonheart08
Just a question, but is it possible to "restrict" which docks windows can be attached to? Dumb example: Say I want to restrict a few different windows to only being dock-able on the top or the bottom, not the sides.
Sorry this is not supported. Finding it a little odd to be honest, but it wouldn't be impossible to eventually support it through the ImGuiDockFamily
mechanism. I personally won't likely work on that.
From my perspective, it's not a question of restricting by region (top, bottom), but of restricting by utility: Toolbar windows can only dock in the toolbar region; viewport windows in the viewport region, property editors in the property region. In my pre-dock-branch code, I managed this in my docking manager by allowing docks to reject panels. i.e. dragging a viewport into the toolbar was impossible because there was a bool accept_panel(Panel*) callback on the toolbar that would report "nope, I can't accommodate you".
@meshula
restricting by utility:
This is what the SetNextWindowDockFamily
/Dockspace
/ImGuiDockFamily
is trying to provide, but the feature-set and API probably need some further design and work.
Toolbar windows can only dock in the toolbar region; viewport windows in the viewport region, property editors in the property region.
This is a little ambiguous. If there is such thing as a "toolbar region", "viewport region" does it means that you are not allowing the user to create their own overall layout at all?
You can currently use the DockFamily system in two ways:
Prevent two "incompatible" windows from being merged with each others. You can see the DockFamily ID to a custom value, e.g. ImHash("TOOLBAR_WINDOW")
, ImHash("PROPERTY_WINDOW
).
Create a dockspace to receive a certain type of window.
If what you stated below is actually what you need, you could imagine creating a "locked" dockspace (given a yet missing hypotherical ImGuiDockNodeFlags_LockLayout
flag) and in each node create another dockspace means to receive only a certain type of window.
I think the constraints you stated are not actually exactly what you need, but it would be worth exploring this and see how/if the design needs to evolve further.
Similarly I think @moonheart08 request as stated might be a little misleading but if there is a useful user story behind it I am happy to dig into the idea further, just please provide more detailed use cases.
FYI all : there seems to a regression in 760c1d95b984f2b4bc2db6b7487a7e67674f1af5 which affects the Docking branch. The regression is a visible 1 frame flicker when dragging a docking node outside of the main viewport into a new viewport. However, while I could repro it yesterday I can't seem to repro it today, so there is maybe something at the framework/driver/os level that effects the repro. If that happens to you let me know. You may also checkout the previous commit 510f0e505c8014f67335643d3ca929be0e865bbe, if the bug affects you.
It would be a good idea to add a button to hide the tab bar when there is only 1 tab in it, like in the unreal engine editor … [...] For reference, this is what UE4 does:
This has been in my list for a while, added it now:
This is persisting value. I also experimented with the possibility of automatically enabling tab-bar collapse mode (with or without an explicit flag) but it raises more issues and confusion so I decided against it for now.
@ImBored
I'm trying to save various preset layouts to disk as .ini files and load them back at run time to change the dock layout dynamically. To do this, I'm just saving the imgui.ini file as normal and copying it/creating duplicates. All good - at first run, when the default ini is loaded, dock layouts are loaded correctly and as expected. However calling ImGui::LoadIniSettingsFromDisk(/ini file/) will place my windows correctly but undock every window. Is there anything extra that needs to be called at this time? I threw together a bare bones test as I wanted to remove any exotic things I may have been doing otherwise to sanity check.
To be honest I am surprised you are not hitting a crash or assertion.. Just looking at e.g. LoadIniSettingsFromMemory()
it has stuff like:
IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0);
Which should assert early on.
This is not supported yet.. There is a very simple workaround which is to kill the imgui context and recreate it (basically call ShutdownContext,CreateContext and maybe some other glue/init stuff). You will lose temporary state such as the open/closed state of tree nodes but it may be good enough for your purpose.
There are DockBuilder*
api for manipulating the docking state but I realize there is use for a simple "save layout" / "load layout" system. The problem is that the .ini
state is not guaranteed to only contains layout data but I'll probably look into fixing the code to allow mid-reload. Either way you will probably need to perform reload before the NewFrame()
call and not in the middle of the frame.
This is a little ambiguous. If there is such thing as a "toolbar region", "viewport region" does it means that you are not allowing the user to create their own overall layout at all?
Yes, that's right. I'm making little end user applications that have regions that are expected to be the same no matter whose desk you're running at, and "workspace" areas, where they can arrange panels to their liking to support their personal workflows. Whereas I could allow them to drag a color picker panel to fill the main viewport, that's not part of the intended design.
some features to help illustrate -
tab the overall workspace (say between Edit and View modes).
panels that belong to Edit, and panels that belong to View cannot dock in eachother's tabs.
enforce a left/right split of the Edit mode, such that the left split can have any number of docked 3d views (so that a single view can be arranged, or a four view CAD arrangement, or whatever the user likes), and the right split allows a stack of arrangeable panels, suitable to a workflow of the user's design. This would be like the stack of tools zbrush presents.
As near as I can tell, this is achievable already? I'm mostly trying to clarify the use case.
@ImBored i managed to achieve dynamic layout switching.
see the following example:
you can build different layouts with the following functions and variables
ImGui::DockBuilderSplitNode()
ImGui::DockBuilderDockWindow()
bind changeLayout to a key to switch
this version should work but i couldn't test it. But this is how i achieve it
bool changeLayout_m = false;
bool currentLayout_m = true;
ImGuiID dockSpaceId_m;
void drawTestDock(){
bool open = true;
const char* dockspaceName;
if (currentLayout_m)
{
dockspaceName = "layout1";
}
else
{
dockspaceName = "layout2";
}
dockSpaceId_m = ImGui::GetID(dockspaceName);
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar;
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGui::Begin("Dock", &open, window_flags);
if (currentLayout_m && changeLayout_m)
{
ImGui::DockBuilderRemoveNode(dockSpaceId_m);
ImGui::DockBuilderAddNode(dockSpaceId_m, viewport->Size);
ImGuiID dock_main_id = dockSpaceId_m;
const ImGuiID james1 = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 0.35f, NULL, &dock_main_id);
const ImGuiID james3 = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, 0.40f, NULL, &dock_main_id);
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.65f, NULL, &dock_main_id);
ImGui::DockBuilderDockWindow("james2", dock_main_id);
ImGui::DockBuilderDockWindow("james1", james1);
ImGui::DockBuilderDockWindow("james3", james3);
ImGui::DockBuilderFinish(dockSpaceId_m);
}
else
{
ImGui::DockBuilderRemoveNode(dockSpaceId_m); // Clear out existing layout
ImGui::DockBuilderAddNode(dockSpaceId_m, viewport->Size); // Add empty node
ImGuiID dock_main_id = dockSpaceId_m;
ImGuiID james5 = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 0.4f, NULL, &dock_main_id);
ImGuiID james2 = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.6f, NULL, &dock_main_id);
ImGuiID james6 = ImGui::DockBuilderSplitNode(james5, ImGuiDir_Right, 0.5f, NULL, &james5);
const ImGuiID james3 = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, 0.40f, NULL, &dock_main_id);
const ImGuiID james4 = ImGui::DockBuilderSplitNode(james5, ImGuiDir_Down, 0.5f, NULL, &james5);
const ImGuiID james1 = ImGui::DockBuilderSplitNode(james6, ImGuiDir_Down, 0.5f, NULL, &james6);
ImGui::DockBuilderDockWindow("james2", dock_main_id);
ImGui::DockBuilderDockWindow("james5", james5);
ImGui::DockBuilderDockWindow("james4", james4);
ImGui::DockBuilderDockWindow("james6", james6);
ImGui::DockBuilderDockWindow("james1", james1);
ImGui::DockBuilderDockWindow("james3", james3);
ImGui::DockBuilderFinish(dockSpaceId_m);
}
ImGui::DockSpace(dockSpaceId_m, ImVec2(0.0f, 0.0f), 0);
ImGui::End();
if (currentLayout_m)
{
ImGui::Begin("james1");
ImGui::Text("james1");
ImGui::End();
ImGui::Begin("james2");
ImGui::Text("james2");
ImGui::End();
ImGui::Begin("james3");
ImGui::Text("james3");
ImGui::End();
}
else
{
ImGui::Begin("james1");
ImGui::Text("james1");
ImGui::End();
ImGui::Begin("james2");
ImGui::Text("james2");
ImGui::End();
ImGui::Begin("james3");
ImGui::Text("james3");
ImGui::End();
ImGui::Begin("james4");
ImGui::Text("james4");
ImGui::End();
ImGui::Begin("james5");
ImGui::Text("james5");
ImGui::End();
ImGui::Begin("james6");
ImGui::Text("james6");
ImGui::End();
}
}
@ocornut by the way docking is working fine on windows and in combination with openFrameworks ( multi viewport not tested)
Main point of my suggustion was to prevent, say, a subwindow with it's own docking point having it's windows dragged to the main one. Say for example i have a UI for some random object in my game, and it has docking support. I dont want them to dock the object's UI somewhere else, but I want to allow joining together various objects into a single tabbed window to save space for the user.
@meshula
As near as I can tell, this is achievable already? I'm mostly trying to clarify the use case.
I think you can do some of that with ImGuiDockFamily
and by embedding dockspace within each others, + using a (yet non-existing) ImGuiDockNodeFlags_NoLayoutChanges
to lock a dockspace. So your top-most layout would be a programmatically created and dockspace.
I would suggest try to toy around with ImGuiDockFamily
and see where you get.
@moonheart08 The SetNextWindowDockFamily()
and ImGuiDockFamily
may help you handle that.
I also made a change that answers some of the recurrent queries, which is that using SetNextWindowDockID()
given a node that is split (e.g. the root node of a dockspace) will now automatically find the central node (or the last focused node for an implicit dockspace).
Is it possible to do centralization of content in the docked area?
@aCuria
Is it possible to do centralization of content in the docked area?
This is not a docking question, the same would happen with a regular window sized the same. There's no mechanism for centering whole groups of elements. If you only have a single image you can center it yourself given the window bounds. Please open a new topic for similar question not related to docking, thank you.
just tested the current docking branch but it crashes this way
this is the assertion message
Thank you @codz01, I added added this assert recently to catch the issue earlier in the pipeline and got sidetracked when I was looking for a repro. You found it :) I have pushed a fix now.
thanks
lel
Hello,
FYI i have been steadily pushing additions/fixes over time here.
If you use Docking keep the feedback coming (prefer to open new thread for specific bug/request, to avoid making this one thread growing forever).
(1)
One thing I just pushed is I changing some code to make it possible for the (currently internal and wip) DockBuilderAddNode()
api to create floating docking node which wasn't possible earlier.
e.g.
static bool display = false;
ImGui::Checkbox("Display", &display);
if (ImGui::Button("Redock"))
{
ImGuiID dock_id = ImGui::DockBuilderAddNode(0, ImGuiDockNodeFlags_None);
ImVec2 viewport_pos = ImGui::GetMainViewport()->Pos;
ImGui::DockBuilderSetNodePos(dock_id, ImVec2(viewport_pos.x + 100, viewport_pos.y + 100));
ImGui::DockBuilderSetNodeSize(dock_id, ImVec2(200, 200));
ImGui::DockBuilderDockWindow("AAAA", dock_id);
ImGui::DockBuilderDockWindow("BBBB", dock_id);
ImGui::DockBuilderDockWindow("CCCC", dock_id);
ImGui::DockBuilderFinish(dock_id);
}
if (display)
{
ImGui::Begin("AAAA");
ImGui::Text("This is AAAA");
ImGui::End();
ImGui::Begin("BBBB");
ImGui::Text("This is BBBB");
ImGui::End();
ImGui::Begin("CCCC");
ImGui::Text("This is CCCC");
ImGui::End();
}
If you used DockBuilderAddNode() with dockspace before (unlikely) take note that I have removed the size parameters from it, and you'll need to call it with the ImGuiDockNodeFlags_Dockspace
flag. For various reason at the moment a node cannot be split if it doesn't know its size, so if you use DockBuilderAddNode + DockBuilderSplitNode you need to call DockBuilderSetSize in between.
(2)
One of my internal test bed has been trying to reproduce the behavior/model of Unreal Editor.
I'm posting an experiment patch to example_win31_directx11/main.cpp
(main library not affected) for those interested in exploring some advanced functionalities but this is super raw and as-is.
This may be de-facto a good reference for advanced uses of ImGuiWindowClass or the DockBuilderXXX API (which is super in flux at the moment).
Jan 31, 2019: unreal_mdi_45.zip UPDATE 2022/08/22: imgui_unreal_style_mdi_v52.zip Moved to #6487
Here's a screenshot:
What it is doing, super roughly:
I have pushed an experimental 'docking' branch: https://github.com/ocornut/imgui/tree/docking Effectively providing a long awaited official solution to the features discussed in #351 and #261.
TL;DR; You can benefit from good portion of docking features with no extra work or API call. Windows can be merged with each others, with or without partitioning the space.
Prefer creating separate New Issues for specific questions/issues, so they can more easily be closed when solved and not clutter this thread (which is already too big)
Please do not report issues without reading the 'Feedback' section of the next post and without reading the 'Contributing' document listed in there. The number of ambiguous, ill-formed questions and incomplete bug reports posted on this entire github is difficult to deal with. Thank you.
GIF (this is actually a gif from an older version which has some glitches, but you get the gist!)
Quick demo
You may checkout
docking
and build one the example e.g.example_win32_dx11/
,example_glfw_opengl3
,example_sdl_vulkan
to test this. Head to Demo>Configuration to see the global configuration flags. Note that multi-viewports are enabled by default in those demo but only well tested under Windows. If you have issues with them you can disable them via the Demo>Configuration pane or by commenting out the line that setsImGuiConfigFlags_ViewportsEnable
in the main.cpp of your example. Docking is functional without multi-viewports enabled.