docs: add Editor API documentation
This commit is contained in:
153
docs/api/_guides/Editor/Editor-Architecture-And-Workflow.md
Normal file
153
docs/api/_guides/Editor/Editor-Architecture-And-Workflow.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Editor Architecture And Workflow
|
||||
|
||||
## 先建立正确心智模型
|
||||
|
||||
`docs/api/XCEngine/Editor/**` 对应的是编辑器应用层,而不是引擎运行时 public API。
|
||||
它更接近 Unity Editor、Unreal Editor 这类“工具壳层”的实现文档,而不是给游戏逻辑直接链接的稳定 SDK。
|
||||
|
||||
可以把当前架构粗略理解成六层:
|
||||
|
||||
1. `Platform` 负责 Win32 进程、窗口消息、崩溃日志和 D3D12 窗口渲染。
|
||||
2. `UI` 负责 ImGui 会话、主题、面板 chrome 和通用控件。
|
||||
3. `Core` 负责上下文、事件总线、动作路由、选择和撤销。
|
||||
4. `Managers` 负责项目和场景服务的默认实现。
|
||||
5. `Actions` 负责把按钮、菜单和快捷键翻译成“可执行动作”。
|
||||
6. `Commands` 负责真正修改项目、场景、实体和组件状态。
|
||||
|
||||
`panels`、`Layout` 和 `ComponentEditors` 则横向挂在这些层之间:
|
||||
|
||||
- `panels` 是用户直接看到的编辑器窗口
|
||||
- `Layout` 决定这些窗口如何 Dock
|
||||
- `ComponentEditors` 决定 Inspector 如何按组件类型渲染
|
||||
|
||||
## 为什么要拆成 Actions 和 Commands
|
||||
|
||||
这是当前 Editor 文档里最重要的一条设计线。
|
||||
如果不拆,最常见的退化就是:
|
||||
|
||||
- 菜单栏自己写一套保存逻辑
|
||||
- 快捷键自己写一套删除逻辑
|
||||
- 右键菜单再写一套复制粘贴逻辑
|
||||
|
||||
时间一长,你会得到三个入口、三份行为、三种 bug。
|
||||
|
||||
当前实现把它拆成:
|
||||
|
||||
- `EditorActions` 定义动作名称、快捷键和启用状态
|
||||
- `ActionRouting` 和 `EditorActionRoute` 决定当前动作应该作用在哪个面板上下文
|
||||
- `*ActionRouter` 负责具体入口的 UI 交互
|
||||
- `Commands` 负责真正修改状态
|
||||
|
||||
这就是商业编辑器很常见的分层方式。Unity 用户会很容易理解这件事:
|
||||
菜单项、快捷键和 Inspector 按钮看起来入口不同,但背后应该落到同一条编辑命令语义上。
|
||||
|
||||
## 为什么 Inspector 不走完全反射,而是组件专用 editor
|
||||
|
||||
当前 Inspector 采用的是:
|
||||
|
||||
- `IComponentEditor`
|
||||
- `ComponentEditorRegistry`
|
||||
- `TransformComponentEditor`
|
||||
- `CameraComponentEditor`
|
||||
- `LightComponentEditor`
|
||||
|
||||
这条路线更接近 Unity 的 custom inspector / property drawer 思想,而不是“把所有字段自动反射成一张表”。
|
||||
|
||||
这样做的好处是:
|
||||
|
||||
- 条件式 UI 更自然,例如 Camera 的透视/正交分支
|
||||
- 撤销、字段分组和按钮布局更可控
|
||||
- 组件编辑体验可以按照组件语义而不是成员变量顺序组织
|
||||
|
||||
代价是:
|
||||
|
||||
- 每个组件都要写专门 editor
|
||||
- 通用自动化程度较低
|
||||
|
||||
但对当前阶段的编辑器,这是更稳妥的商业级做法,因为它优先保证可解释性和可维护性。
|
||||
|
||||
## 从一次用户点击看整条链路
|
||||
|
||||
以 Hierarchy 中“右键删除实体”为例,当前主路径大致是:
|
||||
|
||||
1. `HierarchyPanel` 负责渲染树和弹出上下文菜单。
|
||||
2. `HierarchyActionRouter` 负责把“Delete”菜单项映射为删除动作。
|
||||
3. `EntityCommands::DeleteEntity` 负责发起真正的场景修改。
|
||||
4. `UndoUtils` 和 `UndoManager` 负责录制撤销快照。
|
||||
5. `SceneManager` 负责真正删除实体并发布事件。
|
||||
6. `SelectionManager`、`InspectorPanel` 等其它系统通过事件感知更新。
|
||||
|
||||
这条链路说明了一个核心原则:
|
||||
面板不应该直接修改场景,面板应该只描述用户意图。
|
||||
|
||||
## 为什么当前大量使用小型 helper header
|
||||
|
||||
很多用户第一次看会觉得:为什么 `UI`、`Actions`、`Commands` 下有这么多小头文件?
|
||||
|
||||
这是 Dear ImGui 风格编辑器常见的工程取舍。原因很现实:
|
||||
|
||||
- 即时模式 UI 很容易把一切都塞进 `Render()`
|
||||
- 一旦不拆 helper,单个面板 cpp 会迅速膨胀
|
||||
- 把“交互语义”“控件语义”“状态容器”拆成小头文件后,代码更容易复用和迁移
|
||||
|
||||
所以这些 header 不是“碎片化设计”,而是在对抗 UI 工具代码天然容易失控的问题。
|
||||
|
||||
## 当前架构最像 Unity 的部分
|
||||
|
||||
- `HierarchyPanel / ProjectPanel / InspectorPanel / ConsolePanel` 这组窗口组合很像 Unity Editor 的基本工作区。
|
||||
- `ComponentEditors` 很像 Unity 的 custom inspector。
|
||||
- `SceneCommands + UndoManager` 很像 Unity 编辑态里对场景对象做结构修改时的命令路径。
|
||||
|
||||
## 当前又明显还不像 Unity 的地方
|
||||
|
||||
- 当前只有 Windows + D3D12 + ImGui 主路径。
|
||||
- Project 面板还不是完整资产导入系统。
|
||||
- Inspector 还没有脚本组件、搜索式 Add Component、批量多选混合值等成熟体验。
|
||||
- Console 还是轻量列表,不是完整诊断中心。
|
||||
|
||||
所以更准确的表述应该是:
|
||||
它采用了很多 Unity 风格的编辑器设计理念,但当前实现仍然是一个处在快速重构期的、轻量但方向正确的编辑器壳层。
|
||||
|
||||
## 如果你要继续扩展这个编辑器,推荐从哪层下手
|
||||
|
||||
### 新增一个全新面板
|
||||
|
||||
通常顺序是:
|
||||
|
||||
1. 在 `panels` 下建立新 Panel 类型。
|
||||
2. 优先复用 `PanelWindowScope / PanelToolbarScope / PanelContentScope`。
|
||||
3. 如果面板需要上下文敏感快捷键,再接入 `ActionRouting`。
|
||||
4. 如果面板要真正修改数据,优先写 `Commands`,不要直接改 manager。
|
||||
|
||||
### 给 Inspector 新增一个组件编辑器
|
||||
|
||||
推荐顺序是:
|
||||
|
||||
1. 实现新的 `IComponentEditor`。
|
||||
2. 在 `ComponentEditorRegistry` 注册。
|
||||
3. 优先通过 `PropertyGrid`、`ScalarControls`、`VectorControls` 组装 UI。
|
||||
4. 涉及结构性变化时,通过 `ComponentCommands` 或新的命令 helper 进入撤销链。
|
||||
|
||||
### 给菜单栏或快捷键新增动作
|
||||
|
||||
推荐顺序是:
|
||||
|
||||
1. 在 `EditorActions` 中先定义动作描述。
|
||||
2. 在合适的 `*ActionRouter` 中接 UI 入口。
|
||||
3. 真实变更落到 `Commands`。
|
||||
4. 如果动作取决于当前焦点面板,再考虑是否需要新的 `EditorActionRoute`。
|
||||
|
||||
## 当前文档应该怎么读
|
||||
|
||||
如果你是第一次接触这一套代码,推荐按这个顺序:
|
||||
|
||||
1. [Editor](../../XCEngine/Editor/Editor.md)
|
||||
2. [Application](../../XCEngine/Editor/Application/Application.md)
|
||||
3. [Core](../../XCEngine/Editor/Core/Core.md)
|
||||
4. [Actions](../../XCEngine/Editor/Actions/Actions.md)
|
||||
5. [Commands](../../XCEngine/Editor/Commands/Commands.md)
|
||||
6. [panels](../../XCEngine/Editor/panels/panels.md)
|
||||
7. [ComponentEditors](../../XCEngine/Editor/ComponentEditors/ComponentEditors.md)
|
||||
8. [UI](../../XCEngine/Editor/UI/UI.md)
|
||||
|
||||
这能让你先看清系统骨架,再下钻到具体类型页,而不是一开始就陷进某个 helper 文件里。
|
||||
Reference in New Issue
Block a user