- 更正: Engine 核心已有完整组件系统,Editor Inspector 只是未完善 - 补充: Editor 和 Engine 使用两套不同的 GameObject/Component 系统 (重大架构问题) - 补充: Scene 序列化依赖描述修正 - 补充: 架构问题中新增 Editor/Engine 系统差异分析
941 lines
26 KiB
Markdown
941 lines
26 KiB
Markdown
# XCEngine Editor 设计分析与改进计划
|
||
|
||
## 1. 项目概述
|
||
|
||
### 1.1 当前状态
|
||
|
||
XCEngine Editor 是一个基于 ImGui 的 Unity 风格编辑器 UI,目前具备以下基础功能:
|
||
|
||
- **渲染基础**: DirectX 12 + ImGui 对接
|
||
- **面板框架**: Docking 布局系统
|
||
- **UI 主题**: Unity 风格深色主题
|
||
|
||
### 1.2 对比参考
|
||
|
||
参考项目 Fermion Boson Editor 是一个功能完整的游戏引擎编辑器,具有:
|
||
- 完整的 3D Viewport
|
||
- 场景层级系统
|
||
- 组件检查器
|
||
- 资源浏览器
|
||
- 材质编辑器
|
||
- Play/Edit/Simulate 模式切换
|
||
|
||
---
|
||
|
||
## 2. 整体架构对比
|
||
|
||
### 2.1 架构图
|
||
|
||
**Fermion 架构**:
|
||
```
|
||
Fermion::Application
|
||
└── LayerStack
|
||
├── ImGuiLayer (overlay)
|
||
└── BosonLayer (editor layer)
|
||
├── ViewportPanel (3D viewport + gizmos)
|
||
├── SceneHierarchyPanel (entity tree)
|
||
│ └── InspectorPanel (embedded, component editor)
|
||
├── ContentBrowserPanel (asset browser)
|
||
├── MaterialEditorPanel (node-based material)
|
||
├── SettingsPanel (editor settings)
|
||
├── OverlayRenderPanel (physics debug)
|
||
└── MenuBarPanel (menu bar)
|
||
```
|
||
|
||
**XCEngine 架构**:
|
||
```
|
||
UI::Application
|
||
└── Panels (独立 Panel 类)
|
||
├── MenuBar
|
||
├── HierarchyPanel
|
||
├── InspectorPanel
|
||
├── SceneViewPanel (占位符)
|
||
├── GameViewPanel (占位符)
|
||
├── ProjectPanel
|
||
└── ConsolePanel
|
||
```
|
||
|
||
### 2.2 关键差异
|
||
|
||
| 方面 | Fermion | XCEngine |
|
||
|------|---------|----------|
|
||
| Layer 系统 | Application → LayerStack → BosonLayer | Application 直接管理 Panels |
|
||
| Panel 集成 | SceneHierarchy 内嵌 InspectorPanel | 各 Panel 独立 |
|
||
| Scene 管理 | BosonLayer 持有 Scene/SceneRenderer | SceneManager 单例 |
|
||
| 渲染集成 | BosonLayer → SceneRenderer → Framebuffer | 无对接 |
|
||
| 事件系统 | Layer::onEvent 统一分发 | 各 Panel 独立处理 |
|
||
|
||
---
|
||
|
||
## 3. 各面板详细分析
|
||
|
||
### 3.1 SceneHierarchyPanel / HierarchyPanel
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion | XCEngine | 状态 |
|
||
|------|---------|----------|------|
|
||
| 树节点渲染 | ✅ `TreeNodeEx` + UUID | ✅ `TreeNodeEx` + EntityID | 完成 |
|
||
| 选中高亮 | ✅ | ✅ | 完成 |
|
||
| 展开/折叠 | ✅ 自动记忆状态 | ✅ `isOpen` 状态 | 完成 |
|
||
| 重命名 | ✅ 双击触发 | ⚠️ 有 bug | 需修复 |
|
||
| 拖拽重排 | ✅ 完整 + 循环检测 | ⚠️ 基本实现 | 需完善 |
|
||
| 右键菜单 | ✅ Create Child, Detach, Delete | ✅ Create, Rename, Delete, Copy/Paste, Duplicate | 需补充 |
|
||
| 空区域点击 | ✅ 取消选中 | ✅ 取消选中 | 完成 |
|
||
| 嵌入 Inspector | ✅ Panel 内嵌 InspectorPanel | ❌ 分离 | 架构差异 |
|
||
|
||
#### XCEngine 问题详解
|
||
|
||
**问题 1: 重命名逻辑 bug**
|
||
|
||
`HierarchyPanel.cpp` lines 106-113:
|
||
```cpp
|
||
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) {
|
||
if (strlen(m_renameBuffer) > 0) {
|
||
sceneManager.RenameEntity(id, m_renameBuffer);
|
||
}
|
||
m_renaming = false;
|
||
m_renamingEntity = INVALID_ENTITY_ID;
|
||
}
|
||
```
|
||
|
||
问题:点击 InputText 外部时,`IsItemActive()` 已经变为 false,此时 `IsMouseClicked(0)` 也已经错过。
|
||
|
||
**问题 2: 缺少 "Create Child" 选项**
|
||
|
||
右键菜单只有:
|
||
- Create → Empty Object, Camera, Light, Cube, Sphere, Plane
|
||
- Rename, Delete
|
||
- Copy, Paste, Duplicate
|
||
|
||
缺少 "Create Child" 选项来在选中物体下创建子物体。
|
||
|
||
**问题 3: 没有 "Detach from Parent" 选项**
|
||
|
||
无法将子物体脱离父物体,直接变为根层级。
|
||
|
||
---
|
||
|
||
### 3.2 InspectorPanel
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion (1173 行) | XCEngine (94 行) | 状态 |
|
||
|------|-------------------|------------------|------|
|
||
| 组件显示 | ✅ 模板系统 | ⚠️ 只实现 2 种组件 (Engine 有完整组件库) | 需完善 |
|
||
| 动态增删组件 | ✅ 分类菜单 | ❌ 无 | 需实现 |
|
||
| 删除组件 | ✅ 右键 Remove | ❌ 无 | 需实现 |
|
||
| Transform 编辑 | ✅ `drawVec3Control` | ⚠️ `DragFloat3` 简陋 | 需改进 |
|
||
| Mesh 编辑 | ✅ Drag-drop + popup | ⚠️ 只有 InputText | 需改进 |
|
||
| 材质预览 | ✅ 缩略图渲染 | ❌ 无 | 需实现 |
|
||
| Camera 编辑 | ✅ 完整 | ❌ 无 | 需实现 |
|
||
| Light 编辑 | ✅ D/P/S Light | ❌ 无 | 需实现 |
|
||
| Physics 编辑 | ✅ 完整 | ❌ 无 | 需实现 |
|
||
| Script 编辑 | ✅ 字段编辑 | ❌ 无 | 需实现 |
|
||
| Entity Picking | ✅ 关节连接 | ❌ 无 | 需实现 |
|
||
|
||
#### XCEngine 实现现状
|
||
|
||
`InspectorPanel.cpp` lines 44-92:
|
||
```cpp
|
||
void InspectorPanel::RenderComponent(Component* component) {
|
||
if (auto* transform = dynamic_cast<TransformComponent*>(component)) {
|
||
ImGui::DragFloat3("##Position", transform->position, 0.1f);
|
||
ImGui::DragFloat3("##Rotation", transform->rotation, 1.0f);
|
||
ImGui::DragFloat3("##Scale", transform->scale, 0.1f);
|
||
}
|
||
else if (auto* meshRenderer = dynamic_cast<MeshRendererComponent*>(component)) {
|
||
// 只有 InputText,没有预览,没有拖拽
|
||
}
|
||
}
|
||
```
|
||
|
||
**主要问题**:
|
||
1. Editor Inspector 面板只实现了 Transform 和 MeshRenderer 显示编辑,但 Engine 核心已有完整组件系统
|
||
2. 没有 Add Component 菜单
|
||
3. 没有 Remove Component 功能
|
||
4. 没有 CollapsingHeader 折叠
|
||
5. 布局简陋,没有缩进和对齐
|
||
|
||
---
|
||
|
||
### 3.3 ProjectPanel / ContentBrowserPanel
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion | XCEngine | 状态 |
|
||
|------|---------|----------|------|
|
||
| 布局 | ✅ 两列 (树 + 网格) | ⚠️ 只有网格 | 需补充 |
|
||
| 文件夹树 | ✅ 左侧导航树 | ❌ 无 | 需实现 |
|
||
| 缩略图 | ✅ 加载 Texture | ⚠️ 彩色方块 | 需改进 |
|
||
| 材质预览 | ✅ 缩略图渲染 | ❌ 无 | 需实现 |
|
||
| 拖拽移动 | ✅ 完整实现 | ⚠️ stubbed | 需修复 |
|
||
| 双击打开 | ✅ 打开文件夹 | ✅ 实现 | 完成 |
|
||
| 面包屑导航 | ✅ 路径按钮 | ✅ 实现 | 完成 |
|
||
| 搜索过滤 | ✅ 实现 | ✅ 实现 | 完成 |
|
||
|
||
#### XCEngine 问题详解
|
||
|
||
**问题: HandleDrop() 返回 false**
|
||
|
||
`ProjectPanel.cpp` line 294:
|
||
```cpp
|
||
bool ProjectPanel::HandleDrop(const AssetItemPtr& targetFolder) {
|
||
return false; // STUBBED OUT - 拖拽移动功能不工作
|
||
}
|
||
```
|
||
|
||
虽然 `RenderAssetItem()` 中有拖拽目标代码,但实际上 `HandleDrop()` 从未被调用,拖拽移动功能完全失效。
|
||
|
||
---
|
||
|
||
### 3.4 MenuBar
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion (271 行) | XCEngine (55 行) | 状态 |
|
||
|------|------------------|-------------------|------|
|
||
| 实现方式 | ✅ 自定义窗口边框 | ✅ `BeginMainMenuBar` | 完成 |
|
||
| 菜单项 | ✅ 实际回调 | ❌ **全部 stubbed** | 需实现 |
|
||
| 项目操作 | ✅ new/open/save | ❌ 无 | 需实现 |
|
||
| 创建菜单 | ✅ Material/Texture | ❌ 无 | 需实现 |
|
||
| 窗口控制 | ✅ 有 (已注释) | ❌ 无 | 可选 |
|
||
|
||
#### XCEngine 问题详解
|
||
|
||
**所有菜单项都是空的**:
|
||
```cpp
|
||
// MenuBar.cpp
|
||
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {} // 空
|
||
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {} // 空
|
||
if (ImGui::MenuItem("Save Scene", "Ctrl+S")) {} // 空
|
||
// ... 所有项都是空的
|
||
```
|
||
|
||
---
|
||
|
||
### 3.5 ConsolePanel
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion (84 行) | XCEngine (70 行) | 状态 |
|
||
|------|------------------|-------------------|------|
|
||
| 日志显示 | ✅ 彩色 + 前缀 | ✅ 彩色 + 前缀 | 完成 |
|
||
| 命令输入 | ✅ 底部输入框 | ❌ 无 | 需补充 |
|
||
| 命令处理 | ✅ clear/help | ❌ 无 | 需实现 |
|
||
| 自动滚动 | ✅ 新日志时滚动 | ⚠️ flag 设置但逻辑不完整 | 需改进 |
|
||
|
||
#### XCEngine 优点
|
||
|
||
- 测试按钮注入日志功能完善
|
||
- 日志级别颜色区分正确
|
||
- 基本显示功能正常
|
||
|
||
---
|
||
|
||
### 3.6 SceneViewPanel / ViewportPanel
|
||
|
||
#### 功能对比
|
||
|
||
| 功能 | Fermion (356 行) | XCEngine (54 行) | 状态 |
|
||
|------|------------------|-------------------|------|
|
||
| 3D 渲染 | ✅ Framebuffer | ❌ **只有网格** | 需重构 |
|
||
| 相机 | ✅ EditorCamera | ❌ 无 | 需实现 |
|
||
| 鼠标拾取 | ✅ readPixel | ❌ 无 | 需实现 |
|
||
| Gizmo | ✅ ImGuizmo | ❌ 无 | 需实现 |
|
||
| 工具栏 | ✅ Q/W/E/R | ❌ 无 | 需实现 |
|
||
| Play 控制 | ✅ Play/Stop/Pause/Step | ❌ 无 | 需实现 |
|
||
| 状态切换 | ✅ Edit/Play/Simulate | ❌ 无 | 需实现 |
|
||
|
||
#### XCEngine 实现现状
|
||
|
||
```cpp
|
||
// SceneViewPanel.cpp
|
||
void SceneViewPanel::RenderGrid() {
|
||
// 只画了 50px 网格背景
|
||
for (float x = 0; x < canvasSize.x; x += gridSize) {
|
||
drawList->AddLine(...);
|
||
}
|
||
// 没有任何 3D 渲染
|
||
}
|
||
```
|
||
|
||
**问题**: 完全没有任何 3D 渲染能力,只是占位符。
|
||
|
||
---
|
||
|
||
### 3.7 GameViewPanel
|
||
|
||
| 功能 | Fermion | XCEngine | 状态 |
|
||
|------|---------|----------|------|
|
||
| 游戏视图 | ✅ Framebuffer 渲染 | ❌ **纯占位符** | 需重构 |
|
||
| 状态栏 | ✅ Play/Simulate 指示 | ❌ 无 | 需实现 |
|
||
|
||
---
|
||
|
||
## 4. XCEngine 缺失的面板
|
||
|
||
XCEngine Editor 只有 7 个面板,而 Fermion 有 10 个。以下是缺失的面板:
|
||
|
||
### 4.1 SettingsPanel - 编辑器设置
|
||
|
||
**Fermion 功能**:
|
||
- Renderer Info: 相机设置、设备信息、帧时间统计
|
||
- Environment Settings: Skybox、阴影、IBL、HDR 加载、环境光强度、法线强度
|
||
- Debug Settings: 渲染模式 (Forward/Deferred Hybrid)、GBuffer 调试、深度视图、物理调试开关、无限网格、轮廓设置
|
||
- Project Settings: 项目信息、默认字体配置
|
||
|
||
**XCEngine 状态**: 无此面板
|
||
|
||
**实现建议**: 可以作为 InspectorPanel 的扩展,或者单独的设置浮窗
|
||
|
||
---
|
||
|
||
### 4.2 OverlayRenderPanel - 调试可视化
|
||
|
||
**Fermion 功能**:
|
||
```cpp
|
||
class OverlayRenderPanel {
|
||
void render(const Context &ctx) const;
|
||
void renderPhysicsColliders(); // 物理碰撞体可视化
|
||
void renderPhysics2DColliders(); // 2D 碰撞体
|
||
void renderPhysics3DColliders(); // 3D 碰撞体
|
||
void renderJoints(); // 关节连接可视化
|
||
void renderSelectedEntityOutline(); // 选中物体轮廓
|
||
};
|
||
```
|
||
|
||
**功能说明**:
|
||
- 在 Viewport 上叠加渲染物理调试信息
|
||
- 2D 碰撞体: Box、Circle、BoxSensor、CircleSensor
|
||
- 3D 碰撞体: Box、Sphere、Capsule、Mesh (三角形线框)
|
||
- 关节: RevoluteJoint (锚点圆)、DistanceJoint (锚点圆 + 线段)
|
||
- 选中物体白色轮廓
|
||
|
||
**XCEngine 状态**: 无此面板,但可以在 SceneViewPanel 完善后添加
|
||
|
||
---
|
||
|
||
### 4.3 MaterialEditorPanel - 材质编辑器
|
||
|
||
**Fermion 功能**:
|
||
- 基于 `ax::NodeEditor` (imnodes) 的节点式材质编辑器
|
||
- PBR Output 节点 (ID=1) 固定在右侧
|
||
- Texture 节点可动态创建
|
||
- 引脚连接系统 (Pin ID 约定: `nodeID*100 + pinIndex`)
|
||
- 材质预览渲染 (`MaterialPreviewRenderer`)
|
||
- 材质编译 (`compileMaterial()`)
|
||
|
||
**节点系统**:
|
||
```cpp
|
||
// PBR Output 节点输入引脚
|
||
enum PBRInputPin {
|
||
Albedo = 1, // 引脚 ID = 101
|
||
Normal = 2, // 引脚 ID = 102
|
||
Metallic = 3, // 引脚 ID = 103
|
||
Roughness = 4,// 引脚 ID = 104
|
||
AO = 5 // 引脚 ID = 105
|
||
};
|
||
|
||
// Texture 节点输出引脚
|
||
// 引脚 ID = nodeID * 100 + 1
|
||
```
|
||
|
||
**UI 布局**:
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ [Texture Node] ──────→ [Albedo] │
|
||
│ [Texture Node] ──────→ [Normal] │
|
||
│ [Texture Node] ──────→ [PBR Output] → [Material] │
|
||
│ → [Metallic] │
|
||
│ → [Roughness] │
|
||
│ → [AO] │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**XCEngine 状态**: 无此面板,需要独立开发
|
||
|
||
**实现难度**: 高,需要 imnodes 库集成和材质编译系统
|
||
|
||
---
|
||
|
||
### 4.4 TextureConfigPanel - 纹理配置
|
||
|
||
**Fermion 功能**:
|
||
```cpp
|
||
class TextureConfigPanel {
|
||
void loadTexture(const std::filesystem::path &ftexPath);
|
||
void loadTextures(const vector<path> &ftexPaths);
|
||
void saveTexture(TextureConfigData &data);
|
||
void saveAllTextures();
|
||
|
||
struct TextureConfigData {
|
||
std::filesystem::path FtexPath;
|
||
std::string Name;
|
||
TextureAssetSpecification Spec;
|
||
bool Modified = false;
|
||
};
|
||
|
||
bool m_BatchMode = false; // 批量配置模式
|
||
TextureAssetSpecification m_BatchSpec;
|
||
};
|
||
```
|
||
|
||
**功能**:
|
||
- 批量纹理加载
|
||
- 纹理规格编辑 (格式、过滤器、Mipmaps 等)
|
||
- 保存/导出功能
|
||
|
||
**XCEngine 状态**: 无此面板,ProjectPanel 只做文件浏览
|
||
|
||
---
|
||
|
||
### 4.5 AssetManagerPanel - 资源注册表
|
||
|
||
**Fermion 功能**:
|
||
```cpp
|
||
class AssetManagerPanel {
|
||
void onImGuiRender();
|
||
// 显示所有注册的资源
|
||
// 可搜索、可过滤
|
||
// Asset 类型过滤
|
||
// Load/Unload 按钮
|
||
// 显示: asset path, type, handle ID, loading status
|
||
};
|
||
```
|
||
|
||
**功能**:
|
||
- 查看所有已注册资产
|
||
- 按类型过滤 (Texture, Mesh, Material, etc.)
|
||
- 搜索功能
|
||
- 手动加载/卸载资产
|
||
- 显示资源路径、类型、句柄 ID、加载状态
|
||
|
||
**XCEngine 状态**: 无此面板,ProjectPanel 只做文件系统浏览
|
||
|
||
---
|
||
|
||
## 5. 核心系统差异分析
|
||
|
||
### 5.1 Application 架构对比
|
||
|
||
**Fermion Application**:
|
||
```cpp
|
||
class Application {
|
||
std::unique_ptr<IWindow> m_window;
|
||
std::unique_ptr<ImGuiLayer> m_imGuiLayer;
|
||
std::unique_ptr<LayerStack> m_layerStack;
|
||
|
||
void pushLayer(std::unique_ptr<Layer> layer); // 在 ImGui 之前更新
|
||
void pushOverlay(std::unique_ptr<Layer> overlay); // 在 ImGui 之后更新
|
||
};
|
||
```
|
||
|
||
**XCEngine Application**:
|
||
```cpp
|
||
class Application {
|
||
HWND m_hwnd;
|
||
ID3D12Device* m_device;
|
||
// 直接管理所有 Panels
|
||
std::unique_ptr<MenuBar> m_menuBar;
|
||
std::unique_ptr<HierarchyPanel> m_hierarchyPanel;
|
||
// ...
|
||
};
|
||
```
|
||
|
||
**关键差异**:
|
||
1. Fermion 使用 Layer/Overlay 模式,事件按倒序传播
|
||
2. XCEngine 直接管理 Panels,缺乏层次化设计
|
||
3. Fermion 有 ImGuiLayer 专门处理 ImGui 事件阻塞
|
||
4. XCEngine 需要手动在 Panel 内部处理焦点判断
|
||
|
||
---
|
||
|
||
### 5.2 SceneManager vs Scene/EntityManager
|
||
|
||
**XCEngine SceneManager**:
|
||
```cpp
|
||
class SceneManager {
|
||
std::unordered_map<EntityID, GameObject> m_entities;
|
||
std::vector<EntityID> m_rootEntities;
|
||
|
||
EntityID CreateEntity(name, parent);
|
||
void DeleteEntity(id);
|
||
void MoveEntity(id, newParent);
|
||
EntityID CopyEntity(id);
|
||
EntityID PasteEntity(parent);
|
||
};
|
||
```
|
||
|
||
**Fermion Scene + EntityManager**:
|
||
```cpp
|
||
class Scene {
|
||
std::unique_ptr<EntityManager> m_entityManager;
|
||
std::unique_ptr<Physics2DWorld> m_physicsWorld2D;
|
||
std::unique_ptr<Physics3DWorld> m_physicsWorld3D;
|
||
};
|
||
|
||
class EntityManager {
|
||
entt::registry m_registry; // EnTT ECS
|
||
std::unordered_map<UUID, entt::entity> m_entityMap;
|
||
};
|
||
```
|
||
|
||
**XCEngine 实际情况**:
|
||
1. ✅ 有 Scene 类和 SceneManager (见 engine/include/XCEngine/Scene/)
|
||
2. ❌ 没有物理世界集成
|
||
3. ✅ 有 Component/GameObject 系统,但非 EnTT ECS (使用 dynamic_cast)
|
||
4. ✅ EntityID 是 uint64_t 递增整数,不是 UUID
|
||
5. ❌ Editor 没有场景状态 (Edit/Play/Simulate) 切换机制
|
||
|
||
---
|
||
|
||
### 5.3 BosonUI 自定义控件
|
||
|
||
Fermion 定义了 `ui` 命名空间的自定义控件,XCEngine 没有:
|
||
|
||
**Fermion ui 控件**:
|
||
```cpp
|
||
namespace ui {
|
||
// 向量编辑器 (带 XYZ 标签和 reset 按钮)
|
||
void drawVec3Control(const char* label, glm::vec3& values,
|
||
float resetValue = 0.0f, float columnWidth = 120.0f);
|
||
|
||
// 浮点数编辑器
|
||
bool drawFloatControl(const char* label, float& value,
|
||
float columnWidth = 120.0f, float speed = 0.1f);
|
||
|
||
// 复选框
|
||
void drawCheckboxControl(const char* label, bool& value, float width = 120.0f);
|
||
|
||
// 自定义 Popup 包装
|
||
bool BeginPopup(const char* name);
|
||
void EndPopup();
|
||
}
|
||
```
|
||
|
||
**XCEngine**: 直接使用原生 ImGui API,没有封装
|
||
|
||
---
|
||
|
||
### 5.4 选择系统差异
|
||
|
||
**Fermion 选择 + Entity Picking**:
|
||
```cpp
|
||
// InspectorPanel 实体拾取用于关节连接
|
||
bool m_entityPickingActive = false;
|
||
Entity m_pickingTargetEntity;
|
||
|
||
// 当用户在 Viewport 点击时
|
||
void deliverPickedEntity(Entity pickedEntity) {
|
||
if (m_pickingTargetEntity.hasComponent<RevoluteJoint2DComponent>()) {
|
||
m_pickingTargetEntity.getComponent<RevoluteJoint2DComponent>()
|
||
.connectedBodyID = pickedEntity.getUUID();
|
||
}
|
||
}
|
||
```
|
||
|
||
**XCEngine SelectionManager**:
|
||
```cpp
|
||
class SelectionManager {
|
||
Event<EntityID> OnSelectionChanged;
|
||
EntityID GetSelectedEntity();
|
||
void SetSelectedEntity(EntityID entity);
|
||
};
|
||
```
|
||
|
||
**XCEngine 问题**: 没有 Entity Picking 机制,无法在编辑关节时拾取场景中的物体
|
||
|
||
---
|
||
|
||
### 5.5 资源系统对比
|
||
|
||
**Fermion 资源系统**:
|
||
```
|
||
AssetManager (抽象基类)
|
||
├── EditorAssetManager (编辑器资源管理)
|
||
│ └── importAsset() 导入资源
|
||
└── RuntimeAssetManager (运行时资源管理)
|
||
└── getAsset<T>() 获取资源
|
||
|
||
AssetRegistry (资源注册表)
|
||
AssetHandle (资源句柄)
|
||
```
|
||
|
||
**XCEngine 资源系统**:
|
||
```
|
||
ProjectManager (文件系统浏览)
|
||
└── GetCurrentItems() 返回 AssetItem 列表
|
||
|
||
AssetItem (只包含文件信息)
|
||
├── name
|
||
├── type
|
||
├── isFolder
|
||
└── fullPath
|
||
```
|
||
|
||
**XCEngine 问题**:
|
||
1. 没有真正的资源导入流程
|
||
2. 没有 AssetRegistry 资源注册表
|
||
3. 没有 AssetHandle 统一资源句柄
|
||
4. 没有资源缓存和加载/卸载管理
|
||
|
||
---
|
||
|
||
## 7. 核心问题总结
|
||
|
||
### 7.1 已完成功能
|
||
|
||
| 面板 | 完成度 | 说明 |
|
||
|------|--------|------|
|
||
| HierarchyPanel | 70% | 基本树视图、选中、重命名、复制、拖拽 |
|
||
| ProjectPanel | 60% | 文件浏览、网格显示、导航,但拖拽移动失效 |
|
||
| ConsolePanel | 60% | 日志显示,缺少命令输入 |
|
||
| MenuBar | 30% | 菜单结构存在,但所有项 stubbed |
|
||
| InspectorPanel | 20% | 只实现 Transform 和 MeshRenderer 编辑,但 Engine 核心有完整组件库 |
|
||
| SceneViewPanel | 5% | 纯占位符 |
|
||
| GameViewPanel | 5% | 纯占位符 |
|
||
|
||
### 7.2 高优先级问题
|
||
|
||
1. **MenuBar 所有菜单项 stubbed** - 无法进行任何 Scene/Project 操作
|
||
2. **Inspector 没有 Add/Remove Component** - 无法添加/删除组件
|
||
3. **SceneViewPanel 完全是占位符** - 无法预览场景
|
||
4. **Project 拖拽移动失效** - HandleDrop() 返回 false
|
||
5. **缺少 5 个重要面板** - SettingsPanel, OverlayRenderPanel, MaterialEditorPanel, TextureConfigPanel, AssetManagerPanel
|
||
|
||
### 7.3 RHI 限制
|
||
|
||
当前 RHI 模块状态:
|
||
- D3D12: PipelineState 返回 nullptr,无法创建 3D 渲染 Pipeline
|
||
- OpenGL: Framebuffer、PipelineState、Shader 正常工作
|
||
|
||
**影响**: 在 RHI 重构完成前,3D Viewport 无法实现。
|
||
|
||
---
|
||
|
||
## 8. 改进计划
|
||
|
||
### 8.1 第一阶段: 完善现有面板功能
|
||
|
||
**目标**: 不依赖 RHI,完善 Editor UI 功能
|
||
|
||
#### 8.1.1 MenuBar 菜单功能对接
|
||
|
||
```
|
||
优先级: 高
|
||
预计工作量: 1-2 天
|
||
依赖: 无
|
||
```
|
||
|
||
**需要实现**:
|
||
- File 菜单: New Scene, Open Scene, Save Scene, Exit
|
||
- Edit 菜单: Undo, Redo (需要命令历史系统), Cut, Copy, Paste
|
||
- View 菜单: Reset Layout
|
||
- Help 菜单: About
|
||
|
||
**实现方案**:
|
||
```cpp
|
||
// MenuBar.cpp
|
||
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {
|
||
m_onNewSceneCallback(); // 通过回调连接到 BosonLayer
|
||
}
|
||
```
|
||
|
||
#### 8.1.2 Inspector Add/Remove Component
|
||
|
||
```
|
||
优先级: 高
|
||
预计工作量: 2-3 天
|
||
依赖: 组件系统完善
|
||
```
|
||
|
||
**需要实现**:
|
||
1. 添加 "Add Component" 按钮
|
||
2. 分类组件菜单 (2D, 3D, Other)
|
||
3. 右键 "Remove Component" 选项
|
||
|
||
**实现方案**:
|
||
```cpp
|
||
// InspectorPanel.cpp
|
||
void InspectorPanel::drawComponent<T>(Entity entity, UIFunction uiFunction) {
|
||
// 右键菜单
|
||
if (ImGui::BeginPopupContextItem("ComponentSettings")) {
|
||
if (ImGui::MenuItem("Remove Component"))
|
||
entity.removeComponent<T>();
|
||
ImGui::EndPopup();
|
||
}
|
||
}
|
||
|
||
// Add Component 按钮
|
||
if (ImGui::Button("Add Component")) {
|
||
ImGui::OpenPopup("AddComponentMenu");
|
||
}
|
||
// 分类显示组件列表
|
||
```
|
||
|
||
#### 8.1.3 修复 Project 拖拽移动
|
||
|
||
```
|
||
优先级: 中
|
||
预计工作量: 0.5 天
|
||
依赖: 无
|
||
```
|
||
|
||
**问题**: `HandleDrop()` 返回 false,从未被调用
|
||
|
||
**修复方案**: 在双击打开文件夹时,检查是否正在拖拽,如果是则执行移动操作。
|
||
|
||
---
|
||
|
||
### 8.2 第二阶段: Inspector 组件系统完善
|
||
|
||
**目标**: 实现完整的组件编辑功能
|
||
|
||
#### 8.2.1 Inspector 组件编辑支持
|
||
|
||
Engine 核心已有完整组件系统,Editor Inspector 需要添加对这些组件的编辑支持:
|
||
|
||
| 组件 | Engine 状态 | Inspector 编辑复杂度 | 说明 |
|
||
|------|------------|---------------------|------|
|
||
| TransformComponent | ✅ | 低 | 需改进 UI (drawVec3Control) |
|
||
| MeshRendererComponent | ✅ | 中 | 需添加拖拽、预览 |
|
||
| CameraComponent | ✅ | 中 | 投影、FOV、近远裁剪 |
|
||
| DirectionalLightComponent | ✅ | 低 | 颜色、强度 |
|
||
| PointLightComponent | ✅ | 低 | 颜色、强度、范围 |
|
||
| SpotLightComponent | ✅ | 中 | 颜色、强度、范围、角度 |
|
||
| Rigidbody2DComponent | ✅ | 高 | 物理引擎对接 |
|
||
| Rigidbody3DComponent | ✅ | 高 | 物理引擎对接 |
|
||
| Collider2D/3D | ✅ | 高 | 碰撞体 |
|
||
| SpriteRendererComponent | ✅ | 中 | 2D 精灵 |
|
||
| CircleRendererComponent | ✅ | 低 | 圆形渲染 |
|
||
| TextComponent | ✅ | 中 | 文本渲染 |
|
||
| ScriptComponent | ✅ | 高 | 脚本字段编辑 |
|
||
|
||
#### 8.2.2 Transform UI 改进
|
||
|
||
**当前**:
|
||
```cpp
|
||
ImGui::DragFloat3("##Position", transform->position, 0.1f);
|
||
```
|
||
|
||
**改进方案** (参考 Fermion `ui::drawVec3Control`):
|
||
- 添加 XYZ 标签
|
||
- 添加 Per-axis reset 按钮
|
||
- 统一对齐和缩进
|
||
- 添加合适的刻度 (speed)
|
||
|
||
---
|
||
|
||
### 8.3 第三阶段: 场景序列化
|
||
|
||
**目标**: 实现 Scene Save/Load
|
||
|
||
```
|
||
优先级: 中
|
||
预计工作量: 2-3 天
|
||
依赖: Scene 序列化框架 (Engine Scene 类已有基础 Serialize/Deserialize)
|
||
```
|
||
|
||
**需要实现**:
|
||
- Scene 序列化到文件 (Engine 核心已有基础)
|
||
- Scene 反序列化
|
||
- 资源路径管理
|
||
- Editor/Runtime 场景分离
|
||
|
||
---
|
||
|
||
### 8.4 第四阶段: 3D Viewport (依赖 RHI)
|
||
|
||
**目标**: 实现完整的 3D Viewport
|
||
|
||
```
|
||
优先级: 高 (但依赖 RHI)
|
||
预计工作量: 2-4 周
|
||
依赖: RHI 重构完成
|
||
```
|
||
|
||
#### 8.4.1 OpenGL Backend 优先方案
|
||
|
||
由于 D3D12 PipelineState 当前 broken,可以先用 OpenGL Backend 实现 Viewport:
|
||
|
||
**优势**:
|
||
- OpenGL Framebuffer 正常工作
|
||
- OpenGL PipelineState 正常工作
|
||
- Shader uniform 设置正常工作
|
||
|
||
**需要工作**:
|
||
1. EditorCamera 实现 (Orbit/Pan/Zoom)
|
||
2. SceneRenderer 中间层
|
||
3. ViewportPanel Framebuffer 渲染
|
||
4. 鼠标拾取 (readPixel from entity ID attachment)
|
||
5. ImGuizmo 集成
|
||
|
||
#### 8.4.2 实现步骤
|
||
|
||
**Step 1: EditorCamera** (3-5 天)
|
||
```cpp
|
||
class EditorCamera {
|
||
// Orbit 模式
|
||
void orbit(float deltaX, float deltaY);
|
||
void pan(float deltaX, float deltaY);
|
||
void zoom(float delta);
|
||
|
||
// FPS 模式
|
||
void moveForward(float delta);
|
||
void moveRight(float delta);
|
||
};
|
||
```
|
||
|
||
**Step 2: SceneRenderer 中间层** (1 周)
|
||
```cpp
|
||
class ViewportRenderer {
|
||
std::shared_ptr<Framebuffer> m_framebuffer;
|
||
std::shared_ptr<Scene> m_scene;
|
||
|
||
void beginScene(const EditorCamera& camera);
|
||
void submitMesh(MeshComponent& mesh, glm::mat4 transform);
|
||
void endScene();
|
||
};
|
||
```
|
||
|
||
**Step 3: ViewportPanel 集成** (3-5 天)
|
||
```cpp
|
||
void ViewportPanel::onImGuiRender() {
|
||
// 渲染到 framebuffer
|
||
m_framebuffer->bind();
|
||
m_viewportRenderer->beginScene(m_editorCamera);
|
||
// ... 提交场景物体
|
||
m_viewportRenderer->endScene();
|
||
m_framebuffer->unbind();
|
||
|
||
// 显示到 ImGui
|
||
ImGui::Image(m_framebuffer->getColorTexture(), ...);
|
||
|
||
// 鼠标拾取
|
||
int entityID = m_framebuffer->readPixel(1, pixelX, pixelY);
|
||
}
|
||
```
|
||
|
||
**Step 4: ImGuizmo 集成** (2-3 天)
|
||
```cpp
|
||
ImGuizmo::SetOrthographic(isOrthographic);
|
||
ImGuizmo::SetRect(viewportBounds);
|
||
ImGuizmo::Manipulate(
|
||
cameraView, cameraProjection,
|
||
operation, LOCAL,
|
||
glm::value_ptr(worldTransform)
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
### 8.5 第五阶段: Play/Edit 模式
|
||
|
||
**目标**: 实现场景状态切换
|
||
|
||
```
|
||
优先级: 中
|
||
预计工作量: 1-2 周
|
||
依赖: 3D Viewport + 组件系统
|
||
```
|
||
|
||
**状态机**:
|
||
```cpp
|
||
enum class SceneState { Edit, Play, Simulate };
|
||
|
||
void BosonLayer::onScenePlay() {
|
||
m_runtimeScene = Scene::copy(m_editorScene);
|
||
m_activeScene = m_runtimeScene;
|
||
m_activeScene->onRuntimeStart();
|
||
}
|
||
|
||
void BosonLayer::onSceneStop() {
|
||
m_activeScene->onRuntimeStop();
|
||
m_activeScene = m_editorScene;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 技术债务
|
||
|
||
### 9.1 架构问题
|
||
|
||
1. **Editor 和 Engine 使用两套不同的 GameObject/Component 系统**
|
||
- **Editor** (`editor/src/Core/GameObject.h`): 简化版,使用 `float position[3]` 数组存储变换
|
||
- **Engine** (`engine/include/XCEngine/Components/`): 完整 ECS,使用 `TransformComponent` 组件
|
||
- **后果**: Editor 无法直接使用 Engine 的组件系统,需要重新实现
|
||
- **建议**: Editor 应复用 Engine 的 Components::GameObject/Scene 系统
|
||
|
||
2. **Panel 独立设计 vs Layer 组合**
|
||
- Fermion: BosonLayer 组合所有面板,共享 Context
|
||
- XCEngine: 各 Panel 独立,通过 SceneManager 单例通信
|
||
|
||
3. **SceneManager 单例 vs Scene 指针传递**
|
||
- Editor 使用简化版 SceneManager,与 Engine 的 Scene 类不兼容
|
||
- 建议: 考虑使用 Context 模式传递 Scene 引用
|
||
|
||
4. **缺少 BosonUI 自定义控件封装**
|
||
- Fermion 有 ui::drawVec3Control, ui::drawFloatControl 等
|
||
- XCEngine 直接使用原生 ImGui API,代码重复
|
||
|
||
### 9.2 代码质量问题
|
||
|
||
1. **注释掉的代码** - 建议清理
|
||
2. **TODO/FIXME** - 建议跟踪
|
||
3. **Magic numbers** - 建议定义常量
|
||
|
||
---
|
||
|
||
## 10. 建议实施路线
|
||
|
||
### 短期 (1-2 周)
|
||
|
||
```
|
||
□ MenuBar 菜单功能对接
|
||
□ Inspector Add/Remove Component
|
||
□ 修复 Project 拖拽移动
|
||
□ Transform UI 改进
|
||
□ Console 命令输入
|
||
```
|
||
|
||
### 中期 (1-2 月,RHI 完成后)
|
||
|
||
```
|
||
□ EditorCamera 实现
|
||
□ SceneRenderer 中间层
|
||
□ ViewportPanel 3D 渲染
|
||
□ 鼠标拾取
|
||
□ ImGuizmo 集成
|
||
□ Play/Edit/Simulate 模式
|
||
```
|
||
|
||
### 长期
|
||
|
||
```
|
||
□ 完整的 Inspector 组件编辑界面 (Engine 核心组件已有)
|
||
□ 场景序列化
|
||
□ 资源导入系统
|
||
□ 材质编辑器
|
||
□ 动画编辑器
|
||
□ OverlayRenderPanel (物理调试可视化)
|
||
□ TextureConfigPanel (纹理配置)
|
||
□ AssetManagerPanel (资源注册表)
|
||
□ SettingsPanel (编辑器设置)
|
||
□ Play/Edit/Simulate 模式切换
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 参考资料
|
||
|
||
- Fermion Boson Editor 源码: `参考/Fermion/Boson/`
|
||
- XCEngine Editor 源码: `editor/`
|
||
- RHI 模块: `engine/include/XCEngine/RHI/`
|
||
|
||
---
|
||
|
||
*文档生成时间: 2026-03-24*
|
||
*最后更新: 2026-03-24 (更正 Component 系统描述,补充 Editor/Engine 架构问题)*
|