Files
XCEngine/docs/used/UI-Editor设计与实现.md
ssdfasd 16e2065c6c Unified logging: Replace LogSystem with EditorConsoleSink
- Created EditorConsoleSink (implements ILogSink interface)
- EditorConsoleSink stores logs in memory buffer (max 1000 entries)
- Added to Debug::Logger in Application::Initialize()
- ConsolePanel now reads from EditorConsoleSink via static GetInstance()
- Removed separate LogSystem singleton
- Removed editor/src/Core/LogEntry.h (no longer needed)

Now Editor and Engine share the same Debug::Logger, with ConsolePanel
displaying logs via EditorConsoleSink.
2026-03-25 16:13:02 +08:00

1056 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<T>` | ✅ 已实现 | 直接复用 |
| `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 <XCEngine/...>` 并使用
- 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<T> │ │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<T>` | 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<EntityID> children; // 子实体 ID 列表
std::vector<std::unique_ptr<Component>> components;
bool selected = false;
template<typename T, typename... Args>
T* AddComponent(Args&&... args) {
auto comp = std::make_unique<T>(std::forward<Args>(args)...);
comp->m_entity = this;
T* ptr = comp.get();
components.push_back(std::move(comp));
return ptr;
}
template<typename T>
T* GetComponent() {
for (auto& comp : components) {
if (auto casted = dynamic_cast<T*>(comp.get())) {
return casted;
}
}
return nullptr;
}
template<typename T>
std::vector<T*> GetComponents() {
std::vector<T*> result;
for (auto& comp : components) {
if (auto casted = dynamic_cast<T*>(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<std::unique_ptr<Component>>` 存储组件,支持多态
4. **选择状态**`selected` 成员用于追踪实体是否被选中
**与 Engine GameObject 的接口对齐**
| UI::Entity 接口 | Engine::GameObject 接口 | 对齐状态 |
|---------------|------------------------|---------|
| `id` | (无直接对应Engine 用指针) | 接口不同但功能一致 |
| `name` | `name` | ✅ 完全对齐 |
| `parent` | `GetParent()/SetParent()` | ✅ 功能对齐 |
| `children` | `GetChildren()` | ✅ 功能对齐 |
| `AddComponent<T>()` | `AddComponent<T>()` | ✅ 接口对齐 |
| `GetComponent<T>()` | `GetComponent<T>()` | ✅ 接口对齐 |
### 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<void(Component*)>;
struct ComponentInspectorInfo {
std::string name;
ComponentInspectorFn renderFn;
};
class ComponentRegistry {
public:
static ComponentRegistry& Get() {
static ComponentRegistry instance;
return instance;
}
template<typename T>
void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) {
m_inspectors[name] = {name, inspectorFn};
m_factories[name] = []() -> std::unique_ptr<Component> {
return std::make_unique<T>();
};
}
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<std::string, ComponentInspectorInfo> m_inspectors;
std::unordered_map<std::string, std::function<std::unique_ptr<Component>()>> m_factories;
};
```
**注册示例**(在 `InspectorPanel.cpp` 中):
```cpp
ComponentRegistry::Get().RegisterComponent<TransformComponent>(
"Transform",
[](Component* comp) {
auto* transform = dynamic_cast<TransformComponent*>(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<EntityID>& 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<EntityID> OnEntityCreated;
XCEngine::Core::Event<EntityID> OnEntityDeleted;
XCEngine::Core::Event<EntityID> OnEntityChanged;
XCEngine::Core::Event<> OnSceneChanged;
private:
EntityID m_nextEntityId = 1;
std::unordered_map<EntityID, Entity> m_entities;
std::vector<EntityID> m_rootEntities;
std::optional<ClipboardData> m_clipboard;
};
```
**关键设计决策**
1. **Singleton 模式**:通过 `static SceneManager& Get()` 提供全局访问点
2. **实体存储**`std::unordered_map<EntityID, Entity>` 提供 O(1) 的实体查找
3. **根实体列表**`m_rootEntities` 维护所有顶层实体,用于层级面板展示
4. **剪贴板支持**`std::optional<ClipboardData>` 支持复制/粘贴操作
5. **事件系统**:复用 Engine 的 `Event<T>` 实现观察者模式
**事件类型说明**
| 事件 | 签名 | 触发时机 |
|-----|------|---------|
| `OnEntityCreated` | `Event<EntityID>` | 创建新实体时 |
| `OnEntityDeleted` | `Event<EntityID>` | 删除实体时 |
| `OnEntityChanged` | `Event<EntityID>` | 实体属性变化时(重命名、父子关系变化) |
| `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<TransformComponent>(
"Transform",
[](Component* comp) {
auto* transform = dynamic_cast<TransformComponent*>(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<MeshRendererComponent>(
"Mesh Renderer",
[](Component* comp) {
auto* mesh = dynamic_cast<MeshRendererComponent*>(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<LogEntry> m_logs;
std::vector<LogEntry> 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<EntityID>& entities);
bool IsSelected(EntityID entity) const;
const std::vector<EntityID>& GetSelection() const { return m_selection; }
size_t GetSelectionCount() const { return m_selection.size(); }
XCEngine::Core::Event<EntityID> OnSelected;
XCEngine::Core::Event<EntityID> OnDeselected;
XCEngine::Core::Event<> OnSelectionCleared;
private:
SelectionManager() = default;
std::vector<EntityID> m_selection;
std::unordered_set<EntityID> 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<const LogEntry&> OnLog;
private:
LogSystem() = default;
std::vector<LogEntry> 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<T> 的复用
UI 编辑器直接复用 Engine 的事件系统:
```cpp
#include <XCEngine/Core/Event.h>
// 使用方式
XCEngine::Core::Event<EntityID> OnEntityCreated;
XCEngine::Core::Event<EntityID> OnEntityDeleted;
XCEngine::Core::Event<EntityID> OnEntityChanged;
XCEngine::Core::Event<> OnSceneChanged;
```
**订阅示例**
```cpp
// 在 Panel 初始化时订阅
SceneManager::Get().OnEntityCreated.AddLambda([this](EntityID id) {
// 处理实体创建
});
```
### 6.2 UI 编辑器事件类型
| 事件源 | 事件名 | 签名 | 说明 |
|-------|-------|------|------|
| `SceneManager` | `OnEntityCreated` | `Event<EntityID>` | 实体创建 |
| `SceneManager` | `OnEntityDeleted` | `Event<EntityID>` | 实体删除 |
| `SceneManager` | `OnEntityChanged` | `Event<EntityID>` | 实体属性变化 |
| `SceneManager` | `OnSceneChanged` | `Event<>` | 场景变化 |
| `SelectionManager` | `OnSelected` | `Event<EntityID>` | 实体被选中 |
| `SelectionManager` | `OnDeselected` | `Event<EntityID>` | 实体取消选中 |
| `SelectionManager` | `OnSelectionCleared` | `Event<>` | 选择被清空 |
| `LogSystem` | `OnLog` | `Event<const LogEntry&>` | 日志消息 |
### 6.3 事件处理时机
**同一帧内的事件处理**
```cpp
void Application::Render() {
// 1. 处理用户输入
// 2. 更新 Managers
SceneManager::Get().Update(deltaTime);
// 3. 清空pending列表ProcessUnsubscribes
// 4. 渲染 ImGui UI
RenderUI();
// 5. 渲染 D3D12
RenderD3D12();
}
```
**注意**`Event<T>::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<IAction> action);
void Undo();
void Redo();
bool CanUndo() const;
bool CanRedo() const;
private:
std::vector<std::unique_ptr<IAction>> m_undoStack;
std::vector<std::unique_ptr<IAction>> m_redoStack;
};
```
**支持的操作**
- 实体创建/删除
- 实体重命名
- 实体移动(父子关系变更)
- 组件添加/删除
- 属性修改
### 9.3 资源导入管线
**计划实现**
1. 资源文件监控(文件变化自动检测)
2. 资源导入器Mesh、Texture、Material 等)
3. 资源依赖解析
4. 资源热重载
### 9.4 预制体系统
**计划实现**
```cpp
class Prefab {
public:
String name;
std::vector<std::unique_ptr<Component>> components;
std::vector<Prefab> 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<T>` | N/A | Event.h | ✅ 直接复用 |
| `XCEngine::Debug::LogLevel` | N/A | LogLevel.h | ✅ 直接复用 |
---
## 附录 B事件类型清单
### SceneManager 事件
| 事件名 | 类型 | 参数 | 触发时机 |
|-------|------|------|---------|
| `OnEntityCreated` | `Event<EntityID>` | 新实体的 ID | `CreateEntity()` 成功后 |
| `OnEntityDeleted` | `Event<EntityID>` | 被删实体的 ID | `DeleteEntity()` 成功后 |
| `OnEntityChanged` | `Event<EntityID>` | 变化实体的 ID | `RenameEntity()``MoveEntity()` 等 |
| `OnSceneChanged` | `Event<>` | 无 | 场景整体变化时 |
### SelectionManager 事件
| 事件名 | 类型 | 参数 | 触发时机 |
|-------|------|------|---------|
| `OnSelected` | `Event<EntityID>` | 被选实体的 ID | `Select()` 时 |
| `OnDeselected` | `Event<EntityID>` | 取消选中的实体 ID | `Deselect()` 时 |
| `OnSelectionCleared` | `Event<>` | 无 | `ClearSelection()` 时 |
### LogSystem 事件
| 事件名 | 类型 | 参数 | 触发时机 |
|-------|------|------|---------|
| `OnLog` | `Event<const LogEntry&>` | 日志条目引用 | 任意日志产生时 |
---
## 附录 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 - 右下
---
**文档结束**