Created
February 5, 2022 00:29
-
-
Save AidanSun05/953f1048ffe5699800d2c92b88c36d9f to your computer and use it in GitHub Desktop.
A commented example for Dear ImGui's DockBuilder API.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The DockBuilder API is still marked as experimental, include Dear ImGui's internal header to pull the functions in: | |
#include "imgui_internal.h" | |
// [...] | |
// Beginning of main loop | |
// 1. DockBuilder functions only need to run once to take effect. | |
// This state variable will let us check for the first frame of the app. | |
static bool firstLoop = true; | |
// Only run DockBuilder functions on the first frame of the app: | |
if (firstLoop) { | |
// 2. We want our whole dock node to be positioned in the center of the window, so we'll need to calculate that first. | |
// The "work area" is the space inside the platform window created by GLFW, SDL, etc. minus the main menu bar if present. | |
ImVec2 workPos = ImGui::GetMainViewport()->GetWorkPos(); // The coordinates of the top-left corner of the work area | |
ImVec2 workSize = ImGui::GetMainViewport()->GetWorkSize(); // The dimensions (size) of the work area | |
// We'll need to halve the size, then add those resultant values to the top-left corner to get to the middle point on both X and Y. | |
ImVec2 workCenter{ workPos.x + workSize.x * 0.5f, workPos.y + workSize.y * 0.5f }; | |
// For completeness, this can be simplified in modern versions of Dear ImGui. | |
// v1.81 (found by git blame) adds a new function GetWorkCenter() which does these same calculations, so for any code using a newer version: | |
// | |
// if (firstLoop) { | |
// ImVec2 workCenter = ImGui::GetMainViewport()->GetWorkCenter(); | |
// 3. Now we'll need to create our dock node: | |
ImGuiID id = ImGui::GetID("MainWindowGroup"); // The string chosen here is arbitrary (it just gives us something to work with) | |
ImGui::DockBuilderRemoveNode(id); // Clear any preexisting layouts associated with the ID we just chose | |
ImGui::DockBuilderAddNode(id); // Create a new dock node to use | |
// 4. Set the dock node's size and position: | |
ImVec2 size{ 600, 300 }; // A decently large dock node size (600x300px) so everything displays clearly | |
// Calculate the position of the dock node | |
// | |
// `DockBuilderSetNodePos()` will position the top-left corner of the node to the coordinate given. | |
// This means that the node itself won't actually be in the center of the window; its top-left corner will. | |
// | |
// To fix this, we'll need to subtract half the node size from both the X and Y dimensions to move it left and up. | |
// This new coordinate will be the position of the node's top-left corner that will center the node in the window. | |
ImVec2 nodePos{ workCenter.x - size.x * 0.5f, workCenter.y - size.y * 0.5f }; | |
// Set the size and position: | |
ImGui::DockBuilderSetNodeSize(id, size); | |
ImGui::DockBuilderSetNodePos(id, nodePos); | |
// 5. Split the dock node to create spaces to put our windows in: | |
// Split the dock node in the left direction to create our first docking space. This will be on the left side of the node. | |
// (The 0.5f means that the new space will take up 50% of its parent - the dock node.) | |
ImGuiID dock1 = ImGui::DockBuilderSplitNode(id, ImGuiDir_Left, 0.5f, nullptr, &id); | |
// +-----------+ | |
// | | | |
// | 1 | | |
// | | | |
// +-----------+ | |
// Split the same dock node in the right direction to create our second docking space. | |
// At this point, the dock node has two spaces, one on the left and one on the right. | |
ImGuiID dock2 = ImGui::DockBuilderSplitNode(id, ImGuiDir_Right, 0.5f, nullptr, &id); | |
// +-----+-----+ | |
// | | | | |
// | 1 | 2 | | |
// | | | | |
// +-----+-----+ | |
// split -> | |
// For our last docking space, we want it to be under the second one but not under the first. | |
// Split the second space in the down direction so that we now have an additional space under it. | |
// | |
// Notice how "dock2" is now passed rather than "id". | |
// The new space takes up 50% of the second space rather than 50% of the original dock node. | |
ImGuiID dock3 = ImGui::DockBuilderSplitNode(dock2, ImGuiDir_Down, 0.5f, nullptr, &dock2); | |
// +-----+-----+ | |
// | | 2 | split | |
// | 1 +-----+ | | |
// | | 3 | V | |
// +-----+-----+ | |
// 6. Add windows to each docking space: | |
ImGui::DockBuilderDockWindow("One", dock1); | |
ImGui::DockBuilderDockWindow("Two", dock2); | |
ImGui::DockBuilderDockWindow("Three", dock3); | |
// 7. We're done setting up our docking configuration: | |
ImGui::DockBuilderFinish(id); | |
} | |
// 8. Create some windows to put in the dock node: | |
// (The titles of these windows must match the strings given in DockBuilderDockWindow().) | |
ImGui::Begin("One"); | |
ImGui::End(); | |
ImGui::Begin("Two"); | |
ImGui::End(); | |
ImGui::Begin("Three"); | |
ImGui::End(); | |
// 9. At this point, we're at the end of the loop iteration. | |
// If this is our first one, set the state variable to false so the DockBuilder functions don't run again: | |
if (firstLoop) firstLoop = false; | |
// End of main loop |
Comments are disabled for this gist.