ocornut / imgui

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

Window Layout Configurations #2573

Open PointlessReboot opened 5 years ago

PointlessReboot commented 5 years ago

Version/Branch of Dear ImGui:

Version: v1.69 Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: custom Compiler: VC++ 2017 Operating System: windows

My Issue/Question:

My question is about the ability to support the concept of "window layout configurations". What I mean by this is the ability to position/dock a bunch of windows and save/load these configurations at run-time. Think of it like a preset for a particular workflow arrangement.. Hope I explained this enough.

From what I could tell it's kind of possible (small changes to LoadIniSettingsFromMemory, the IM_ASSERT for SettingsLoaded and the FrameCount needed to be removed). With this change I can kind of get loading different configurations in working.

But the docking side of this breaks in all sorts of places, I tried various things to reset/rebuild the docking but had no luck (will try a little bit more).

Can you suggest some ways to get this working or tell me that currently this is just not possible??

Regards Graeme

ocornut commented 5 years ago

It is currently possible via the wip DockBuilderXXX api but not via .ini storage. This needs to be worked on and is among the pending task, in fact it has been discussed a few times in the past. Fiddling with DockContextRebuild() may allow it to work with a .ini reload, I kinda recall there was an issue with it last time I tried.

Sorry I don't have a better answer at the moment.

PointlessReboot commented 5 years ago

Thanks I have not used the DockContextRebuild yet is there any examples I can check out.. I will also search for discussions around this...

On Wed., 22 May 2019, 6:29 pm omar, notifications@github.com wrote:

It is currently possible via the wip DockBuilderXXX api but not via .ini storage. This needs to be worked on and is among the pending task, in fact it has been discussed a few times in the past. Fiddling with DockContextRebuild() may allow it to work with a .ini reload, I kinda recall there was an issue with it last time I tried.

Sorry I don't have a better answer at the moment.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ocornut/imgui/issues/2573?email_source=notifications&email_token=AAWZP3SRDZGTXQS2VMSGYP3PWUOADA5CNFSM4HOSZZEKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV6TVXA#issuecomment-494746332, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWZP3V35SJP4CUHA4CJWMDPWUOADANCNFSM4HOSZZEA .

ocornut commented 5 years ago

There are no examples none of this are public API, you'll be working on imgui itself if you want to move this forward.

DamianMadden commented 5 years ago

I've achieved this by exposing DockContextClearNodes, DockContextBuildNodesFromSettings, & the DockNodeSettings struct in imgui_internal, then recursively writing out the settings for dock nodes in the same file as the rest of the settings for the application, so I'd say it's likely possible with few tweaks

ocornut commented 4 years ago

I have pushed some code allowing to reload settings data at runtime, which includes docking data.

Quick test:

        static const char* ini_to_load = NULL;
        if (ini_to_load)
        {
            ImGui::LoadIniSettingsFromDisk(ini_to_load);
            ini_to_load = NULL;
        }

        // Start the Dear ImGui frame
        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::Begin("Ini Test");
        if (ImGui::Button("Load Ini 1"))
            ini_to_load = "imgui1.ini";
        if (ImGui::Button("Load Ini 2"))
            ini_to_load = "imgui2.ini";
        if (ImGui::Button("Load Ini 3"))
            ini_to_load = "imgui3d.ini";
        if (ImGui::Button("Load Ini 4"))
            ini_to_load = "imgui4d.ini";
        ImGui::End();

Note: it should be illegal to call LoadIniSettingsFromMemory / LoadIniSettingsFromDisk between NewFrame and EndFrame but I have not currently enforced it with an assert, I expect to do so later after some test.

Some all forms of rebuild are 100% flicker free, hope to fix that eventually.

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

image

kudaba commented 4 years ago

Thanks for this, it almost works for me but I'm still sometimes hitting asserts at:

// imgui.cpp(~13043)
    if (node->IsSplitNode())
        IM_ASSERT(node->TabBar == NULL);

And if I skip that one then I'll hit this one:

// imgui.cpp(~12954)
    // Bind or create host window
    ImGuiWindow* host_window = NULL;
    bool beginned_into_host_window = false;
    if (node->IsDockSpace())
    {
        // [Explicit root dockspace node]
        IM_ASSERT(node->HostWindow);

So far it seems that having multiple dockable viewports is the quickest way to repro, I'll update if I can narrow it down a bit more.

Update: I've narrowed it down to DockContextBuildAddWindowsToNodes(ctx, 0); in ImGui::DockSettingsHandler_ApplyAll. Commenting that out makes everything work perfectly.

Now to figure out why my windows grow in size whenever I drag them out of the new window.... Update: Nevermind, user problem, turns out you need to call ImGui_ImplWin32_EnableDpiAwareness(); BEFORE you call ImGui_ImplWin32_Init otherwise monitors are initialized with dpi scale of 1.

cmaughan commented 3 years ago

I implemented layouts using LoadIniSettingsFromDisk, etc. I found that it did not work well until I made the calls outside of the ImGui::NewFrame. The source has an assert for this, but it is checked out. I believe is should be set.... When loading inside NewFrame I see some windows float and appear top left.

The first image is what I expect, when reloading a layout: image

This is what I see if I reload inside NewFrame: image

These 2 examples load the same .ini file. I am synced to the 10 October Docking branch.