docs: 添加 Editor 设计与实现分析文档
- 对比分析 XCEngine Editor 与 Fermion Boson Editor 各面板功能 - 详细列出缺失的面板: SettingsPanel, OverlayRenderPanel, MaterialEditorPanel, TextureConfigPanel, AssetManagerPanel - 分析核心系统差异: Application 架构、SceneManager、UI 控件封装、选择系统、资源系统 - 制定改进计划分阶段实施路线
This commit is contained in:
933
docs/plan/Editor设计与实现.md
Normal file
933
docs/plan/Editor设计与实现.md
Normal file
@@ -0,0 +1,933 @@
|
||||
# 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 种 | 需重写 |
|
||||
| 动态增删组件 | ✅ 分类菜单 | ❌ 无 | 需实现 |
|
||||
| 删除组件 | ✅ 右键 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. 组件类型太少 (只有 TransformComponent, MeshRendererComponent)
|
||||
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 概念,只有实体列表
|
||||
2. 没有物理世界集成
|
||||
3. 没有 ECS 系统 (使用简单的 Component 基类)
|
||||
4. EntityID 是简单递增整数,不是 UUID
|
||||
5. 没有场景状态 (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 | 15% | 只有 Transform 和 MeshRenderer 显示 |
|
||||
| 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 组件类型补充
|
||||
|
||||
需要添加的组件类型:
|
||||
|
||||
| 组件 | 复杂度 | 说明 |
|
||||
|------|--------|------|
|
||||
| TransformComponent | 已实现 | 需改进 UI |
|
||||
| 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 天
|
||||
依赖: RHI 完善后
|
||||
```
|
||||
|
||||
**需要实现**:
|
||||
- Scene 序列化 (YAML/JSON)
|
||||
- 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. **Panel 独立设计 vs Layer 组合**
|
||||
- Fermion: BosonLayer 组合所有面板,共享 Context
|
||||
- XCEngine: 各 Panel 独立,通过 SceneManager 单例通信
|
||||
|
||||
2. **SceneManager 单例 vs Scene 指针传递**
|
||||
- 单例方便访问,但耦合紧密
|
||||
- 建议: 考虑使用 Context 模式传递 Scene 引用
|
||||
|
||||
3. **缺少 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 模式
|
||||
```
|
||||
|
||||
### 长期
|
||||
|
||||
```
|
||||
□ 完整的组件系统
|
||||
□ 场景序列化
|
||||
□ 资源导入系统
|
||||
□ 材质编辑器
|
||||
□ 动画编辑器
|
||||
□ OverlayRenderPanel (物理调试可视化)
|
||||
□ TextureConfigPanel (纹理配置)
|
||||
□ AssetManagerPanel (资源注册表)
|
||||
□ SettingsPanel (编辑器设置)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 参考资料
|
||||
|
||||
- Fermion Boson Editor 源码: `参考/Fermion/Boson/`
|
||||
- XCEngine Editor 源码: `editor/`
|
||||
- RHI 模块: `engine/include/XCEngine/RHI/`
|
||||
|
||||
---
|
||||
|
||||
*文档生成时间: 2026-03-24*
|
||||
*最后更新: 2026-03-24 (补充缺失面板和系统差异分析)*
|
||||
Reference in New Issue
Block a user