diff --git a/docs/plan/UI-Editor设计与实现.md b/docs/plan/UI-Editor设计与实现.md new file mode 100644 index 00000000..80d7c71a --- /dev/null +++ b/docs/plan/UI-Editor设计与实现.md @@ -0,0 +1,1055 @@ +# UI-Editor 设计与实现文档 + +> **版本**: 1.0 +> **日期**: 2026-03-20 +> **目标**: 为 XCEngine 游戏引擎搭建 UI 编辑器框架 + +--- + +## 第一章 概述 + +### 1.1 UI编辑器目标与定位 + +UI 编辑器是 XCEngine 游戏引擎的编辑器前端,用于可视化编辑游戏场景、场景层级、检视组件属性、控制台输出等核心功能。 + +**核心目标**: +1. 提供独立的 UI 编辑器可执行程序(基于 ImGui + D3D12) +2. UI 编辑器的数据结构与引擎核心类型对齐 +3. 引擎核心已有的类型直接复用,引擎核心未实现的则在 UI 编辑器中临时实现但保持接口一致 +4. 支持场景层级管理、实体创建删除、组件编辑等基础功能 + +**定位**: +- UI 编辑器作为引擎的独立模块,不直接耦合引擎渲染管线 +- 通过 Engine 核心的抽象接口与引擎通信 +- 当前阶段以独立开发为主,待引擎核心完善后进行对接 + +### 1.2 与引擎核心的对齐策略 + +| Engine 类型 | 状态 | UI 编辑器策略 | +|------------|------|-------------| +| `XCEngine::Core::Event` | ✅ 已实现 | 直接复用 | +| `XCEngine::Core::uint64` | ✅ 已实现 | 直接复用 | +| `XCEngine::Debug::Logger` | ✅ 已实现 | 直接复用 | +| `XCEngine::Debug::LogLevel` | ✅ 已实现 | 直接复用 | +| `XCEngine::Debug::LogEntry` | ✅ 已实现 | 直接复用 | +| `XCEngine::Math::Vector3` 等 | 仅有设计文档 | UI 编辑器临时实现但接口对齐 | +| `Component` | 仅有设计文档 | UI 编辑器自行实现 `UI::Component` | +| `GameObject` | 仅有设计文档 | UI 编辑器自行实现 `UI::Entity` | +| `TransformComponent` | 仅有设计文档 | UI 编辑器自行实现 `UI::TransformComponent` | +| `Scene` / `SceneManager` | 仅有设计文档 | UI 编辑器自行实现 `UI::SceneManager` | + +**对齐原则**: +- Engine 已有类型:直接 `#include ` 并使用 +- Engine 暂无类型:在 UI 编辑器中实现,但类名、成员变量、成员函数命名与设计文档保持一致 +- Engine 实现后:UI 编辑器可平滑迁移到 Engine 类型 + +### 1.3 技术选型 + +**渲染后端:D3D12** +- 与引擎核心渲染管线技术栈一致 +- 支持多窗口、多渲染目标 +- 提供高性能的 GPU 命令提交 + +**UI 框架:Dear ImGui** +- 轻量级、可扩展的即时模式 UI +- 支持主题定制 +- 成熟的 D3D12 集成示例 +- 高效的 UI 渲染管线 + +**架构模式:模块化 Manager + Panel** +- Manager:负责数据管理和业务逻辑 +- Panel:负责 UI 展示和用户交互 +- 清晰的职责分离便于维护和扩展 + +--- + +## 第二章 架构设计 + +### 2.1 整体架构图 + +``` +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ UI 编辑器架构 │ +└─────────────────────────────────────────────────────────────────────────────────────┘ + + ┌─────────────────┐ + │ Application │ 应用程序入口 + │ (D3D12 + ImGui)│ + └────────┬────────┘ + │ + ┌─────────────────────────────────┼─────────────────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Managers │ │ Panels │ │ Core Types │ +│ │ │ │ │ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │SceneManager │ │ │ │HierarchyPanel│ │ │ │ Entity │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │SelectionMgr │ │◀──────────────│ │InspectorPanel│ │ │ │ Component │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │ LogSystem │ │ │ │SceneViewPanel│ │ │ │ Theme │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ +│ │ProjectManager│ │ │ │GameViewPanel │ │ │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ +│ │ AssetItem │ │ │ │ConsolePanel │ │ │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ │ +│ │ │ ┌─────────────┐ │ │ │ +│ │ │ │ ProjectPanel│ │ │ │ +│ │ │ └─────────────┘ │ │ │ +│ │ │ ┌─────────────┐ │ │ │ +│ │ │ │ MenuBar │ │ │ │ +│ │ │ └─────────────┘ │ │ │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ + │ ┌───────────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ Engine Core (XCEngine) │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │Event │ │Logger │ │LogLevel │ │LogEntry │ │ +│ │(已实现复用) │ │(已实现复用) │ │(已实现复用) │ │(已实现复用) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │Math Types │ │Component │ │GameObject │ │Scene │ │ +│ │(设计文档) │ │(设计文档) │ │(设计文档) │ │(设计文档) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 目录结构 + +``` +ui_editor/ +├── CMakeLists.txt # 构建配置 +├── bin/ # 编译输出 +│ └── Release/ +│ └── XCVolumeRendererUI2.exe +├── build/ # 中间文件 +└── src/ + ├── main.cpp # 程序入口 + ├── Application.h/cpp # 应用程序类(D3D12 + ImGui) + │ + ├── Core/ # 核心数据类型 + │ ├── GameObject.h # Entity、Component、TransformComponent + │ ├── LogEntry.h # 日志条目(复用 Engine LogLevel) + │ └── AssetItem.h # 资产条目 + │ + ├── Managers/ # 管理器系统 + │ ├── SceneManager.h/cpp # 场景管理 + │ ├── SelectionManager.h # 选择管理 + │ ├── LogSystem.h/cpp # 日志系统 + │ └── ProjectManager.h/cpp # 项目管理 + │ + ├── panels/ # UI 面板 + │ ├── Panel.h/cpp # 面板基类 + │ ├── MenuBar.h/cpp # 菜单栏 + │ ├── HierarchyPanel.h/cpp # 层级面板 + │ ├── InspectorPanel.h/cpp # 检视面板 + │ ├── SceneViewPanel.h/cpp # 场景视图 + │ ├── GameViewPanel.h/cpp # 游戏视图 + │ ├── ConsolePanel.h/cpp # 控制台面板 + │ └── ProjectPanel.h/cpp # 项目面板 + │ + └── Theme.h/cpp # 主题样式 +``` + +### 2.3 核心类型与引擎核心的对齐映射表 + +| UI 编辑器类型 | 文件位置 | 对齐的 Engine 类型 | 说明 | +|-------------|---------|------------------|------| +| `UI::Entity` | Core/GameObject.h | `XCEngine::GameObject` | 实体,包含 ID、名称、层级关系、组件 | +| `UI::Component` | Core/GameObject.h | `XCEngine::Component` | 组件基类 | +| `UI::TransformComponent` | Core/GameObject.h | `XCEngine::TransformComponent` | 变换组件 | +| `UI::MeshRendererComponent` | Core/GameObject.h | `XCEngine::RenderMeshComponent` | 网格渲染组件 | +| `UI::EntityID` | Core/GameObject.h | `uint64_t` | 实体唯一标识符 | +| `UI::INVALID_ENTITY_ID` | Core/GameObject.h | N/A | 无效实体 ID 常量 | +| `UI::SceneManager` | Managers/SceneManager.h | `XCEngine::SceneManager` | 场景管理器 | +| `UI::LogSystem` | Managers/LogSystem.h | `XCEngine::Debug::Logger` | 日志系统 | +| `UI::LogEntry` | Core/LogEntry.h | `XCEngine::Debug::LogEntry` | 日志条目 | +| `XCEngine::Core::Event` | Engine/include/... | N/A | 直接复用引擎事件系统 | + +--- + +## 第三章 核心数据类型 + +### 3.1 Entity(对齐 Engine GameObject) + +`Entity` 是 UI 编辑器中的核心对象类型,对齐 Engine 的 `GameObject` 设计。 + +**设计文件**:`ui_editor/src/Core/GameObject.h` + +```cpp +namespace UI { + +using EntityID = uint64_t; +constexpr EntityID INVALID_ENTITY_ID = 0; + +class Entity { +public: + EntityID id = INVALID_ENTITY_ID; + std::string name; + EntityID parent = INVALID_ENTITY_ID; // 父实体 ID + std::vector children; // 子实体 ID 列表 + std::vector> components; + bool selected = false; + + template + T* AddComponent(Args&&... args) { + auto comp = std::make_unique(std::forward(args)...); + comp->m_entity = this; + T* ptr = comp.get(); + components.push_back(std::move(comp)); + return ptr; + } + + template + T* GetComponent() { + for (auto& comp : components) { + if (auto casted = dynamic_cast(comp.get())) { + return casted; + } + } + return nullptr; + } + + template + std::vector GetComponents() { + std::vector result; + for (auto& comp : components) { + if (auto casted = dynamic_cast(comp.get())) { + result.push_back(casted); + } + } + return result; + } +}; + +} // namespace UI +``` + +**关键设计决策**: + +1. **EntityID 类型**:使用 `uint64_t` 作为实体唯一标识,与 Engine 的 `uint64_t` 一致 +2. **父子关系**:通过 `parent` ID 和 `children` ID 列表维护层级关系,避免循环引用 +3. **组件存储**:使用 `std::vector>` 存储组件,支持多态 +4. **选择状态**:`selected` 成员用于追踪实体是否被选中 + +**与 Engine GameObject 的接口对齐**: + +| UI::Entity 接口 | Engine::GameObject 接口 | 对齐状态 | +|---------------|------------------------|---------| +| `id` | (无直接对应,Engine 用指针) | 接口不同但功能一致 | +| `name` | `name` | ✅ 完全对齐 | +| `parent` | `GetParent()/SetParent()` | ✅ 功能对齐 | +| `children` | `GetChildren()` | ✅ 功能对齐 | +| `AddComponent()` | `AddComponent()` | ✅ 接口对齐 | +| `GetComponent()` | `GetComponent()` | ✅ 接口对齐 | + +### 3.2 Component(对齐 Engine Component) + +**设计文件**:`ui_editor/src/Core/GameObject.h` + +```cpp +class Component { +public: + virtual ~Component() = default; + virtual std::string GetName() const = 0; + + virtual void Awake() {} + virtual void Start() {} + virtual void Update(float deltaTime) {} + virtual void OnDestroy() {} + + class Entity* GetEntity() const { return m_entity; } + bool IsEnabled() const { return m_enabled; } + void SetEnabled(bool enabled) { m_enabled = enabled; } + +protected: + class Entity* m_entity = nullptr; + bool m_enabled = true; + + friend class Entity; +}; +``` + +**生命周期函数**:对齐 Engine Component 的设计,包含 `Awake()`、`Start()`、`Update()`、`OnDestroy()` 等。 + +**TransformComponent 实现**: + +```cpp +class TransformComponent : public Component { +public: + float position[3] = {0.0f, 0.0f, 0.0f}; + float rotation[3] = {0.0f, 0.0f, 0.0f}; + float scale[3] = {1.0f, 1.0f, 1.0f}; + + std::string GetName() const override { return "Transform"; } +}; +``` + +**MeshRendererComponent 实现**: + +```cpp +class MeshRendererComponent : public Component { +public: + std::string materialName = "Default-Material"; + std::string meshName = ""; + + std::string GetName() const override { return "Mesh Renderer"; } +}; +``` + +### 3.3 ComponentRegistry(组件注册表) + +组件注册表用于将组件类型与对应的 ImGui 检视函数关联。 + +```cpp +using ComponentInspectorFn = std::function; + +struct ComponentInspectorInfo { + std::string name; + ComponentInspectorFn renderFn; +}; + +class ComponentRegistry { +public: + static ComponentRegistry& Get() { + static ComponentRegistry instance; + return instance; + } + + template + void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) { + m_inspectors[name] = {name, inspectorFn}; + m_factories[name] = []() -> std::unique_ptr { + return std::make_unique(); + }; + } + + ComponentInspectorInfo* GetInspector(const std::string& name) { + auto it = m_inspectors.find(name); + if (it != m_inspectors.end()) { + return &it->second; + } + return nullptr; + } + +private: + ComponentRegistry() = default; + std::unordered_map m_inspectors; + std::unordered_map()>> m_factories; +}; +``` + +**注册示例**(在 `InspectorPanel.cpp` 中): + +```cpp +ComponentRegistry::Get().RegisterComponent( + "Transform", + [](Component* comp) { + auto* transform = dynamic_cast(comp); + ImGui::InputFloat3("Position", transform->position); + ImGui::InputFloat3("Rotation", transform->rotation); + ImGui::InputFloat3("Scale", transform->scale); + } +); +``` + +### 3.4 SceneManager(对齐 Engine SceneManager) + +**设计文件**:`ui_editor/src/Managers/SceneManager.h` + +```cpp +class SceneManager { +public: + static SceneManager& Get() { + static SceneManager instance; + return instance; + } + + EntityID CreateEntity(const std::string& name, EntityID parent = INVALID_ENTITY_ID); + + Entity* GetEntity(EntityID id) { + auto it = m_entities.find(id); + if (it != m_entities.end()) { + return &it->second; + } + return nullptr; + } + + const std::vector& GetRootEntities() const { + return m_rootEntities; + } + + void DeleteEntity(EntityID id); + void RenameEntity(EntityID id, const std::string& newName); + void CopyEntity(EntityID id); + EntityID PasteEntity(EntityID parent = INVALID_ENTITY_ID); + EntityID DuplicateEntity(EntityID id); + void MoveEntity(EntityID id, EntityID newParent); + void CreateDemoScene(); + + XCEngine::Core::Event OnEntityCreated; + XCEngine::Core::Event OnEntityDeleted; + XCEngine::Core::Event OnEntityChanged; + XCEngine::Core::Event<> OnSceneChanged; + +private: + EntityID m_nextEntityId = 1; + std::unordered_map m_entities; + std::vector m_rootEntities; + std::optional m_clipboard; +}; +``` + +**关键设计决策**: + +1. **Singleton 模式**:通过 `static SceneManager& Get()` 提供全局访问点 +2. **实体存储**:`std::unordered_map` 提供 O(1) 的实体查找 +3. **根实体列表**:`m_rootEntities` 维护所有顶层实体,用于层级面板展示 +4. **剪贴板支持**:`std::optional` 支持复制/粘贴操作 +5. **事件系统**:复用 Engine 的 `Event` 实现观察者模式 + +**事件类型说明**: + +| 事件 | 签名 | 触发时机 | +|-----|------|---------| +| `OnEntityCreated` | `Event` | 创建新实体时 | +| `OnEntityDeleted` | `Event` | 删除实体时 | +| `OnEntityChanged` | `Event` | 实体属性变化时(重命名、父子关系变化) | +| `OnSceneChanged` | `Event<>` | 场景整体变化时 | + +--- + +## 第四章 面板系统 + +### 4.1 Panel 基类 + +所有面板继承自 `Panel` 基类,提供统一的接口。 + +**设计文件**:`ui_editor/src/panels/Panel.h` + +```cpp +class Panel { +public: + virtual ~Panel() = default; + + virtual void Initialize() {} + virtual void Render() = 0; + virtual void OnSceneChanged() {} + + const char* GetName() const { return m_name; } + bool IsVisible() const { return m_visible; } + void SetVisible(bool visible) { m_visible = visible; } + +protected: + const char* m_name = "Panel"; + bool m_visible = true; +}; +``` + +**ImGui 窗口包装示例**: + +```cpp +void HierarchyPanel::Render() { + if (!m_visible) return; + + ImGui::PushID(GetName()); + if (ImGui::Begin(GetName(), &m_visible, ImGuiWindowFlags_NoCollapse)) { + RenderContent(); + } + ImGui::End(); + ImGui::PopID(); +} +``` + +### 4.2 HierarchyPanel(层级面板) + +**职责**:展示场景层级结构,支持实体的创建、删除、拖拽排序、右键菜单。 + +**设计文件**:`ui_editor/src/panels/HierarchyPanel.h` + +```cpp +class HierarchyPanel : public Panel { +public: + void Initialize() override; + void OnSceneChanged() override; + +private: + void RenderContent(); + void RenderEntity(EntityID entity, int& nodeIndex); + void RenderContextMenu(EntityID entity); + void RenderCreateMenu(); +}; +``` + +**核心功能**: + +1. **树形结构展示**:递归渲染实体及其子实体 +2. **选中高亮**:选中的实体以高亮显示 +3. **拖拽排序**:支持通过拖拽改变实体顺序和父子关系 +4. **右键菜单**:创建、删除、复制、粘贴、重命名等操作 +5. **搜索过滤**:支持按名称搜索实体 + +**节点渲染流程**: + +``` +RenderEntity(EntityID id) + │ + ├── 获取实体指针 GetEntity(id) + │ + ├── 构建节点标签 [图标] [名称] [子节点数量] + │ + ├── 选中状态处理 + │ └── 点击时调用 SelectionManager::Select(id) + │ + ├── 展开/折叠状态 + │ + ├── 渲染子节点(递归) + │ └── for child in entity.children: RenderEntity(child) + │ + └── 渲染右键菜单(如果右键) +``` + +### 4.3 InspectorPanel(检视面板) + +**职责**:展示选中实体的所有组件及其属性,支持编辑。 + +**设计文件**:`ui_editor/src/panels/InspectorPanel.h` + +```cpp +class InspectorPanel : public Panel { +public: + void Initialize() override; + void OnSelectionChanged(); + +private: + void RenderContent(); + void RenderEntityHeader(Entity* entity); + void RenderComponent(Component* comp); + void RenderAddComponentMenu(); +}; +``` + +**核心功能**: + +1. **实体头信息**:显示实体名称,支持直接编辑 +2. **组件列表**:遍历实体的所有组件 +3. **组件检视**:调用 `ComponentRegistry` 获取检视函数并渲染 +4. **添加组件**:显示可添加的组件类型列表 + +**组件检视函数注册示例**: + +```cpp +void InspectorPanel::Initialize() { + ComponentRegistry::Get().RegisterComponent( + "Transform", + [](Component* comp) { + auto* transform = dynamic_cast(comp); + ImGui::InputFloat3("Position", transform->position); + if (ImGui::InputFloat3("Rotation", transform->rotation)) { + SceneManager::Get().GetEntity(transform->GetEntity()->id) + ->name = transform->GetEntity()->name; // 触发变更事件 + } + ImGui::InputFloat3("Scale", transform->scale, 1.0f); + } + ); + + ComponentRegistry::Get().RegisterComponent( + "Mesh Renderer", + [](Component* comp) { + auto* mesh = dynamic_cast(comp); + ImGui::InputText("Mesh", &mesh->meshName); + ImGui::InputText("Material", &mesh->materialName); + } + ); +} +``` + +### 4.4 SceneViewPanel(场景视图) + +**职责**:渲染场景视图窗口,提供视口控制。 + +**设计文件**:`ui_editor/src/panels/SceneViewPanel.h` + +**当前实现状态**:基础框架已搭建,待扩展。 + +**计划功能**: +- 视口渲染(通过 Engine 渲染管线) +- 相机控制(平移、旋转、缩放) +- Gizmos 渲染(变换、旋转、缩放工具) +- 网格和辅助线显示 + +### 4.5 GameViewPanel(游戏视图) + +**职责**:显示游戏运行时的画面。 + +**设计文件**:`ui_editor/src/panels/GameViewPanel.h` + +**当前实现状态**:基础框架已搭建,待与 Engine 渲染管线对接。 + +### 4.6 ConsolePanel(控制台) + +**职责**:显示日志系统收集的日志消息。 + +**设计文件**:`ui_editor/src/panels/ConsolePanel.h/cpp` + +```cpp +class ConsolePanel : public Panel { +public: + void Initialize() override; + void Clear(); + void OnLogMessage(const LogEntry& entry); + +private: + void RenderContent(); + void RenderLogEntry(const LogEntry& entry); + void RenderFilterBar(); + + std::vector m_logs; + std::vector m_filteredLogs; + bool m_autoScroll = true; + bool m_wordWrap = false; + XCEngine::Debug::LogLevel m_minLevel = XCEngine::Debug::LogLevel::Verbose; +}; +``` + +**核心功能**: + +1. **日志显示**:显示所有收集的日志条目 +2. **级别过滤**:通过下拉菜单筛选日志级别 +3. **自动滚动**:新日志自动滚动到底部 +4. **时间戳显示**:显示每条日志的时间戳 +5. **双击跳转**:双击日志可定位到相关实体(预留) + +### 4.7 ProjectPanel(项目面板) + +**职责**:浏览项目资源文件。 + +**设计文件**:`ui_editor/src/panels/ProjectPanel.h/cpp` + +**当前实现状态**:基础框架已搭建,待扩展资源导入功能。 + +--- + +## 第五章 管理器系统 + +### 5.1 SelectionManager(选择管理器) + +**设计文件**:`ui_editor/src/Managers/SelectionManager.h` + +```cpp +class SelectionManager { +public: + static SelectionManager& Get() { + static SelectionManager instance; + return instance; + } + + void Select(EntityID entity); + void Deselect(EntityID entity); + void ToggleSelection(EntityID entity); + void ClearSelection(); + void SetSelection(const std::vector& entities); + + bool IsSelected(EntityID entity) const; + const std::vector& GetSelection() const { return m_selection; } + size_t GetSelectionCount() const { return m_selection.size(); } + + XCEngine::Core::Event OnSelected; + XCEngine::Core::Event OnDeselected; + XCEngine::Core::Event<> OnSelectionCleared; + +private: + SelectionManager() = default; + std::vector m_selection; + std::unordered_set m_selectionSet; +}; +``` + +**关键设计决策**: + +1. **双向存储**:`m_selection` 保持顺序,`m_selectionSet` 提供 O(1) 查询 +2. **事件系统**:选择变化时触发对应事件 +3. **多选支持**:通过 `SetSelection` 支持批量选择 + +### 5.2 LogSystem(日志系统) + +**设计文件**:`ui_editor/src/Managers/LogSystem.h/cpp` + +```cpp +class LogSystem { +public: + static LogSystem& Get() { + static LogSystem instance; + return instance; + } + + void Initialize(); + void Shutdown(); + + void Log(XCEngine::Debug::LogLevel level, const std::string& message, + const std::string& file = "", int line = 0); + + void Info(const std::string& message) { Log(LogLevel::Info, message); } + void Warning(const std::string& message) { Log(LogLevel::Warning, message); } + void Error(const std::string& message) { Log(LogLevel::Error, message); } + + XCEngine::Core::Event OnLog; + +private: + LogSystem() = default; + std::vector m_logs; +}; +``` + +**日志流向**: + +``` +XCEngine::Debug::Logger (Engine) + │ + ▼ (通过自定义 LogSink 拦截) +UI::LogSystem::OnLog + │ + ▼ +ConsolePanel::OnLogMessage + │ + ▼ +显示到 ConsolePanel +``` + +### 5.3 ProjectManager(项目管理器) + +**设计文件**:`ui_editor/src/Managers/ProjectManager.h/cpp` + +**职责**: +- 管理项目根目录 +- 扫描和索引资源文件 +- 提供资源查找接口 + +--- + +## 第六章 事件系统 + +### 6.1 引擎 Event 的复用 + +UI 编辑器直接复用 Engine 的事件系统: + +```cpp +#include + +// 使用方式 +XCEngine::Core::Event OnEntityCreated; +XCEngine::Core::Event OnEntityDeleted; +XCEngine::Core::Event OnEntityChanged; +XCEngine::Core::Event<> OnSceneChanged; +``` + +**订阅示例**: + +```cpp +// 在 Panel 初始化时订阅 +SceneManager::Get().OnEntityCreated.AddLambda([this](EntityID id) { + // 处理实体创建 +}); +``` + +### 6.2 UI 编辑器事件类型 + +| 事件源 | 事件名 | 签名 | 说明 | +|-------|-------|------|------| +| `SceneManager` | `OnEntityCreated` | `Event` | 实体创建 | +| `SceneManager` | `OnEntityDeleted` | `Event` | 实体删除 | +| `SceneManager` | `OnEntityChanged` | `Event` | 实体属性变化 | +| `SceneManager` | `OnSceneChanged` | `Event<>` | 场景变化 | +| `SelectionManager` | `OnSelected` | `Event` | 实体被选中 | +| `SelectionManager` | `OnDeselected` | `Event` | 实体取消选中 | +| `SelectionManager` | `OnSelectionCleared` | `Event<>` | 选择被清空 | +| `LogSystem` | `OnLog` | `Event` | 日志消息 | + +### 6.3 事件处理时机 + +**同一帧内的事件处理**: + +```cpp +void Application::Render() { + // 1. 处理用户输入 + // 2. 更新 Managers + SceneManager::Get().Update(deltaTime); + + // 3. 清空pending列表(ProcessUnsubscribes) + // 4. 渲染 ImGui UI + RenderUI(); + + // 5. 渲染 D3D12 + RenderD3D12(); +} +``` + +**注意**:`Event::ProcessUnsubscribes()` 应在每帧适当位置调用,以确保安全的订阅取消。 + +--- + +## 第七章 渲染集成 + +### 7.1 D3D12 初始化流程 + +**设计文件**:`ui_editor/src/Application.cpp` + +``` +Initialize(HWND hwnd) + │ + ├── CreateDevice() + │ ├── D3D12CreateDevice() + │ ├── CreateCommandQueue() + │ ├── CreateCommandAllocator() + │ └── CreateCommandList() + │ + ├── CreateRenderTarget() + │ ├── CreateDescriptorHeap (RTV) + │ ├── CreateDescriptorHeap (SRV) + │ └── CreateRenderTargets (3个双缓冲) + │ + └── CreateFence() +``` + +### 7.2 ImGui 渲染管线 + +**初始化**: + +```cpp +ImGui_ImplWin32_Init(hwnd); +ImGui_ImplDX12_Init( + m_device, + 3, // 双缓冲帧数 + DXGI_FORMAT_R8G8B8A8_UNORM, // 格式 + m_srvHeap, + m_srvHeap->GetCPUDescriptorHandleForHeapStart(), + m_srvHeap->GetGPUDescriptorHandleForHeapStart() +); +``` + +**渲染**: + +```cpp +ImGui_ImplDX12_NewFrame(); +ImGui_ImplWin32_NewFrame(); +ImGui::NewFrame(); + +// 渲染 ImGui UI +RenderUI(); + +ImGui::EndFrame(); +ImGui::Render(); +ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_commandList); +``` + +### 7.3 渲染目标与交换链 + +**配置**: + +```cpp +swapChainDesc.Width = width; +swapChainDesc.Height = height; +swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; +swapChainDesc.BufferCount = 3; // 三重缓冲 +swapChainDesc.SampleDesc.Count = 1; +``` + +**_present 流程**: + +```cpp +m_swapChain->Present(1, 0); +m_fenceValue++; +m_commandQueue->Signal(m_fence, m_fenceValue); +``` + +--- + +## 第八章 主题与样式 + +### 8.1 Theme 系统 + +**设计文件**:`ui_editor/src/Theme.h/cpp` + +```cpp +struct Theme { + ImVec4 colors[ImGuiCol_COUNT]; + + void Apply(); + void LoadDefault(); + void LoadDark(); + void LoadLight(); +}; + +extern Theme g_theme; +``` + +**默认深色主题配色**: + +| 用途 | 颜色 (RGB) | +|-----|-----------| +| 背景 | (0.1, 0.1, 0.1) | +| 面板背景 | (0.15, 0.15, 0.15) | +| 边框 | (0.3, 0.3, 0.3) | +| 文字 | (0.9, 0.9, 0.9) | +| 选中 | (0.2, 0.4, 0.8) | +| 警告 | (0.9, 0.6, 0.2) | +| 错误 | (0.9, 0.2, 0.2) | + +--- + +## 第九章 未来扩展计划 + +### 9.1 序列化/反序列化 + +**计划实现**: + +```cpp +class SceneSerializer { +public: + bool Serialize(Scene* scene, const String& filePath); + bool Deserialize(Scene* scene, const String& filePath); +}; +``` + +**文件格式**:JSON 或二进制(待定) + +### 9.2 撤销/重做系统 + +**计划实现**: + +```cpp +class UndoSystem { +public: + void PushAction(std::unique_ptr action); + void Undo(); + void Redo(); + bool CanUndo() const; + bool CanRedo() const; + +private: + std::vector> m_undoStack; + std::vector> m_redoStack; +}; +``` + +**支持的操作**: +- 实体创建/删除 +- 实体重命名 +- 实体移动(父子关系变更) +- 组件添加/删除 +- 属性修改 + +### 9.3 资源导入管线 + +**计划实现**: + +1. 资源文件监控(文件变化自动检测) +2. 资源导入器(Mesh、Texture、Material 等) +3. 资源依赖解析 +4. 资源热重载 + +### 9.4 预制体系统 + +**计划实现**: + +```cpp +class Prefab { +public: + String name; + std::vector> components; + std::vector children; +}; +``` + +--- + +## 附录 A:核心类型对齐详细对照表 + +| UI 编辑器类型/接口 | Engine 类型/接口 | 文件位置 | 对齐状态 | +|------------------|----------------|---------|---------| +| `UI::Entity` | `XCEngine::GameObject` | GameObject.h / GameObject.h | ✅ 接口对齐 | +| `UI::EntityID` | `uint64_t` | GameObject.h / Types.h | ✅ 完全一致 | +| `UI::INVALID_ENTITY_ID = 0` | N/A | GameObject.h | ✅ 自定义常量 | +| `UI::Component` | `XCEngine::Component` | GameObject.h / Component.h | ✅ 接口对齐 | +| `UI::Component::GetEntity()` | `Component::gameObject()` | GameObject.h / Component.h | ✅ 功能一致 | +| `UI::TransformComponent` | `XCEngine::TransformComponent` | GameObject.h / TransformComponent.h | ✅ 接口对齐 | +| `UI::TransformComponent::position` | `TransformComponent::GetPosition()` | GameObject.h / TransformComponent.h | ✅ 成员/方法对齐 | +| `UI::SceneManager` | `XCEngine::SceneManager` | SceneManager.h / SceneManager.h | ✅ 接口对齐 | +| `UI::SceneManager::CreateEntity()` | `SceneManager::CreateScene()` (不同) | SceneManager.h | ⚠️ 接口有差异 | +| `UI::LogSystem` | `XCEngine::Debug::Logger` | LogSystem.h / Logger.h | ✅ 功能复用 | +| `UI::LogEntry` | `XCEngine::Debug::LogEntry` | LogEntry.h / LogEntry.h | ✅ 复用 Engine | +| `XCEngine::Core::Event` | N/A | Event.h | ✅ 直接复用 | +| `XCEngine::Debug::LogLevel` | N/A | LogLevel.h | ✅ 直接复用 | + +--- + +## 附录 B:事件类型清单 + +### SceneManager 事件 + +| 事件名 | 类型 | 参数 | 触发时机 | +|-------|------|------|---------| +| `OnEntityCreated` | `Event` | 新实体的 ID | `CreateEntity()` 成功后 | +| `OnEntityDeleted` | `Event` | 被删实体的 ID | `DeleteEntity()` 成功后 | +| `OnEntityChanged` | `Event` | 变化实体的 ID | `RenameEntity()`、`MoveEntity()` 等 | +| `OnSceneChanged` | `Event<>` | 无 | 场景整体变化时 | + +### SelectionManager 事件 + +| 事件名 | 类型 | 参数 | 触发时机 | +|-------|------|------|---------| +| `OnSelected` | `Event` | 被选实体的 ID | `Select()` 时 | +| `OnDeselected` | `Event` | 取消选中的实体 ID | `Deselect()` 时 | +| `OnSelectionCleared` | `Event<>` | 无 | `ClearSelection()` 时 | + +### LogSystem 事件 + +| 事件名 | 类型 | 参数 | 触发时机 | +|-------|------|------|---------| +| `OnLog` | `Event` | 日志条目引用 | 任意日志产生时 | + +--- + +## 附录 C:面板布局配置 + +**默认布局**(通过 ImGui Dockspace 实现): + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ MenuBar │ +├──────────────┬─────────────────────────────────┬─────────────────┤ +│ │ │ │ +│ Hierarchy │ SceneView │ Inspector │ +│ Panel │ Panel │ Panel │ +│ │ │ │ +│ (200px) │ (flex) │ (250px) │ +│ │ │ │ +├──────────────┼─────────────────────────────────┼─────────────────┤ +│ │ │ │ +│ Project │ GameView │ Console │ +│ Panel │ Panel │ Panel │ +│ │ │ │ +│ (200px) │ (flex) │ (150px) │ +│ │ │ │ +└──────────────┴─────────────────────────────────┴─────────────────┘ +``` + +**Dock 优先级**: +1. HierarchyPanel - 左上 +2. SceneViewPanel - 中上 +3. InspectorPanel - 右上 +4. ProjectPanel - 左下 +5. GameViewPanel - 中下 +6. ConsolePanel - 右下 + +--- + +**文档结束**