ocornut / imgui

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

Docking branch available for testing #2109

Open ocornut opened 6 years ago

ocornut commented 6 years ago

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.

image

GIF (this is actually a gif from an older version which has some glitches, but you get the gist!) 20180809_docking

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 sets ImGuiConfigFlags_ViewportsEnable in the main.cpp of your example. Docking is functional without multi-viewports enabled.

izirayd commented 5 years ago

@ocornut Hey, so what u think about make poll windows for ImGui_ImplGlfw_CreateWindow. It`s it solves the problem with VAO, cuz we can make for all context VAO. It will also fix a micro lag when creating a window.

ocornut commented 5 years ago

@oriongame I don’t understand what you are saying, and it doesn’t seem related to Docking. If related to Viewport please discuss in the appropriate issue or create a new issue with more details.

Highflex commented 5 years ago

Hey there,

I have been trying to use DockBuilderSplitNode but no matter how i apply it my application always crashes, is there any chance to get a updated sample on split layouts? I couldn't find any in the demos.

Thanks.

EDIT:

Figured it out, i was passing the wrong parameters to DockBuilderSplitNode, works perfectly now :)

hartcw commented 5 years ago

I've been trying out the docking branch on my app, its working well.

One issue I've encountered is with the behaviour of docked window resize, when resizing the app's main window.

Sometimes the splitter between docked windows will adjust in proportion to the original split. But sometimes, the splitter will stay at an absolute position during resize (and hence the % split between the two windows will change).

I've attached a gif to illustrate. It shows that the splitter between top/bottom windows behaves nicely, the proportional split is maintained during app resize. But for the splitter between left/right windows, the left-side windows do not change width, instead the right-side window increases its share of the available app width.

Is there some way I can control this, so the proportional split is also maintained during app-resize? Do I need to do the node splitting differently? (I use the DockBuilder app to set the initial config)

dock_resize

ocornut commented 5 years ago

@hartcw

Sometimes the splitter between docked windows will adjust in proportion to the original split. But sometimes, the splitter will stay at an absolute position during resize (and hence the % split between the two windows will change).

The central node of a dockspace will try to use remaining size, and the non-central nodes will be distributed over their relative size.

We may need to implement ImGuiDockNodeFlags_NoCentralNode to disable the central node here. Or we can rework the system to not have a central node at all, and instead rely on per-node flag (e.g. what currently is the central node could be a node with a specifc sizing policy and a dont-delete-when-empty policy).

(Additionally you seem you have a refreshing glitch when resizing from the OS window border)

hartcw commented 5 years ago

@ocornut

So if the central window is taking the extra width when resizing, why does it also take the extra height? Instead, the heights are staying proportional with the window at the bottom.

ocornut commented 5 years ago

So if the central window is taking the extra width when resizing, why does it also take the extra height? Instead, the heights are staying proportional with the window at the bottom.

Hmm, it is possible there is another issue. Could you open a New Issue with a repro for it, so the issue can be isolated? Thanks!

hartcw commented 5 years ago

Thanks @ocornut , I opened a new issue #2350 I've attached a new gif to that issue, I think it illustrates the problem better.

mrPalomar commented 5 years ago

Is it possible yet to lock a window so it cannot be undocked?

eddieparker commented 5 years ago

Apologies if this isn't the place to ask - but does anyone have an implementation of this working with bgfx as a backend that I could crib off of? I have the basic imgui working, but finding the right places to put the swap chain rebuilds and viewport destruction isn't readily apparent.

ocornut commented 5 years ago

@eddieparker You seem to be making a request about Multi-viewports which are unrelated to Docking save from the fact they are hosted in the same branch. Please git in the correct thread not a docking thread. If anything you could be also asking in the bgfx repo instead.

almic commented 5 years ago

I have a question, do you think it would be beneficial to have the WindowClass stored inside the NextWindowData of the imgui context (and the windows themselves) be a pointer instead? Currently I'm writing a system to allow end users to rearrange the windows in a dockspace and save that to the file system, and need to pass a derived class to the SetNextWindowClass() function. However because the context doesn't store it as a pointer, all my extra data is chopped off.

I'm pretty sure this was the intention when adding that, so it would be great if it actually worked that way.

ocornut commented 5 years ago

@almic Again, best to open a new topic! The quick answer is that we almost never hold on user pointers in dear imgui, but understanding better what you are trying to do may lead to a better answer or solution.

BeachCoder76 commented 5 years ago

Hi- I've been playing around with the Docking Branch. Is DockSpace() supposed to be used within any window juste created? I'm asking the question since I tried to have one top window handle "on first call" for other windows opening by docking them directly under itself in its DockSpace. This works until I collapsed my top window (DockSpace owner window) and all docked windows go floating...

imguidockspaceissue

Maybe there's another way to declare a docking region within a window? But if that's a real code issue, I'd be more than pleased to open a new topic about it.

Thanks

ocornut commented 5 years ago

@BeachCoder76 I don't understand all of your message. I think what is happening here is that you are doing an early-out when the Master Window is collapsed, which is a common pattern. However in the case of a DockSpace you will need to keep it "alive" otherwise its windows will get undocked. Typically you would submit the dockspace even if Begin() returned false.

I will add more commentary in the ShowExampleAppDockSpace() demo to explain this. Note that you can also call DockSpace() with the ImGuiDockNodeFlags_KeepAliveOnly to keep it alive.

(For further issues, please open a separate issue and tag this one.)

BeachCoder76 commented 5 years ago

Sorry about that, I thought I'd keep it as simple as possible without a new topic. I should probably followed my first instinct and submit one instead. I did test your suggestion and it works but it was counter-intuitive to me .. I might still open a Topic on this as I've never read anything about this and it's good info for all coders. Unless you disagree :)

rokups commented 5 years ago

I noticed that windows are dockable by default. Does it make sense though? Usually in applications that support docking we have a tight selection of dockable widgets and rest of windows (message boxes, file dialogs, options dialogs) are not dockable. Maybe it would make sense to have opt-in dockable windows instead of opt-out?

ocornut commented 5 years ago

I noticed that windows are dockable by default. Does it make sense though? Usually in applications that support docking we have a tight selection of dockable widgets and rest of windows (message boxes, file dialogs, options dialogs) are not dockable. Maybe it would make sense to have opt-in dockable windows instead of opt-out?

I disagree. I think the docking feature is much more powerful when this is available by default. Making it opt-in would put a severe entry bar to maximimize the use of merging windows.

It's already always off for popups, modals, tooltips, menus.

ocornut commented 5 years ago

Work on Docking is still ongoing and I've been regularly pushing fixes and small improvement. If you have specific bug report/request please prefer opening a new github issue.

I pushed a change to allow undocking a whole node (vs a single window) by dragging from the empty space in tab bar / title bar. This is in line with most people expectation and previously was only possible by draggong from the "collapse button" / "docking menu" button which wasn't well understood.

However if the dock node is part of a moveable, floating hierarchy, dragging from the tab bar will still move the whole hierarchy otherwise we can not move those windows (unless they have OS decoration) enabled. You can still undock whole node that are part of a floating hierarchy by dragging from the "docking menu" menu.

Aborres commented 5 years ago

Hey! I'm testing this branch and it's going fine so far; however, I haven't managed to make imgui save the state of the docked windows. Calling SaveIniSettingsToDisk manually seems to make imgui remember the positions of the windows but not how they were docked to each other.

Am I missing something or this is a missing feature? If it's in the TODO list, can I help to implement this?

ocornut commented 5 years ago

@Aborres Saving should be supported. A possible issue is that you may be enabling docking after loading the .ini file and that information will be discarded on load. First check your .ini file to rule that out or not. Otherwise please provide a Minimal, Complete and Reprodudice example (https://stackoverflow.com/help/minimal-reproducible-example) and create a new issue for it. Thank you!.

Aborres commented 5 years ago

@ocornut You were right that was the problem, sorry about that. Apart from that it was quite easy to integrate (awesome). I've found an issue with aligned combo menus and I am having a constant crash when switching to a specific tab but I believe these are my fault.

image

ocornut commented 5 years ago

I've found an issue with aligned combo menus and I am having a constant crash when switching to a specific tab but I believe these are my fault.

Please open New Issue for anything you have to report, with a repro. Thank you.

bilek993 commented 5 years ago

Hi, I would like to achive result like @rokups, but it doesn't seems to work like expected. Probably I'm doing something wrong, but I don't know what.

I'm trying to achive this: image I've got this: image

auto dockingEnabled = true;
const auto windowFlags =    ImGuiWindowFlags_MenuBar | 
                            ImGuiWindowFlags_NoDocking | 
                            ImGuiWindowFlags_NoTitleBar | 
                            ImGuiWindowFlags_NoCollapse | 
                            ImGuiWindowFlags_NoResize | 
                            ImGuiWindowFlags_NoMove | 
                            ImGuiWindowFlags_NoBringToFrontOnFocus | 
                            ImGuiWindowFlags_NoNavFocus |
                            ImGuiWindowFlags_NoBackground;

const auto dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode;

const auto 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);

ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("MainDockspaceArea", &IsDockingEnabled, windowFlags);
ImGui::PopStyleVar(3);

DrawMenuBar();

auto mainDockspaceId = ImGui::GetID("MainDockspaceArea");
ImGui::DockSpace(mainDockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);

static auto firstTime = true;
if (firstTime)
{
    firstTime = false;
    ImGui::DockBuilderRemoveNode(mainDockspaceId);
    ImGui::DockBuilderAddNode(mainDockspaceId, dockspaceFlags);
    ImGui::DockBuilderSetNodeSize(mainDockspaceId, viewport->Size);

    auto dockIdProp = ImGui::DockBuilderSplitNode(mainDockspaceId, ImGuiDir_Right, 0.20f, nullptr, &mainDockspaceId);
    auto dockIdBottom = ImGui::DockBuilderSplitNode(mainDockspaceId, ImGuiDir_Down, 0.20f, nullptr, &mainDockspaceId);

    ImGui::DockBuilderDockWindow("Systems browser", dockIdProp);
    ImGui::DockBuilderFinish(mainDockspaceId);
}

ImGui::End();
ocornut commented 5 years ago

@bilek993 When calling DockBuilderAddNode() you need to pass the ImGuiDockNodeFlags_DockSpace flag otherwise you won't have a default "central node" which can stay empty.

REMINDER TO EVERYONE USING ImGui::DockBuilderXXX this is a Beta api and it has been changing. If you have issues with it check the posts, git log and comments here.

PLEASE OPEN NEW ISSUES WHEN YOU HAVE AN ISSUE WITH DOCKING. THIS THREAD IS TOO CROWDED.

Husenap commented 5 years ago

Hi!

I started playing around with the docking branch and ran into an assert here: https://github.com/ocornut/imgui/blob/13f00331dacbfc6ff14e41fc359c4234100fa6b9/imgui_widgets.cpp#L7187

You can reproduce this by just using the DockSpace example in the demo window, make a vertical split, then start moving one split to the side, when a TabItem gets to 0 width, it crashes.

I tried adding an early return instead of an assert and that worked. Is there any workaround for this without changing the imgui code?

ocornut commented 5 years ago

Thank you @Husenap for reporting this bug. The issue was introduced by a856c67 and I have now pushed the fix in 80b3ab7. (In the future you can open a new thread for Docking related issues/questions)

Husenap commented 5 years ago

Thank you @Husenap for reporting this bug. The issue was introduced by a856c67 and I have now pushed the fix in 80b3ab7.

Thank you so much for the quick fix!

(In the future you can open a new thread for Docking related issues/questions)

Noted ^^

rasky commented 4 years ago

@ocornut without any commitment, what is the ETA for this branch? Weeks? Months? Years? I’m starting to use it (through a binding) and I’d love to understand how much to engineer my build system through several layers of bindings and libraries to use this branch (I need several local forks/patches). I don’t want to waste much time on it if the branch is landing “soon”.

hateom commented 4 years ago

@ocornut I'm testing the docking feature quite a lot lately and have to say it's great! One question though - what would be the best way to save & restore the layout of all the windows and their dockings? (sort of the info that is stored in the *.ini file). I need multiple layouts that could be toggled between.

ocornut commented 4 years ago

@hateom There's no easy way right now, supposedly the internal/wip DockBuilder API was meant to do things like that for for saving existing templates something closer to loading partial .ini data would be more useful. It's all unfortunately more complicated than just saving/loaded .ini data, but for simple apps I will work on making it possible to reload .ini data while imgui is running (currently it's not possible). Current workaround is to shutdown and recreate imgui context (which is surprisingly non intrusive but you'll lose tree node open/close state and focus order). For further questions best to open new threads.

edselmalasig commented 4 years ago

How do I get started with dock panels? Nice work team ImGui I got to start donating again.

manuliner commented 4 years ago

How do I get started with dock panels? Nice work team ImGui I got to start donating again.

read this

and this

mastergog1 commented 4 years ago

Hello is there a way to use the DockerBuilder functions, like the split function with FirstUseEver flag? Can't seem to find one... I want to build an initial layout that can be re-arranged and it will persist on restart. Thank you.

ocornut commented 4 years ago

Hello @Lin20, Are you properly testing the return value of BeginTabBar() ? Otherwise, please open a new issue with a copy & pastable repro ideally, thank you!

hsimyu commented 4 years ago

@hsimyu Please open a new issue with the same info (and then you can delete the message here), it's easier to maintain at this point. Thanks!

(PS: Note that the ShowMetricsWindow() has many similar infos as the one you are displaying in your debug windows.)

@ocornut OK, I opened #3111 and deleted my message here, Thanks! (And also, thanks for telling me ShowMetricsWindow(). It is more useful than my simplistic debug windows 🙏 )

ocornut commented 4 years ago

I've pushed some changes making it now possible to call LoadIniSettingsFromDisk() / LoadIniSettingsFromMemory() at runtime before NewFrame(). In particular, this is related to docking as I've managed to make it works to reload docking information from .ini data and thus this could perhaps be used to setup some initial state. Up to experiment... https://github.com/ocornut/imgui/issues/2573#issuecomment-625512092

In addition, the Metrics windows now has some extra Settings infos and tools: image

epezent commented 4 years ago

I upgraded from ~1.75 WIP to the current 1.77 WIP and docked windows are no longer drag-able from their title-bar tab. Did a default setting change somewhere, or is this a bug?

ocornut commented 4 years ago

@epezent I confirmed there's a very bug on docking right now, see #3243, looking at it now.

dolphineye commented 4 years ago

Hey,

I've just started toying around with this branch 👍

I've noticed that when we attempt to dock a collapsed window, it will just crash at:

void ImGui::Scrollbar(ImGuiAxis axis)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;

    const ImGuiID id = GetScrollbarID(window, axis);
    KeepAliveID(id);

    // Calculate scrollbar bounding box
    const ImRect outer_rect = window->Rect();
    const ImRect inner_rect = window->InnerRect;
    const float border_size = window->WindowBorderSize;
    const float scrollbar_size = window->ScrollbarSizes[axis ^ 1];
    IM_ASSERT(scrollbar_size > 0.0f);

    // ...
}

Is this a known issue? If not, a possible quick fix would be preventing collapsed windows from docking. Possibly, we can also fix it the other way around and expand the window before docking it. Not sure of what would be the most intuitive behavior though.

rokups commented 4 years ago

Hey @dolphineye. I am unable to reproduce this crash. Could you specify exact commit of docking branch you tested, exact steps to reproduce the issue (to the most minor detail), example you tested this on (including backend, graphics api, platform).

dolphineye commented 4 years ago

Hey @dolphineye. I am unable to reproduce this crash. Could you specify exact commit of docking branch you tested, exact steps to reproduce the issue (to the most minor detail), example you tested this on (including backend, graphics api, platform).

Hey Rokups, thanks for your feedback. After investigating, it turned out there was a defect in. my ImGUI integration, which caused the issue. So this is on me :)

ChristianIvicevic commented 4 years ago

Hey there, I was curious whether there is already support to customize the distance between docked windows. For comparison you can see the following Unity screenshot that has some significant free space between the windows which makes it slightly "lighter":

Unity

The current behavior of imgui is more dense in contrast.

image

It'd be nice to be able to configure that distance which is the splitter thickness.

ChristianIvicevic commented 4 years ago

Quick update: Even though my C++ is a bit rusty I found the IMGUI_DOCK_SPLITTER_SIZE variable in imgui.cpp and it does exactly what I was looking for. I definitely propose that this becomes an actual style variable at some point. In the meantime and for testing purposes I changed its value and rebuild cimgui and Imgui.NET so I can use the customized version in my PoC playground.

nauq302 commented 4 years ago

How can I use this with Vcpkg and Cmake?

PathogenDavid commented 4 years ago

Dear ImGui does not impose (or provide support for) any particular build system. From the readme:

No specific build process is required. You can add the .cpp files to your existing project.

1aam2am1 commented 4 years ago

How could I dock visible window and undock it sometime later?

FilipePpereira commented 4 years ago

Como faço para começar a usar os painéis de encaixe? Bom trabalho, equipe ImGui. Eu tenho que começar a doar novamente.

Leia isso

e isto

usa isto ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->Pos); ImGui::SetNextWindowSize(viewport->Size); ImGui::SetNextWindowViewport(viewport->ID); ImGui::SetNextWindowBgAlpha(0.0f);

ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;

ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::Begin("DockSpace Demo", p_open, window_flags); ImGui::PopStyleVar(3);

ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode; ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);

1aam2am1 commented 4 years ago

Flag: ImGui::GetStyle().WindowMenuButtonPosition = ImGuiDir_None; Creates visible artifacts as it displays Hide Bar menu but don't move cursor for drawing tabs.

ocornut commented 4 years ago

@1aam2am1 Please open a separate issue with screenshots/gifs and details, thank you.