From 6e2711f9e8d57e3c2e45fa6ce83b2f7f493a4071 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 1 Apr 2026 16:43:46 +0800 Subject: [PATCH] Preserve saved editor dock layouts --- editor/src/Application.cpp | 7 ++++- editor/src/Layout/DockLayoutController.h | 36 +++++++++++++++++++++++- editor/src/UI/ImGuiSession.h | 28 ++++++++++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/editor/src/Application.cpp b/editor/src/Application.cpp index 75355bb5..29ef5b0f 100644 --- a/editor/src/Application.cpp +++ b/editor/src/Application.cpp @@ -194,7 +194,7 @@ bool Application::SwitchProject(const std::string& projectPath) { return false; } - m_imguiSession.SetProjectPath(projectPath); + const bool hasSavedDockLayout = m_imguiSession.SetProjectPath(projectPath); m_editorContext->SetProjectPath(projectPath); auto& logger = Debug::Logger::Get(); @@ -208,6 +208,11 @@ bool Application::SwitchProject(const std::string& projectPath) { m_lastWindowTitle.clear(); UpdateWindowTitle(); + + if (!hasSavedDockLayout) { + m_editorContext->GetEventBus().Publish(DockLayoutResetRequestedEvent{}); + } + return true; } diff --git a/editor/src/Layout/DockLayoutController.h b/editor/src/Layout/DockLayoutController.h index 680726a9..09cb2f9b 100644 --- a/editor/src/Layout/DockLayoutController.h +++ b/editor/src/Layout/DockLayoutController.h @@ -6,6 +6,7 @@ #include "UI/DockHostStyle.h" #include "UI/DockTabBarChrome.h" +#include #include #include @@ -24,6 +25,8 @@ public: [this](const DockLayoutResetRequestedEvent&) { RequestReset(); }); + m_layoutDirty = true; + m_forceRebuild = false; } void Detach() { @@ -34,10 +37,12 @@ public: m_context = nullptr; m_resetLayoutHandlerId = 0; m_layoutDirty = true; + m_forceRebuild = false; } void RequestReset() { m_layoutDirty = true; + m_forceRebuild = true; } void RenderDockspace() { @@ -65,8 +70,11 @@ public: } if (m_layoutDirty) { - BuildDefaultLayout(dockspaceId, viewport->Size); + if (m_forceRebuild || !HasSavedDockLayout()) { + BuildDefaultLayout(dockspaceId, viewport->Size); + } m_layoutDirty = false; + m_forceRebuild = false; } UI::ConfigureDockTabBarChrome(dockspaceId); @@ -74,6 +82,31 @@ public: } private: + static bool HasSavedDockLayout() { + if (ImGui::GetCurrentContext() == nullptr) { + return false; + } + + const char* iniFilename = ImGui::GetIO().IniFilename; + if (iniFilename == nullptr || iniFilename[0] == '\0') { + return false; + } + + std::ifstream input(iniFilename, std::ios::in); + if (!input.is_open()) { + return false; + } + + std::string line; + while (std::getline(input, line)) { + if (line == "[Docking][Data]") { + return true; + } + } + + return false; + } + void BuildDefaultLayout(ImGuiID dockspaceId, const ImVec2& dockspaceSize) { ImGui::DockBuilderRemoveNode(dockspaceId); ImGui::DockBuilderAddNode(dockspaceId, m_dockspaceFlags | ImGuiDockNodeFlags_DockSpace); @@ -97,6 +130,7 @@ private: IEditorContext* m_context = nullptr; uint64_t m_resetLayoutHandlerId = 0; bool m_layoutDirty = true; + bool m_forceRebuild = false; ImGuiDockNodeFlags m_dockspaceFlags = ImGuiDockNodeFlags_NoWindowMenuButton; }; diff --git a/editor/src/UI/ImGuiSession.h b/editor/src/UI/ImGuiSession.h index 807d4ac5..da48c94b 100644 --- a/editor/src/UI/ImGuiSession.h +++ b/editor/src/UI/ImGuiSession.h @@ -5,6 +5,7 @@ #include #include +#include #include namespace XCEngine { @@ -48,15 +49,17 @@ public: return m_iniPath; } - void SetProjectPath(const std::string& projectPath) { + bool SetProjectPath(const std::string& projectPath) { if (ImGui::GetCurrentContext() == nullptr) { - return; + return false; } SaveSettings(); ImGuiIO& io = ImGui::GetIO(); ConfigureIniFile(projectPath, io); + const bool hasSavedLayout = HasSavedDockLayoutOnDisk(m_iniPath); ImGui::LoadIniSettingsFromDisk(m_iniPath.c_str()); + return hasSavedLayout; } private: @@ -64,6 +67,27 @@ private: static constexpr const char* kPrimaryUiFontPath = "C:/Windows/Fonts/segoeui.ttf"; static constexpr const char* kChineseFallbackFontPath = "C:/Windows/Fonts/msyh.ttc"; + static bool HasSavedDockLayoutOnDisk(const std::filesystem::path& iniPath) { + std::error_code ec; + if (!std::filesystem::is_regular_file(iniPath, ec) || ec) { + return false; + } + + std::ifstream input(iniPath, std::ios::in); + if (!input.is_open()) { + return false; + } + + std::string line; + while (std::getline(input, line)) { + if (line == "[Docking][Data]") { + return true; + } + } + + return false; + } + void ConfigureIniFile(const std::string& projectPath, ImGuiIO& io) { const std::filesystem::path configDir = std::filesystem::path(projectPath) / ".xceditor"; std::error_code ec;