-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
Docking: saving layout #8033
Comments
In addition to loading from ini file I also tried to build with this code:
I’m waiting to get:
as written in used ini string but getting:
|
I have get some approach: #include <json.hpp>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
using json = nlohmann::json;
struct DockNodeInfo {
ImGuiID nodeID;
int splitAxis;
ImVec2 size;
ImGuiDockNodeFlags sharedFlags;
ImGuiDockNodeFlags localFlags;
ImGuiDockNodeFlags mergedFlags;
int state;
std::vector<std::string> windows;
DockNodeInfo* child[2] = { nullptr, nullptr }; // To hold child nodes
};
json serializeDockNode(ImGuiDockNode* node)
{
if (!node) return nullptr;
json j;
j["NodeID"] = node->ID;
j["SplitAxis"] = node->SplitAxis;
j["Size"] = { node->Size.x, node->Size.y };
j["SharedFlags"] = node->SharedFlags;
j["LocalFlags"] = node->LocalFlags;
j["LocalFlagsInWindows"] = node->LocalFlagsInWindows;
j["MergedFlags"] = node->MergedFlags;
j["State"] = node->State;
// Serialize docked windows
if (!node->Windows.empty()) {
j["Windows"] = json::array();
for (ImGuiWindow* window : node->Windows) {
json window_info;
window_info["WindowID"] = window->ID;
window_info["WindowName"] = window->Name;
j["Windows"].push_back(window_info);
}
}
// Serialize child nodes (if any)
if (node->ChildNodes[0]) {
j["ChildNode1"] = serializeDockNode(node->ChildNodes[0]);
}
if (node->ChildNodes[1]) {
j["ChildNode2"] = serializeDockNode(node->ChildNodes[1]);
}
return j;
}
DockNodeInfo deserializeDockNode(const json& j)
{
DockNodeInfo nodeInfo;
nodeInfo.nodeID = j["NodeID"].get<ImGuiID>();
nodeInfo.splitAxis = j["SplitAxis"].get<int>();
nodeInfo.size = ImVec2(j["Size"][0].get<float>(), j["Size"][1].get<float>());
nodeInfo.sharedFlags = j["SharedFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.localFlags = j["LocalFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.mergedFlags = j["MergedFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.state = j["State"].get<int>();
// Deserialize the windows associated with the node
if (j.contains("Windows")) {
for (const auto& window : j["Windows"]) {
nodeInfo.windows.push_back(window["WindowName"].get<std::string>());
}
}
// Deserialize child nodes recursively
if (j.contains("ChildNode1")) {
nodeInfo.child[0] = new DockNodeInfo(deserializeDockNode(j["ChildNode1"]));
}
if (j.contains("ChildNode2")) {
nodeInfo.child[1] = new DockNodeInfo(deserializeDockNode(j["ChildNode2"]));
}
return nodeInfo;
}
void createDockFromInfo(ImGuiID dockspaceID, const DockNodeInfo& info, int child_num)
{
// Set up the dock node (starting with the dockspace root node)
if (info.child[0] != nullptr || info.child[1] != nullptr) {
// Split the dock node if it has children
ImGuiID nodeID = info.child[0] ? info.child[0]->nodeID : 0;
ImGuiID parentID =info.nodeID;
ImGuiDir splitDir;
float splitRatio = 0.5f;
if(info.splitAxis == -1) {
splitDir = ImGuiDir_None;
}
else if(child_num == 0){
splitDir = (ImGuiDir)(child_num + 2 * info.splitAxis);
}
else{
splitDir = (ImGuiDir)(child_num + 2 * info.splitAxis);
}
if(info.splitAxis==0) {
splitRatio = info.child[0]->size.x / (info.child[0]->size.x + info.child[1]->size.x);
}
else
{
splitRatio = info.child[0]->size.y / (info.child[0]->size.y + info.child[1]->size.y);
}
ImGui::DockBuilderSplitNode(info.nodeID, splitDir, splitRatio,
&nodeID, &parentID);
// Recursively handle child nodes
if (info.child[0]) {
createDockFromInfo(dockspaceID, *info.child[0], 0);
}
if (info.child[1]) {
createDockFromInfo(dockspaceID, *info.child[1], 1);
}
} else {
// If the node has no children, dock the windows
for (const auto& window_name : info.windows) {
ImGui::DockBuilderDockWindow(window_name.c_str(), info.nodeID);
}
}
}
void createDockLayoutFromJson(ImGuiID dockspaceID, std::string filename) {
// Parse the JSON
// Open the JSON file
std::ifstream input_file(filename);
if (!input_file.is_open()) {
std::cert <<"Could not open file: "<< filename << std::end;
return;
}
// Parse the JSON
json layout_json;
input_file >> layout_json;
// Deserialize root node
DockNodeInfo root_node_info = deserializeDockNode(layout_json);
if(root_node_info.nodeID != dockspaceID) {
// Remove any existing dockspace and prepare for a new layout
ImGuiID dockspace_id = root_node_info.nodeID ;
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing dockspace
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None); // Add the main dockspace
dockspaceID = dockspace_id;
}
// Rebuild the layout from the deserialized tree
createDockFromInfo(dockspaceID, root_node_info, 0);
}
void printAllDockNodesAsJson(ImGuiDockNode* node, std::string filename) {
if (node) {
// Serialize the dock node tree into JSON
json root_node_json = serializeDockNode(node);
// Output JSON to console or file
std::string json_output = root_node_json.dump(4); // 4 is the indentation level
// Write the JSON string to a file
std::cout << json_output<<std::endl;
std::ofstream file(filename, std::ios::out);
if (file.is_open()) {
file << json_output;
file.close();
std::cout << "JSON saved to file: "<< filename << std::end;
} else {
std::cerr <<"Could not open file for writing: "<< filename<< std::end;
}
} else {
std::cerr <<"DockSpace node not found."<< std::end;
}
} At this time if I get different dockspace it will get error:
I will get more steps... :) |
I get this approach worked. :) I will put it for anyone need different approaches #include <gui/layout.h>
#include <json.hpp>
#include <fstream>
#include <iostream>
#include <map>
using json = nlohmann::json;
std::map<ImGuiID, ImGuiID> dictionary;
json serializeDockNode(ImGuiDockNode* node)
{
if (!node) return nullptr;
json j;
j["NodeID"] = node->ID;
j["SplitAxis"] = node->SplitAxis;
j["Size"] = { node->Size.x, node->Size.y };
j["SharedFlags"] = node->SharedFlags;
j["LocalFlags"] = node->LocalFlags;
j["LocalFlagsInWindows"] = node->LocalFlagsInWindows;
j["MergedFlags"] = node->MergedFlags;
j["State"] = node->State;
// Serialize docked windows
if (!node->Windows.empty()) {
j["Windows"] = json::array();
for (ImGuiWindow* window : node->Windows) {
json window_info;
window_info["WindowID"] = window->ID;
window_info["WindowName"] = window->Name;
j["Windows"].push_back(window_info);
}
}
// Serialize child nodes (if any)
if (node->ChildNodes[0]) {
j["ChildNode1"] = serializeDockNode(node->ChildNodes[0]);
}
if (node->ChildNodes[1]) {
j["ChildNode2"] = serializeDockNode(node->ChildNodes[1]);
}
return j;
}
DockNodeInfo deserializeDockNode(const json& j)
{
DockNodeInfo nodeInfo;
nodeInfo.nodeID = j["NodeID"].get<ImGuiID>();
nodeInfo.splitAxis = j["SplitAxis"].get<int>();
nodeInfo.size = ImVec2(j["Size"][0].get<float>(), j["Size"][1].get<float>());
nodeInfo.sharedFlags = j["SharedFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.localFlags = j["LocalFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.mergedFlags = j["MergedFlags"].get<ImGuiDockNodeFlags>();
nodeInfo.state = j["State"].get<int>();
// Deserialize the windows associated with the node
if (j.contains("Windows")) {
for (const auto& window : j["Windows"]) {
nodeInfo.windows.push_back(window["WindowName"].get<std::string>());
}
}
// Deserialize child nodes recursively
if (j.contains("ChildNode1")) {
nodeInfo.child[0] = new DockNodeInfo(deserializeDockNode(j["ChildNode1"]));
}
if (j.contains("ChildNode2")) {
nodeInfo.child[1] = new DockNodeInfo(deserializeDockNode(j["ChildNode2"]));
}
return nodeInfo;
}
void createDockFromInfo(ImGuiID dockspaceID, const DockNodeInfo& info)
{
// Set up the dock node (starting with the dockspace root node)
if (info.child[0] != nullptr || info.child[1] != nullptr) {
// Split the dock node if it has children
ImGuiID nodeID = info.nodeID;
ImGuiID leftID = info.child[0]->nodeID;
ImGuiID rightID = info.child[1]->nodeID;
if(dictionary.size() != 0){
nodeID=dictionary[nodeID];
}
ImGuiDir splitDir;
float splitRatio = 0.5f;
if(info.splitAxis == -1) {
splitDir = ImGuiDir_None;
}
else if(info.splitAxis == 0){
splitDir = (ImGuiDir)(info.splitAxis);
}
else{
splitDir = (ImGuiDir)(2 * info.splitAxis);
}
if(info.splitAxis==0) {
splitRatio = info.child[0]->size.x / (info.child[0]->size.x + info.child[1]->size.x);
}
else
{
splitRatio = info.child[0]->size.y / (info.child[0]->size.y + info.child[1]->size.y);
}
// Split the main dockspace node into left and right nodes
ImGui::DockBuilderSplitNode(nodeID, splitDir, splitRatio, &leftID, &rightID);
dictionary[info.child[0]->nodeID] = leftID;
dictionary[info.child[1]->nodeID] = rightID;
// Recursively handle child nodes
if (info.child[0]) {
createDockFromInfo(dockspaceID, *info.child[0]);
}
if (info.child[1]) {
createDockFromInfo(dockspaceID, *info.child[1]);
}
} else {
// If the node has no children, dock the windows
for (const auto& window_name : info.windows) {
ImGui::DockBuilderDockWindow(window_name.c_str(), dictionary[info.nodeID]);
}
}
}
void layout::createDockLayoutFromJson(ImGuiID& dockspaceID, ImVec2 availableSpaceForDocking, std::string filename) {
// Parse the JSON
// Open the JSON file
dictionary.clear();
std::ifstream input_file(filename);
if (!input_file.is_open()) {
std::cerr<<"Could not open file: "<<filename<<std::endl;
return;
}
// Parse the JSON
json layout_json;
input_file >> layout_json;
// Deserialize root node
DockNodeInfo root_node_info = deserializeDockNode(layout_json);
// Remove any existing dockspace and prepare for a new layout
ImGui::DockBuilderRemoveNode(dockspaceID); // Clear out existing dockspace
// Remove any existing dockspace and prepare for a new layout
ImGuiID dockspace_id = root_node_info.nodeID ;
ImGui::DockSpace(dockspace_id, availableSpaceForDocking, ImGuiDockNodeFlags_None);
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing dockspace
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None); // Add the main dockspace
dockspaceID = dockspace_id;
// Rebuild the layout from the deserialized tree
createDockFromInfo(dockspace_id, root_node_info);
ImGui::DockBuilderFinish(dockspace_id);
}
void layout::printAllDockNodesAsJson(ImGuiDockNode* node, std::string filename) {
if (node) {
// Serialize the dock node tree into JSON
json root_node_json = serializeDockNode(node);
// Output JSON to console or file
std::string json_output = root_node_json.dump(4); // 4 is the indentation level
// Write the JSON string to a file
std::cout << json_output<<std::endl;
std::ofstream file(filename, std::ios::out);
if (file.is_open()) {
file << json_output;
file.close();
std::cout<<"JSON saved to file: "<<filename<<std::endl;
} else {
std::cerr<<"Could not open file for writing: "<< filename<<std::endl;
}
} else {
std::cerr<<"DockSpace node not found."<<std::endl;
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Version/Branch of Dear ImGui:
Branch: docking, Commit: 7937732
Back-ends:
imgui_impl_opengl3.cpp + imgui_impl_XXX.cpp
Compiler, OS:
macOS + Clang 12, GCC, Windows + MSVC
Full config/build information:
No response
Details:
I'm trying to crate a docking area with following code:
After that I'm filling "Menu", "Debug" and "Waterfall" windows. But If I want to save this layout to ini file all of my layout corrupts.
Inside of my ini file is that:
Original layout:
After ini file loaded:
It seems all windows goes 0,0 point.
How does it possible? Is there any solution?
Edit:
When I save this layout it seems configuration on ini file is corrupted:
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
No response
The text was updated successfully, but these errors were encountered: