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

BeginViewportSideBar disappears #6283

Closed
thewoz opened this issue Mar 30, 2023 · 2 comments
Closed

BeginViewportSideBar disappears #6283

thewoz opened this issue Mar 30, 2023 · 2 comments

Comments

@thewoz
Copy link

thewoz commented Mar 30, 2023

Branch: docking

Hi sorry another stupid question.
I created a BeginViewportSideBar on the bottom of the window and it is displayed correctly.
But when I press from any in the window it disappears.

screen.mov

Here the code:

ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None | ImGuiDockNodeFlags_NoCloseButton;

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

ImGuiViewport * viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));

ImGui::Begin("MainWindow", NULL, window_flags);
ImGui::PopStyleVar();

float height = ImGui::GetFrameHeight();

if(ImGui::BeginMenuBar()) {
  if(ImGui::BeginMenu("Menu")) {
    ImGui::MenuItem("Main menu bar", NULL, false, true);
    ImGui::EndMenu();
  }
  ImGui::EndMenuBar();
}

if(ImGui::BeginViewportSideBar("StatusBar", viewport, ImGuiDir_Down, height, window_flags)) {
  if(ImGui::BeginMenuBar()) {
    ImGui::Text("status bar");
    ImGui::EndMenuBar();
  }
  ImGui::End();
}

ImGuiID mainDockSpaceId = ImGui::GetID("MainDockSpace");
const ImVec2 dockspace_size = ImGui::GetContentRegionAvail();
ImGui::DockSpace(mainDockSpaceId, ImVec2(0.0f, 0.0f), dockspace_flags);

ImGuiWindowClass window_class;
window_class.DockNodeFlagsOverrideSet = ImGuiDockNodeFlags_NoTabBar;

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Down", &show_another_window, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Left", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Right", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

static bool sFirstFrame = true;
if(sFirstFrame) {
  
  sFirstFrame = false;
  
  ImGui::DockBuilderRemoveNode(mainDockSpaceId);
  ImGui::DockBuilderAddNode(mainDockSpaceId, ImGuiDockNodeFlags_None);
  ImGui::DockBuilderSetNodeSize(mainDockSpaceId, dockspace_size);

  ImGuiID dock_id_up;
  ImGuiID dock_id_down;
  
  ImGuiID dock_id_left;
  ImGuiID dock_id_right;

  ImGui::DockBuilderSplitNode(mainDockSpaceId, ImGuiDir_Up, 0.5f, &dock_id_up, &dock_id_down);

  ImGui::DockBuilderSplitNode(dock_id_up, ImGuiDir_Right, 0.5f, &dock_id_right, &dock_id_left);
  
  ImGui::DockBuilderDockWindow("Down", dock_id_down);
  ImGui::DockBuilderDockWindow("Left", dock_id_left);
  ImGui::DockBuilderDockWindow("Right", dock_id_right);
  
  ImGui::DockBuilderFinish(mainDockSpaceId);
  
}

ImGui::End();
@PathogenDavid
Copy link
Contributor

As the name implies, viewport side bars apply to the viewport--not the current window. As such your window overlaps with your viewport side bar and ends up covering it when it is brought to the front.

The easiest route is to move your viewport side bar to before the MainWindow and use ImGuiViewport::WorkPos/WorkSize to position the MainWindow (which will respect the sidebar.)

Personally I'd also use BeginMainMenuBar rather than BeginMenuBar just so the menu bar and status bar are implemented the same way, but it realistically shouldn't matter.

As an aside, your other windows (Down/Left/Right) don't need to be within the Begin..End for MainWindow. You should also be able to just replace MainWindow with DockSpaceOverViewport (your code needs the custom dockspace for DockBuilderSetNodeSize but I don't think you need DockBuilderSetNodeSize in the first place.)

Your height is also going to be wrong once per-monitor DPI is fully implemented when multiple viewports are involved. You should explicitly set the current viewport like BeginMainMenuBar does.

Here's your example tweaked with the above suggestions:

ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetCurrentViewport(nullptr, (ImGuiViewportP*)viewport); // Set viewport explicitly so GetFrameHeight reacts to DPI changes

float height = ImGui::GetFrameHeight();

if (ImGui::BeginMainMenuBar()) {
    if (ImGui::BeginMenu("Menu")) {
        ImGui::MenuItem("Main menu bar", NULL, false, true);
        ImGui::EndMenu();
    }
    ImGui::EndMainMenuBar();
}

if (ImGui::BeginViewportSideBar("StatusBar", viewport, ImGuiDir_Down, height, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar)) {
    if (ImGui::BeginMenuBar()) {
        ImGui::Text("status bar");
        ImGui::EndMenuBar();
    }
    ImGui::End();
}

ImGuiID mainDockSpaceId = ImGui::DockSpaceOverViewport();

ImGuiWindowClass window_class;
window_class.DockNodeFlagsOverrideSet = ImGuiDockNodeFlags_NoTabBar;

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Down", &show_another_window, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Left", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

ImGui::SetNextWindowClass(&window_class);
ImGui::Begin("Right", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
ImGui::Text("Stats:");
ImGui::End();

static bool sFirstFrame = true;
if (sFirstFrame) {

    sFirstFrame = false;

    ImGui::DockBuilderRemoveNode(mainDockSpaceId);
    ImGui::DockBuilderAddNode(mainDockSpaceId, ImGuiDockNodeFlags_None);

    ImGuiID dock_id_up;
    ImGuiID dock_id_down;

    ImGuiID dock_id_left;
    ImGuiID dock_id_right;

    ImGui::DockBuilderSplitNode(mainDockSpaceId, ImGuiDir_Up, 0.5f, &dock_id_up, &dock_id_down);

    ImGui::DockBuilderSplitNode(dock_id_up, ImGuiDir_Right, 0.5f, &dock_id_right, &dock_id_left);

    ImGui::DockBuilderDockWindow("Down", dock_id_down);
    ImGui::DockBuilderDockWindow("Left", dock_id_left);
    ImGui::DockBuilderDockWindow("Right", dock_id_right);

    ImGui::DockBuilderFinish(mainDockSpaceId);
}

And here's the output after clicking around to adjust the splitters:

Screenshot of the above code

@thewoz
Copy link
Author

thewoz commented Mar 31, 2023

Thank you very much!!!
Especially for the explanation of how things work!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants