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

38 KiB
Raw Permalink Blame History

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

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

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 实现

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 实现

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 检视函数关联。

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 中):

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

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

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 窗口包装示例

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

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

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. 添加组件:显示可添加的组件类型列表

组件检视函数注册示例

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

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

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

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 的复用

UI 编辑器直接复用 Engine 的事件系统:

#include <XCEngine/Core/Event.h>

// 使用方式
XCEngine::Core::Event<EntityID> OnEntityCreated;
XCEngine::Core::Event<EntityID> OnEntityDeleted;
XCEngine::Core::Event<EntityID> OnEntityChanged;
XCEngine::Core::Event<> OnSceneChanged;

订阅示例

// 在 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 事件处理时机

同一帧内的事件处理

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 渲染管线

初始化

ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX12_Init(
    m_device,
    3,                              // 双缓冲帧数
    DXGI_FORMAT_R8G8B8A8_UNORM,    // 格式
    m_srvHeap,
    m_srvHeap->GetCPUDescriptorHandleForHeapStart(),
    m_srvHeap->GetGPUDescriptorHandleForHeapStart()
);

渲染

ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

// 渲染 ImGui UI
RenderUI();

ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_commandList);

7.3 渲染目标与交换链

配置

swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferCount = 3;       // 三重缓冲
swapChainDesc.SampleDesc.Count = 1;

_present 流程

m_swapChain->Present(1, 0);
m_fenceValue++;
m_commandQueue->Signal(m_fence, m_fenceValue);

第八章 主题与样式

8.1 Theme 系统

设计文件ui_editor/src/Theme.h/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 序列化/反序列化

计划实现

class SceneSerializer {
public:
    bool Serialize(Scene* scene, const String& filePath);
    bool Deserialize(Scene* scene, const String& filePath);
};

文件格式JSON 或二进制(待定)

9.2 撤销/重做系统

计划实现

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 预制体系统

计划实现

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 - 右下

文档结束