chore: sync workspace state

This commit is contained in:
2026-03-29 01:36:53 +08:00
parent eb5de3e3d4
commit e5cb79f3ce
4935 changed files with 35593 additions and 360696 deletions

View File

@@ -2,49 +2,110 @@
**命名空间**: `XCEngine::Editor`
**类型**: `class + enum class`
**类型**: `class`
**源文件**: `editor/src/panels/HierarchyPanel.h`
**描述**: 层级面板,负责显示场景对象树、搜索、排序、拖放层级调整以及内联重命名
**描述**: 编辑器场景层级面板,负责绘制根实体树、处理选择与重命名事件,并把上下文菜单与拖放操作路由给 Action 层
## 概述
`HierarchyPanel` 是当前编辑器里交互最丰富的面板之一
`HierarchyPanel` 是当前编辑器里最典型的“视图层面板”:它自己拥有 UI 状态,但不直接承担场景编辑命令实现。它的主要任务是把当前场景对象以树形方式呈现出来,并把用户交互转换成选择、重命名、右键菜单和拖放请求
当前承载的功能包括
当前实现,这个面板主要负责
- 订阅选择变化重命名请求事件
- 层级树渲染
- 搜索过滤
- 排序选项
- 拖拽层级调整
- 右键上下文菜单
- 内联重命名
- 订阅选择变化与外部重命名请求事件
- 读取 `ISceneManager` 提供的根实体列表。
- 基于 `UI::TreeView` 递归绘制场景对象树。
- 维护内联重命名状态。
- 将选择、右键菜单、拖放等行为委托给 `Actions::HierarchyActionRouter` 一侧的 helper。
头文件里还定义了:
这和商业引擎编辑器的分层很一致Hierarchy 面板负责“看见和触发”,而不是直接“改数据和执行业务命令”。
- `enum class SortMode { Name, ComponentCount, TransformFirst }`
## 当前实现行为
## 当前实现说明
`editor/src/panels/HierarchyPanel.cpp` 的实现:
- `OnAttach()` 会订阅 `SelectionChangedEvent``EntityRenameRequestedEvent`
- 搜索过滤当前按名字子串匹配,并递归检查子节点。
- 排序支持:
- `Name`
- `ComponentCount`
- `TransformFirst`
- 双击节点会进入重命名状态
- 背景点击、右键菜单和拖放逻辑主要委托给 `Actions`
- `OnAttach()` 会订阅
- `SelectionChangedEvent`
- `EntityRenameRequestedEvent`
- `OnDetach()` 会正确取消订阅并清零 handler id。
- `Render()` 会:
- 应用 `HierarchyInspectorPanelBackgroundColor()`
- 通过 `PanelWindowScope` / `PanelContentScope` 建立标准面板外壳
- 调用 `Actions::ObserveFocusedActionRoute(...)` 将当前焦点路由标记为 `Hierarchy`
-`ISceneManager` 读取根实体并逐个递归渲染。
- 在树绘制完成后处理背景点击、背景右键菜单、实体右键菜单和根级 drop target。
## 当前实现边界
## 节点绘制模型
- 当前排序和过滤都在 UI 渲染阶段直接对实体列表做处理。
- `TransformFirst` 排序实际上是“有 Transform 的对象优先”,而不是更复杂的 transform-aware hierarchy order。
当前的节点绘制已经不再是旧版本那种局部自定义树,而是完全建立在 `UI::TreeView` 之上:
- 每个实体节点都会构造一个 `UI::TreeNodeDefinition`
- `selected` 状态来自 `ISelectionManager::IsSelected(...)`
- `leaf` 状态来自 `gameObject->GetChildCount() == 0`
- `persistenceKey` 使用 `gameObject->GetUUID()` 转成字符串,保证展开状态在同一面板实例中稳定。
- `style` 使用 `UI::HierarchyTreeStyle()`
- `prefix` 使用 `UI::NavigationTreePrefixWidth()``UI::DrawAssetIcon(..., AssetIconKind::GameObject)` 绘制对象图标。
这意味着当前 Hierarchy 的视觉和交互行为已经被统一纳入 Editor UI 基础设施,而不是面板自己手工维护整套树渲染细节。
## 交互行为
当前节点交互通过 `TreeNodeCallbacks` 接入:
- 单击左键:调用 `Actions::HandleHierarchySelectionClick(...)`,支持结合 `Ctrl` 执行多选。
- 右键:调用 `Actions::HandleHierarchyItemContextRequest(...)` 打开目标实体上下文菜单。
- 双击:调用 `BeginRename(...)` 进入内联重命名。
- 节点额外渲染阶段:调用 `Actions::BeginHierarchyEntityDrag(...)``Actions::AcceptHierarchyEntityDrop(...)` 接入拖放。
因此 `HierarchyPanel` 自己不直接执行“重排父子关系”之类操作,它只负责在正确的节点生命周期里提供 drop source / target 入口。
## 重命名模型
`HierarchyPanel` 当前用 `UI::InlineTextEditState<uint64_t, 256>` 保存重命名状态。
当前行为是:
- 外部若派发 `EntityRenameRequestedEvent`,面板会在 `OnRenameRequested(...)` 中找到实体并进入重命名。
- 若用户双击树节点,也会进入重命名。
- 编辑过程中:
- `Enter` 提交。
- `Escape` 取消。
- 输入框失焦且用户左键点击其他位置时提交。
- `CommitRename()` 最终通过 `Actions::CommitEntityRename(...)` 把改名请求发往动作层。
这类实现很像商业编辑器中的“inline rename controller”面板持有输入框状态但真正的实体改名仍然走统一命令路径。
## 生命周期与线程语义
- 该面板依赖有效的 `IEditorContext` 才能 attach、订阅事件并绘制。
- 事件订阅和 UI 绘制都应视为编辑器主线程行为。
- `m_treeState``m_renameState` 都属于面板实例私有状态,不会自动跨会话持久化。
## 设计说明
当前实现的一个正确方向是Hierarchy 面板只负责“把场景对象转成 Editor UI 语义”,而不是把所有业务都塞进面板里。
这样做的收益是:
- 树视图风格、图标前缀、展开行为可以和 `ProjectPanel` 共享。
- 选择、重命名、上下文菜单、拖放都能被 `Actions` 层集中治理。
- 面板本身更容易继续重构,比如后续加入搜索、过滤、批量操作时,不必推翻底层树控件。
## 当前限制
- 当前没有搜索、过滤、排序或大场景虚拟化能力。
- 展开状态只保存在 `UI::TreeViewState` 的内存态中,不会自动写入布局文件。
- 重命名输入框是替换式绘制,不是“树节点原位嵌入子控件”的更复杂实现。
- 目前只为每个节点提供统一的 `GameObject` 图标前缀,没有按组件类型做更细粒度图标区分。
## 相关文档
- [panels](../panels.md)
- [SelectionManager](../../Core/SelectionManager/SelectionManager.md)
- [SceneManager](../../Managers/SceneManager/SceneManager.md)
- [TreeView](../../UI/TreeView/TreeView.md)
- [BuiltInIcons](../../UI/BuiltInIcons/BuiltInIcons.md)
- [HierarchyActionRouter](../../Actions/HierarchyActionRouter/HierarchyActionRouter.md)
- [EditorEvents](../../Core/EditorEvents/EditorEvents.md)
- [ISceneManager](../../Core/ISceneManager/ISceneManager.md)
- [ISelectionManager](../../Core/ISelectionManager/ISelectionManager.md)