ocornut / imgui

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

Background colour of docked windows #2700

Open Unit2Ed opened 5 years ago

Unit2Ed commented 5 years ago

Version/Branch of Dear ImGui:

Version: 1.72 WIP (17102) Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_dx11.cpp + imgui_impl_win32.cpp Compiler: Visual C++ 2017 Operating System: Windows 10

Docked windows currently have the flag ImGuiWindowFlags_ChildWindow added to them automatically, which causes them to use ImGuiCol_ChildBg rather than their normal ImGuiCol_WindowBg. Do you think it would be reasonable to add an exception to GetWindowBgColorIdxFromFlags so that they continue to use ImGuiCol_WindowBg if the window's docked?

We have some windows with background colours that differ from the style's default, and this change makes them inconsistent. To workaround it we would need to also adjust ImGuiCol_ChildBg on every dockable window, and pop it immediately after Begin so that any "real" child windows within them are drawn with the proper ImGuiCol_ChildBg.

WindowBackground

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;

ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode;
if (dockspaceFlags & ImGuiDockNodeFlags_PassthruCentralNode)
    window_flags |= ImGuiWindowFlags_NoBackground;

ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_Always);
ImGui::Begin("Dock", nullptr, window_flags);
ImGui::PopStyleVar(2);
ImGuiID dockspaceID = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspaceID, ImVec2(0, 0), dockspaceFlags);
ImGui::End();

ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // Set window background to red
ImGui::Begin("Red Window");
ImGui::PopStyleColor();
ImGui::End();
ocornut commented 5 years ago

Hello,

The reasoning behind this choice is that the root/host docking window handle displaying the entire background. Individual docked windows because ChildBg default to zero wouldn't display anything again, to save on fillrate and avoid situation where where alpha <1.0 we would end up with a different final color (because two layers would blend).

You are however right it should be using WindowBg. An easy but slightly incorrect workaround:

One correct but tricky solution would be:

On your side, in the short term you may also consider just drawing a background color of your choice yourself.

ocornut commented 3 years ago

(Addenum: commit 9e4956d86bf6cbb8a10df210cba2e70857cd3eb0 referring incorrectly to #2700 where it actually wanted to refer to #3521.)

ocornut commented 3 years ago

FYI I've been working on that yesterday: (#2700, #2539) window_docked_styles_2

I've got a "mostly working" version but there are many edge cases that are currently tricky to solve and would lead to "holes" in the background for 1-2 frames. At the moment I believe the fully correct version would require too much work (maybe a few days) as it would requires reoverhauling some aspect of how docking nodes gets updated mid-frame. I however think it will be healthy for the code to do that reoverhaul, and for many more reasons that just override WindowBg color, so I'll eventually do it. But for now I left this stashed.

(Note that I pushed another commit yesterday which makes the Docking system honor changes of ImGuiCol_Tab*** colors and text colors, so it is possible to make specific windows have a colored tab.)

ocornut commented 2 years ago

This is now properly solved by b16f738

It turned out a bit difficult but still easier than I thought. One key element was fixing two other bugs a bit earlier (8733ca4).

I needed to rework this because we have another task (newly appearing windows showing behind modals) which required a rework of our dimming layers, which required a rework of how background layers were rendered, so this come in the yak-saving pile.

Also fixed #2539 and #2522 all-together.

ocornut commented 2 years ago

Temporarily reverting this at it is causing a problem with dimming overlay (ctrl+tab, modals) in dock trees.

ocornut commented 2 years ago

Amend/fix with b40c54d

loryruta commented 2 years ago

Version/Branch of Dear ImGui:

Version: 1.87 Branch: docking Commit: 1ee252772ae9c0a971d06257bb5c89f628fa696a

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_vulkan.cpp + imgui_impl_glfw.cpp Compiler: Visual Studio 2019 Operating System: Windows 10


Hi, I'm writing my problem here because it seems to be related:

I have a main window hosting a DockSpace with ImGuiWindowFlags_NoBackground and a window with a semi-trasparent background (alpha = 0.1). If I dock the latter within the no-background window its background doesn't get blended correctly: it's still transparent but not the same as when it wasn't docked (I guess because it gets blended with some black color (?)).

Here's what is happening:

https://user-images.githubusercontent.com/24776968/159745725-92a287b3-88b5-4da1-bb87-206f849dc996.mp4

And here's the code I'm using:

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);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));

ImGui::Begin("##main", nullptr,
            ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
            ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus |
            ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoBackground);

ImGui::PopStyleVar(3);

m_main_dock_id = ImGui::GetID("main-dock_id");

if (!ImGui::DockBuilderGetNode(m_main_dock_id))
{
    ImGui::DockBuilderRemoveNode(m_main_dock_id);
    ImGui::DockBuilderAddNode(m_main_dock_id, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_DockSpace);
    ImGui::DockBuilderSetNodeSize(m_main_dock_id, viewport->Size);

    ImGuiID rem_dock_id;
    m_bottom_toolbar_dock_id = ImGui::DockBuilderSplitNode(m_main_dock_id, ImGuiDir_Down, 0.15f, nullptr, &rem_dock_id);
    m_left_sidebar_dock_id = ImGui::DockBuilderSplitNode(rem_dock_id, ImGuiDir_Left, 0.2f, nullptr, nullptr);

    ImGui::DockBuilderFinish(m_main_dock_id);
}

ImGui::DockSpace(m_main_dock_id, ImVec2(0, 0), ImGuiDockNodeFlags_PassthruCentralNode);

ImGui::End();

ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1, 0, 0, 0.1));
ImGui::SetNextWindowDockID(m_left_sidebar_dock_id, ImGuiCond_Once);
ImGui::ShowDemoWindow();
ImGui::PopStyleColor();

What do I expect: Since the main window has no background, I'd expect the docked window's alpha to be kept and be the same as it is when not docked.

ocornut commented 2 years ago

I think WindowBG color is used on dock node indeed.

loryruta commented 2 years ago

I have also tried to force the main window's background colors to transparent:

ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0,0,0,0));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0,0,0,0));
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0,0,0,0));

ImGui::Begin("##main", nullptr, ... ImGuiWindowFlags_NoBackground ...);

// (...)

ImGui::PopStyleColor(3);

But I still have the same issue. How can I keep the docked window background the same?

ocornut commented 2 years ago

Presently i don’t think you can.