2026-04-03 14:17:50 +08:00
|
|
|
|
# Unity式 SceneView Gizmo 系统完整审查与正式化重构方案
|
|
|
|
|
|
|
|
|
|
|
|
日期:`2026-04-03`
|
|
|
|
|
|
|
|
|
|
|
|
相关旧文档:
|
|
|
|
|
|
- `docs/plan/SceneViewport_Overlay_Gizmo_Rework_Plan.md`
|
|
|
|
|
|
- `docs/plan/SceneViewport_Overlay_Gizmo_Rework_Checkpoint_2026-04-02.md`
|
|
|
|
|
|
- `docs/plan/Unity SRP API参考文档.md`
|
|
|
|
|
|
|
|
|
|
|
|
本文档以当前代码真实状态为准,覆盖:
|
|
|
|
|
|
- `editor` 中 SceneView gizmo / grid / outline / overlay 的现状审查
|
|
|
|
|
|
- `engine` 与 `editor` 的职责边界重划
|
|
|
|
|
|
- 一套更接近 Unity SceneView / Gizmos / Handles 思路的正式化重构方案
|
|
|
|
|
|
- 可分阶段落地、可测试、可验收的迁移计划
|
|
|
|
|
|
|
|
|
|
|
|
## 0. 执行结论
|
|
|
|
|
|
|
|
|
|
|
|
当前 SceneView 可视化链路已经完成了第一轮“从 ImGui 临时绘制向正式渲染 pass 迁移”的关键基础设施建设,但还没有真正收口。
|
|
|
|
|
|
|
|
|
|
|
|
当前最重要的结论有四条:
|
|
|
|
|
|
|
|
|
|
|
|
1. `engine` 里现有的通用渲染扩展点是对的,应该保留。
|
|
|
|
|
|
- `RenderPass`
|
|
|
|
|
|
- `RenderPassSequence`
|
|
|
|
|
|
- `CameraRenderRequest::preScenePasses`
|
|
|
|
|
|
- `CameraRenderRequest::postScenePasses`
|
|
|
|
|
|
- `CameraRenderRequest::overlayPasses`
|
|
|
|
|
|
|
|
|
|
|
|
2. `editor` 里现有的 `SceneViewportEditorOverlayData` 和 `SceneViewportEditorOverlayPass` 方向是对的,应该继续扩展,而不是回退到 ImGui world draw。
|
|
|
|
|
|
|
|
|
|
|
|
3. 目前真正的架构问题,不是“某个 gizmo 画得还不够像 Unity”,而是 **SceneView 的 editor 语义仍然泄漏进了 engine 的 builtin postprocess**。
|
|
|
|
|
|
- `infinite grid`
|
|
|
|
|
|
- `selection outline`
|
|
|
|
|
|
- `outline debug mask`
|
|
|
|
|
|
- 与之绑定的 shader / resource 注册
|
|
|
|
|
|
|
|
|
|
|
|
4. 最终正确边界应当是:
|
|
|
|
|
|
- `engine/runtime` 负责“能画什么、怎样插 pass、怎样跑后端”
|
|
|
|
|
|
- `editor/SceneView` 负责“为什么要画、何时画、画哪些 gizmo、哪些对象参与、交互规则是什么”
|
|
|
|
|
|
|
|
|
|
|
|
换句话说,**Unity-like 的正确做法不是把所有 gizmo 都塞进 runtime engine,而是 runtime 提供绘制能力,editor 拥有 SceneView gizmo 的语义和调度权。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 当前实现完整审查
|
|
|
|
|
|
|
|
|
|
|
|
## 1.1 已经正式化、应保留的部分
|
|
|
|
|
|
|
|
|
|
|
|
### A. CameraRenderer 的可扩展 pass 时序已经成立
|
|
|
|
|
|
|
|
|
|
|
|
当前 `CameraRenderer` 的执行顺序已经具备正规的扩展缝:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
preScenePasses
|
|
|
|
|
|
-> scene geometry
|
|
|
|
|
|
-> object id
|
|
|
|
|
|
-> postScenePasses
|
|
|
|
|
|
-> builtin postprocess
|
|
|
|
|
|
-> overlayPasses
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这条缝本身是正确的,说明现在的 renderer 已经不是一个只能硬编码单条流水线的结构,后续 SceneView 的正式化工作不需要推翻它。
|
|
|
|
|
|
|
|
|
|
|
|
### B. Editor world overlay 已经有 canonical frame data
|
|
|
|
|
|
|
|
|
|
|
|
`SceneViewportEditorOverlayData.h` 已经提供了一份比较正确的中间表示:
|
|
|
|
|
|
- `worldLines`
|
|
|
|
|
|
- `worldSprites`
|
|
|
|
|
|
- `screenTriangles`
|
|
|
|
|
|
- `handleRecords`
|
|
|
|
|
|
|
|
|
|
|
|
这意味着当前系统已经不必再依赖“某个 gizmo 组件自己画、自己 hit test、自己决定屏幕图元”的散乱做法,而是可以朝一份单帧 canonical overlay 数据前进。
|
|
|
|
|
|
|
|
|
|
|
|
### C. Editor overlay 已经具备独立 GPU pass
|
|
|
|
|
|
|
|
|
|
|
|
`SceneViewportEditorOverlayPass` 已经能够在 renderer pass 中绘制:
|
|
|
|
|
|
- world line
|
|
|
|
|
|
- sprite billboard
|
|
|
|
|
|
- screen-space triangle
|
|
|
|
|
|
|
|
|
|
|
|
这一步非常关键。它说明 camera/light icon、camera frustum、light shape、transform gizmo 等内容已经不需要再走 ImGui world draw 这条临时路径。
|
|
|
|
|
|
|
|
|
|
|
|
### D. Scene object picking 已经走 object-id GPU 路线
|
|
|
|
|
|
|
|
|
|
|
|
当前对象选中本身已经不是纯 CPU 射线猜测,而是建立在 object id buffer 之上的正式读回流程。这个方向是对的,后续无需推翻。
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
**当前系统最有价值的资产不是若干单独功能,而是已经出现了一套可继续扩张的“SceneView render extension seam + canonical overlay data + editor overlay pass”。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1.2 已经进入正式化,但还没有彻底收口的部分
|
|
|
|
|
|
|
|
|
|
|
|
### A. Camera / Light icon、Camera frustum、Directional Light gizmo
|
|
|
|
|
|
|
|
|
|
|
|
这部分现在已经通过 `SceneViewportOverlayBuilder -> SceneViewportEditorOverlayPass` 进入 GPU overlay 链路,已经不再是纯 ImGui hack。
|
|
|
|
|
|
|
|
|
|
|
|
这是正确方向,但当前还存在几个明显问题:
|
|
|
|
|
|
- `SceneViewportOverlayBuilder` 仍然是一个偏“堆逻辑”的单体 builder
|
|
|
|
|
|
- gizmo provider 还没有独立注册体系
|
|
|
|
|
|
- 灯光 gizmo 的覆盖范围还不完整
|
|
|
|
|
|
- `PointLight` / `SpotLight` 还没有形成完整正式方案
|
|
|
|
|
|
|
|
|
|
|
|
### B. Transform gizmo 的绘制链路已经正规化,但来源还偏临时
|
|
|
|
|
|
|
|
|
|
|
|
当前 transform gizmo 的 solver、状态机、屏幕几何、handle records 已经大量进入 canonical overlay 路线,这是好的。
|
|
|
|
|
|
|
|
|
|
|
|
但当前仍然有两个收口问题:
|
|
|
|
|
|
- `SceneViewPanel` 仍然参与了 transform gizmo 输入组装与 transient overlay 提交
|
|
|
|
|
|
- `ViewportHostService` 仍然通过 `SetSceneViewTransientTransformGizmoOverlayData(...)` 注入一份“临时 overlay”
|
|
|
|
|
|
|
|
|
|
|
|
这说明 transform gizmo 还没有真正变成一套由 SceneView gizmo system 自己统一调度的 provider,而是“正规链路 + 临时桥接层”并存。
|
|
|
|
|
|
|
|
|
|
|
|
### C. Orientation gizmo 仍然走 ImGui / HUD 路线
|
|
|
|
|
|
|
|
|
|
|
|
这本身不算错误,因为 orientation gizmo 本质上就是 HUD,而不是 world overlay。
|
|
|
|
|
|
|
|
|
|
|
|
真正的问题在于:
|
|
|
|
|
|
- 当前 HUD overlay 与 world overlay 的系统边界还没有被正式命名
|
|
|
|
|
|
- `SceneViewportOverlayRenderer.cpp` 还承担着一个“历史遗留收容层”的角色
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
**不是所有 gizmo 都必须迁入 GPU world pass。SceneView 右上角 orientation gizmo 属于 HUD,可以继续保留在 editor UI 层,但应该被正式归类为 HUD overlay,而不是继续以“杂项 overlay”存在。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1.3 当前最核心的架构问题:SceneView 语义泄漏进了 engine
|
|
|
|
|
|
|
|
|
|
|
|
### A. grid / outline 不应该继续作为 engine 的 builtin scene semantics 存在
|
|
|
|
|
|
|
|
|
|
|
|
当前 `CameraRenderRequest::BuiltinPostProcessRequest` 直接携带:
|
|
|
|
|
|
- `InfiniteGridPassData`
|
|
|
|
|
|
- `selectedObjectIds`
|
|
|
|
|
|
- `ObjectIdOutlineStyle`
|
|
|
|
|
|
|
|
|
|
|
|
这在工程上能跑,但从架构边界看是不对的。原因很简单:
|
|
|
|
|
|
|
|
|
|
|
|
- SceneView infinite grid 是编辑器语义,不是 runtime camera 的通用语义
|
|
|
|
|
|
- Scene selection outline 是编辑器语义,不是 runtime scene 的通用语义
|
|
|
|
|
|
- `debugSelectionMask` 更是纯 editor 调试语义
|
|
|
|
|
|
|
|
|
|
|
|
如果这些字段挂在 engine 的公共 camera request 上,等价于让 runtime camera API 默认理解 SceneView 的编辑器概念。
|
|
|
|
|
|
|
|
|
|
|
|
这与 Unity 风格不一致。
|
|
|
|
|
|
|
|
|
|
|
|
### B. 具体 editor 效果被注册成 engine builtin shader / builtin resource
|
|
|
|
|
|
|
|
|
|
|
|
当前 engine builtin resource 中已经出现:
|
|
|
|
|
|
- `builtin://shaders/object-id-outline`
|
|
|
|
|
|
- `builtin://shaders/infinite-grid`
|
|
|
|
|
|
|
|
|
|
|
|
这意味着:
|
|
|
|
|
|
- runtime 资源表里已经掺入 editor SceneView 专用效果
|
|
|
|
|
|
- 后续 player/package 很容易继续被这些 editor-only 资源污染
|
|
|
|
|
|
- engine API 会逐步被 SceneView 需求反向牵着走
|
|
|
|
|
|
|
|
|
|
|
|
### C. SceneView 的 post scene policy 目前仍然依赖 engine 内建的固定流程
|
|
|
|
|
|
|
|
|
|
|
|
现在 `SceneView` 的 grid / outline 虽然是从 editor 发起,但执行上还是通过 engine builtin postprocess builder 被硬编码规划:
|
|
|
|
|
|
- `SceneInfiniteGrid`
|
|
|
|
|
|
- `SceneSelectionOutline`
|
|
|
|
|
|
- `SceneSelectionMaskDebug`
|
|
|
|
|
|
|
|
|
|
|
|
这相当于 SceneView 的一部分渲染语义并不真正属于 editor,而是“借用 engine builtin 实现”。
|
|
|
|
|
|
|
|
|
|
|
|
短期可用,长期会越来越难维护。
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
**当前系统最大的结构性缺陷,不是 gizmo 样式,而是 editor 语义与 runtime 语义没有彻底分层。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1.4 仍然偏临时的实现点
|
|
|
|
|
|
|
|
|
|
|
|
### A. icon 资源加载仍然是 ad hoc 文件路径解析
|
|
|
|
|
|
|
|
|
|
|
|
`SceneViewportEditorOverlayPass` 当前直接解析:
|
|
|
|
|
|
- `editor/resources/Icons/camera_gizmo.png`
|
|
|
|
|
|
- `editor/resources/Icons/main_light_gizmo.png`
|
|
|
|
|
|
|
|
|
|
|
|
问题在于:
|
|
|
|
|
|
- 没有 editor 内建资源注册表
|
|
|
|
|
|
- 没有生命周期与缓存抽象
|
|
|
|
|
|
- 没有 icon atlas / versioning / fallback 策略
|
|
|
|
|
|
- 这条链仍然像“功能先跑起来”的工程写法
|
|
|
|
|
|
|
|
|
|
|
|
### B. gizmo provider 没有正式注册点
|
|
|
|
|
|
|
|
|
|
|
|
当前 camera/light gizmo 是 `SceneViewportOverlayBuilder` 直接扫描 scene 后构建。
|
|
|
|
|
|
|
|
|
|
|
|
这在功能上可行,但有明显扩展隐患:
|
|
|
|
|
|
- 新增 gizmo 类型时会继续堆进单个 builder
|
|
|
|
|
|
- provider 的职责无法单测
|
|
|
|
|
|
- 组件与 gizmo 的映射关系不清晰
|
|
|
|
|
|
- 后续 collider / reflection probe / audio source / particle / custom component gizmo 很难优雅接入
|
|
|
|
|
|
|
|
|
|
|
|
### C. 视觉图元与交互图元虽然已经接近统一,但规范还不完整
|
|
|
|
|
|
|
|
|
|
|
|
现在 `handleRecords` 已经是一个很好的方向,但还缺少更明确的约束:
|
|
|
|
|
|
- 哪些图元负责可见渲染
|
|
|
|
|
|
- 哪些记录负责 hit test
|
|
|
|
|
|
- 同一 handle 是否允许多份可视 primitive
|
|
|
|
|
|
- 优先级、遮挡、深度模式、拾取扩张半径等是否有统一规则
|
|
|
|
|
|
|
|
|
|
|
|
当前这些规则大多“隐含在代码里”,还没有真正上升为系统规范。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1.5 测试体系现状
|
|
|
|
|
|
|
|
|
|
|
|
当前测试并不差,但仍然没有覆盖到最关键的“正式化边界”。
|
|
|
|
|
|
|
|
|
|
|
|
已有较好覆盖:
|
|
|
|
|
|
- grid 数学与相机投影相关测试
|
|
|
|
|
|
- render flow utils 测试
|
|
|
|
|
|
- object id picker 测试
|
|
|
|
|
|
- move / rotate / scale gizmo solver 测试
|
|
|
|
|
|
|
|
|
|
|
|
当前缺口:
|
|
|
|
|
|
- `SceneViewportOverlayBuilder` 的 contract 测试不足
|
|
|
|
|
|
- `SceneViewportEditorOverlayPass` 的资源契约与 primitive 分发测试不足
|
|
|
|
|
|
- camera / light gizmo provider 行为测试不足
|
|
|
|
|
|
- SceneView pass 顺序与装配测试不足
|
|
|
|
|
|
- “editor-only 资源不污染 runtime” 的构建层测试缺失
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
**当前最大测试缺口不是数学公式,而是架构边界、provider 契约、pass 组合关系。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. Unity 风格的目标架构
|
|
|
|
|
|
|
|
|
|
|
|
## 2.1 总体原则
|
|
|
|
|
|
|
|
|
|
|
|
参考 Unity 的思路,应当把 SceneView 可视化拆成三层:
|
|
|
|
|
|
|
|
|
|
|
|
### Layer A:Runtime Render Capability(属于 `engine`)
|
|
|
|
|
|
|
|
|
|
|
|
负责“能画什么”:
|
|
|
|
|
|
- scene geometry 渲染
|
|
|
|
|
|
- object id 渲染
|
|
|
|
|
|
- render pass 扩展点
|
|
|
|
|
|
- 通用 full-screen / line / sprite / mesh / debug primitive 渲染能力
|
|
|
|
|
|
- 后端抽象、资源绑定、shader 编译与执行
|
|
|
|
|
|
|
|
|
|
|
|
### Layer B:SceneView Gizmo Orchestration(属于 `editor`)
|
|
|
|
|
|
|
|
|
|
|
|
负责“为什么画、何时画、画哪些”:
|
|
|
|
|
|
- SceneView grid
|
|
|
|
|
|
- selection outline
|
|
|
|
|
|
- camera / light / helper gizmo
|
|
|
|
|
|
- transform gizmo
|
|
|
|
|
|
- Scene icon
|
|
|
|
|
|
- gizmo subset 调度
|
|
|
|
|
|
- 交互 handle 组织与命中规则
|
|
|
|
|
|
|
|
|
|
|
|
### Layer C:HUD Overlay(属于 `editor UI`)
|
|
|
|
|
|
|
|
|
|
|
|
负责固定在面板屏幕空间的内容:
|
|
|
|
|
|
- orientation gizmo
|
|
|
|
|
|
- toolbar
|
|
|
|
|
|
- 状态提示
|
|
|
|
|
|
- 调试开关
|
|
|
|
|
|
- 2D 操作提示与 hover 标签
|
|
|
|
|
|
|
|
|
|
|
|
这三层之间的关系应该是:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
engine 提供绘制能力
|
|
|
|
|
|
editor SceneView 决定 world gizmo / editor pass 计划
|
|
|
|
|
|
editor UI 决定 HUD 展示
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2 Unity-like 的关键不是“都放 engine”,而是“runtime 与 editor 的语义边界清楚”
|
|
|
|
|
|
|
|
|
|
|
|
Unity 的本质做法并不是让 player runtime 永远背着 SceneView gizmo 语义。
|
|
|
|
|
|
|
|
|
|
|
|
更接近本项目的正确映射应当是:
|
|
|
|
|
|
|
|
|
|
|
|
- `engine` 对应 Unity 中底层 render context / renderer capability
|
|
|
|
|
|
- `editor` 的 SceneView 系统对应 Unity 中 SceneView 对 gizmos / wire overlay / handles 的调度
|
|
|
|
|
|
- `HUD` 对应 SceneView 窗口自己的 UI overlay
|
|
|
|
|
|
|
|
|
|
|
|
因此本项目的最终方案应当遵循:
|
|
|
|
|
|
|
|
|
|
|
|
1. `engine` 暴露“generic render extension seam”
|
|
|
|
|
|
2. `editor` 组装 SceneView 专属 render plan
|
|
|
|
|
|
3. SceneView 的 gizmo/grid/outline 作为 editor-only feature 实现
|
|
|
|
|
|
4. runtime/player 构建不再默认携带 SceneView 语义资产
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.3 正式目标流水线
|
|
|
|
|
|
|
|
|
|
|
|
推荐的 SceneView 渲染时序如下:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
PreScenePasses
|
|
|
|
|
|
-> Scene Geometry
|
|
|
|
|
|
-> ObjectId Pass
|
|
|
|
|
|
-> SceneView Editor PostScene Passes
|
|
|
|
|
|
- Grid
|
|
|
|
|
|
- Selection Outline
|
|
|
|
|
|
- Future: bounds / selection mask visualize / editor-only debug fullscreen pass
|
|
|
|
|
|
-> SceneView World Overlay Pass
|
|
|
|
|
|
- Scene icons
|
|
|
|
|
|
- Camera frustum
|
|
|
|
|
|
- Light gizmos
|
|
|
|
|
|
- Transform gizmos
|
|
|
|
|
|
- Future: collider / audio / volume / probe gizmos
|
|
|
|
|
|
-> SceneView HUD Overlay
|
|
|
|
|
|
- Orientation gizmo
|
|
|
|
|
|
- Toolbar
|
|
|
|
|
|
- Labels / hints / debug text
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这里面最关键的一点是:
|
|
|
|
|
|
|
|
|
|
|
|
- `grid` 和 `selection outline` 仍然属于 world-space / scene-view editor pass
|
|
|
|
|
|
- 但它们不再属于 engine 的 builtin camera semantics
|
|
|
|
|
|
- 它们应该变成 editor 自己构建的 post-scene pass chain
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.4 Gizmo 系统内部应再拆三类数据
|
|
|
|
|
|
|
|
|
|
|
|
最终系统不应只有“画什么”,还要清楚地区分三种数据:
|
|
|
|
|
|
|
|
|
|
|
|
### A. Visual Primitive Data
|
|
|
|
|
|
|
|
|
|
|
|
纯视觉数据:
|
|
|
|
|
|
- line
|
|
|
|
|
|
- billboard sprite
|
|
|
|
|
|
- mesh / wire mesh
|
|
|
|
|
|
- screen triangle
|
|
|
|
|
|
|
|
|
|
|
|
### B. Handle Interaction Data
|
|
|
|
|
|
|
|
|
|
|
|
纯交互数据:
|
|
|
|
|
|
- handle id
|
|
|
|
|
|
- entity id
|
|
|
|
|
|
- pick shape
|
|
|
|
|
|
- priority
|
|
|
|
|
|
- depth / sort rule
|
|
|
|
|
|
- hit thickness / pick expansion
|
|
|
|
|
|
|
|
|
|
|
|
### C. Gizmo Provider Output
|
|
|
|
|
|
|
|
|
|
|
|
语义层输出:
|
|
|
|
|
|
- Camera gizmo provider 输出 camera icon + frustum + camera specific handles
|
|
|
|
|
|
- Light gizmo provider 输出 light icon + light shape
|
|
|
|
|
|
- Transform gizmo provider 输出 axis / plane / ring / center handles
|
|
|
|
|
|
|
|
|
|
|
|
这样做的好处是:
|
|
|
|
|
|
- 视觉可以演进
|
|
|
|
|
|
- 交互可以演进
|
|
|
|
|
|
- provider 可以独立测试
|
|
|
|
|
|
- 不会再把 SceneViewPanel 变成绘制器 + 命中器 + 业务调度器的混合体
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 最终职责边界
|
|
|
|
|
|
|
|
|
|
|
|
## 3.1 `engine` 应保留的内容
|
|
|
|
|
|
|
|
|
|
|
|
以下内容应明确保留在 `engine`:
|
|
|
|
|
|
|
|
|
|
|
|
- `RenderPass` / `RenderPassSequence`
|
|
|
|
|
|
- `CameraRenderer` 的 pass 执行骨架
|
|
|
|
|
|
- scene geometry 渲染
|
|
|
|
|
|
- object id pass
|
|
|
|
|
|
- render target / state transition / descriptor / backend shader compilation
|
|
|
|
|
|
- 如果未来可复用,则保留“无 editor 语义”的底层 helper
|
|
|
|
|
|
- full-screen quad/blit helper
|
|
|
|
|
|
- line primitive renderer helper
|
|
|
|
|
|
- sprite billboard renderer helper
|
|
|
|
|
|
- debug mesh renderer helper
|
|
|
|
|
|
|
|
|
|
|
|
核心要求:
|
|
|
|
|
|
**这些能力必须是 generic 的,不能带 SceneView / Gizmo / Editor 的具体业务语义。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3.2 `editor` 应拥有的内容
|
|
|
|
|
|
|
|
|
|
|
|
以下内容应明确归 `editor`:
|
|
|
|
|
|
|
|
|
|
|
|
- SceneView grid
|
|
|
|
|
|
- selection outline 及其颜色、宽度、debug mask 策略
|
|
|
|
|
|
- camera / light scene icon
|
|
|
|
|
|
- camera frustum
|
|
|
|
|
|
- directional / point / spot light gizmo
|
|
|
|
|
|
- transform gizmo
|
|
|
|
|
|
- orientation gizmo
|
|
|
|
|
|
- 组件到 gizmo provider 的注册关系
|
|
|
|
|
|
- editor-only gizmo shader / icon / material / texture 资源
|
|
|
|
|
|
|
|
|
|
|
|
换句话说:
|
|
|
|
|
|
**凡是只有 SceneView 才关心的“显示语义”,最终都必须回收到 `editor`。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3.3 可以下沉到 `engine` 的只有“无语义 helper”,不是 SceneView 语义本身
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- 如果 full-screen outline 的底层执行流程是通用的,可以提炼成 helper
|
|
|
|
|
|
- 如果 world line / billboard / wire mesh 的 GPU 提交代码是通用的,可以提炼成 helper
|
|
|
|
|
|
|
|
|
|
|
|
但是不能继续暴露成这样的 engine 公共语义:
|
|
|
|
|
|
- `SceneInfiniteGrid`
|
|
|
|
|
|
- `SceneSelectionOutline`
|
|
|
|
|
|
- `debugSelectionMask`
|
|
|
|
|
|
|
|
|
|
|
|
原则非常简单:
|
|
|
|
|
|
|
|
|
|
|
|
**实现可以共享,语义不能泄漏。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 正式重构方案
|
|
|
|
|
|
|
|
|
|
|
|
## 4.1 Phase 1:先把 SceneView pass 规划权完全收回 editor
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
让 `editor` 自己决定 SceneView 需要哪些 pass,而不是继续把 grid / outline 塞进 `engine::BuiltinPostProcessRequest`。
|
|
|
|
|
|
|
|
|
|
|
|
### 方案
|
|
|
|
|
|
|
|
|
|
|
|
新增 editor 侧的 SceneView render planning 层,例如:
|
|
|
|
|
|
- `SceneViewportRenderPlan`
|
|
|
|
|
|
- `SceneViewportPassChainBuilder`
|
|
|
|
|
|
|
|
|
|
|
|
由它负责:
|
|
|
|
|
|
- 生成 SceneView 的 `postScenePasses`
|
|
|
|
|
|
- 生成 SceneView 的 `overlayPasses`
|
|
|
|
|
|
- 规划 object id 是否需要
|
|
|
|
|
|
- 规划 grid / outline / gizmo 的具体顺序
|
|
|
|
|
|
|
|
|
|
|
|
### 结果
|
|
|
|
|
|
|
|
|
|
|
|
`CameraRenderRequest` 仍然保留:
|
|
|
|
|
|
- `preScenePasses`
|
|
|
|
|
|
- `postScenePasses`
|
|
|
|
|
|
- `overlayPasses`
|
|
|
|
|
|
|
|
|
|
|
|
但 `BuiltinPostProcessRequest` 不再继续承载 SceneView 专属语义。
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- `SceneView` 渲染路径不再依赖 `BuiltinPostProcessRequest` 中的 grid / outline 字段
|
|
|
|
|
|
- SceneView pass 顺序完全由 editor 侧 builder 决定
|
|
|
|
|
|
- engine 只负责执行 pass,不再理解 SceneView 概念
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4.2 Phase 2:把 Grid 与 Selection Outline 从 engine builtin 中迁出
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
完成这次重构中最关键的一刀:**切断 SceneView editor 语义对 engine builtin postprocess 的依赖。**
|
|
|
|
|
|
|
|
|
|
|
|
### 方案
|
|
|
|
|
|
|
|
|
|
|
|
在 `editor/src/Viewport/Passes` 新建 editor-owned passes:
|
|
|
|
|
|
- `SceneViewportGridPass`
|
|
|
|
|
|
- `SceneViewportSelectionOutlinePass`
|
|
|
|
|
|
|
|
|
|
|
|
如果当前实现代码中有通用部分,可以这样拆:
|
|
|
|
|
|
|
|
|
|
|
|
- `engine`
|
|
|
|
|
|
- 保留无语义的 GPU helper
|
|
|
|
|
|
- `editor`
|
|
|
|
|
|
- 维护 `SceneViewportGridPassData`
|
|
|
|
|
|
- 维护 `SceneViewportSelectionOutlineSettings`
|
|
|
|
|
|
- 维护 SceneView 下的调用时机与参数策略
|
|
|
|
|
|
|
|
|
|
|
|
### 需要同步迁移的内容
|
|
|
|
|
|
|
|
|
|
|
|
- `InfiniteGridPassData` 从 engine 公共 camera request 中移除
|
|
|
|
|
|
- `ObjectIdOutlineStyle` 不再作为 engine camera request 的 editor 语义字段暴露
|
|
|
|
|
|
- `builtin://shaders/infinite-grid`
|
|
|
|
|
|
- `builtin://shaders/object-id-outline`
|
|
|
|
|
|
|
|
|
|
|
|
上述资源应迁移为 editor-owned builtin 资源,或至少从注册语义上变为 editor 专属。
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- runtime build 不再默认依赖 SceneView grid / outline shader
|
|
|
|
|
|
- `CameraRenderRequest` 不再携带 SceneView grid / outline 语义
|
|
|
|
|
|
- SceneView grid / outline 仍能正常工作,并维持现有视觉效果
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4.3 Phase 3:建立正式的 Gizmo Provider Registry
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
把当前“一个大 builder 扫全场”的模式,升级为“SceneView 系统调度多个 provider”。
|
|
|
|
|
|
|
|
|
|
|
|
### 建议接口
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
ISceneViewportGizmoProvider
|
|
|
|
|
|
Gather(const SceneViewportGizmoBuildContext&, SceneViewportOverlayFrameData&)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 建议首批 provider
|
|
|
|
|
|
|
|
|
|
|
|
- `SceneCameraGizmoProvider`
|
|
|
|
|
|
- `SceneLightGizmoProvider`
|
|
|
|
|
|
- `SceneTransformHandleProvider`
|
|
|
|
|
|
- `SceneSelectionHelperProvider`
|
|
|
|
|
|
|
|
|
|
|
|
后续可继续扩展:
|
|
|
|
|
|
- collider gizmo provider
|
|
|
|
|
|
- audio source gizmo provider
|
|
|
|
|
|
- reflection probe gizmo provider
|
|
|
|
|
|
- custom editor component gizmo provider
|
|
|
|
|
|
|
|
|
|
|
|
### 为什么必须这么做
|
|
|
|
|
|
|
|
|
|
|
|
因为 Unity-like 的 SceneView 不是“一个巨大 builder 拼所有形状”,而是“editor 根据对象类型和选择状态,调度多种 gizmo provider / handle provider / wire provider”。
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- `SceneViewportOverlayBuilder` 从单体 builder 退化为 orchestration layer
|
|
|
|
|
|
- 新增 gizmo 类型时,不需要继续往一个 cpp 文件里堆逻辑
|
|
|
|
|
|
- provider 可以独立单测
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4.4 Phase 4:把 World Overlay 与 HUD Overlay 正式分家
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
让系统命名和责任与实际表现一致。
|
|
|
|
|
|
|
|
|
|
|
|
### 最终划分
|
|
|
|
|
|
|
|
|
|
|
|
#### World Overlay
|
|
|
|
|
|
|
|
|
|
|
|
使用 renderer pass:
|
|
|
|
|
|
- scene icons
|
|
|
|
|
|
- frustum
|
|
|
|
|
|
- light shapes
|
|
|
|
|
|
- transform gizmos
|
|
|
|
|
|
- future helper volumes
|
|
|
|
|
|
|
|
|
|
|
|
#### HUD Overlay
|
|
|
|
|
|
|
|
|
|
|
|
使用 editor UI / ImGui:
|
|
|
|
|
|
- orientation gizmo
|
|
|
|
|
|
- toolbar
|
|
|
|
|
|
- screen label
|
|
|
|
|
|
- 操作提示
|
|
|
|
|
|
|
|
|
|
|
|
### 注意
|
|
|
|
|
|
|
|
|
|
|
|
这一步不是要求 orientation gizmo 也上 GPU。
|
|
|
|
|
|
|
|
|
|
|
|
正确目标是:
|
|
|
|
|
|
- world-space 的内容不再走 ImGui
|
|
|
|
|
|
- HUD 的内容明确归 UI
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- `SceneViewportOverlayRenderer.cpp` 不再承担历史兼容杂项职责
|
|
|
|
|
|
- 所有 world-anchored overlay 都从统一 world overlay frame 进入
|
|
|
|
|
|
- HUD overlay 有独立职责命名
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4.5 Phase 5:建立 editor gizmo 资源体系
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
消除当前 ad hoc 图标与 shader 资源加载方式。
|
|
|
|
|
|
|
|
|
|
|
|
### 方案
|
|
|
|
|
|
|
|
|
|
|
|
新增 editor 资源注册层,例如:
|
|
|
|
|
|
- `EditorBuiltinResourceRegistry`
|
|
|
|
|
|
- `EditorGizmoResourceRegistry`
|
|
|
|
|
|
|
|
|
|
|
|
负责:
|
|
|
|
|
|
- icon texture 注册
|
|
|
|
|
|
- gizmo shader 注册
|
|
|
|
|
|
- gizmo material / pipeline preset 注册
|
|
|
|
|
|
- future atlas / hot reload / fallback
|
|
|
|
|
|
|
|
|
|
|
|
### 具体要求
|
|
|
|
|
|
|
|
|
|
|
|
- 不再在 pass 内部直接写文件路径解析作为长期方案
|
|
|
|
|
|
- camera / light / future icons 统一纳入 editor builtin 资源
|
|
|
|
|
|
- gizmo pass 通过资源 key 查询,而不是硬编码本地 png 路径
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- gizmo 资源加载路径统一
|
|
|
|
|
|
- 资源生命周期与缓存不再散落在单个 pass 里
|
|
|
|
|
|
- future 新增 icon / shader 不需要继续复制粘贴路径解析代码
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4.6 Phase 6:测试体系重构
|
|
|
|
|
|
|
|
|
|
|
|
### 目标
|
|
|
|
|
|
|
|
|
|
|
|
让测试覆盖系统边界,而不只是覆盖若干数学细节。
|
|
|
|
|
|
|
|
|
|
|
|
### 建议补齐的测试类别
|
|
|
|
|
|
|
|
|
|
|
|
#### A. Provider contract tests
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- camera provider 在 camera enabled 时输出 icon + frustum
|
|
|
|
|
|
- disabled camera 不输出 gizmo
|
|
|
|
|
|
- directional / point / spot light 分别输出正确图元组合
|
|
|
|
|
|
|
|
|
|
|
|
#### B. Overlay builder orchestration tests
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- 多 provider 输出能正确合并到单帧 overlay data
|
|
|
|
|
|
- selected / unselected subset 行为正确
|
|
|
|
|
|
- provider 顺序不影响 hit test 规则
|
|
|
|
|
|
|
|
|
|
|
|
#### C. Pass assembly tests
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- SceneView render plan 能生成正确的 `postScenePasses`
|
|
|
|
|
|
- SceneView world overlay pass 顺序正确
|
|
|
|
|
|
- object id / outline / gizmo 的依赖关系正确
|
|
|
|
|
|
|
|
|
|
|
|
#### D. Editor resource contract tests
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- icon key 能解析到合法资源
|
|
|
|
|
|
- 缺失资源时能给出可诊断 fallback
|
|
|
|
|
|
|
|
|
|
|
|
#### E. Packaging / build boundary tests
|
|
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
- player runtime target 不依赖 editor gizmo shader / icon 资源
|
|
|
|
|
|
- editor target 才链接或注册 SceneView gizmo 资源
|
|
|
|
|
|
|
|
|
|
|
|
### 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
- 新增 gizmo 类型时,至少有 provider contract test
|
|
|
|
|
|
- 修改 SceneView pass 顺序时,至少有 render plan test 可以兜底
|
|
|
|
|
|
- editor/runtime 边界错误能通过构建或测试尽早暴露
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 关于 Picking 与 Handle 命中的最终建议
|
|
|
|
|
|
|
|
|
|
|
|
## 5.1 Scene object picking
|
|
|
|
|
|
|
|
|
|
|
|
当前对象选择已经基于 object-id buffer,这条路线应保留。
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
- 这是正规的 GPU picking
|
|
|
|
|
|
- 它与场景真实渲染结果一致性更好
|
|
|
|
|
|
- 更适合 editor 里对 mesh / model / future submesh 的对象级选中
|
|
|
|
|
|
|
|
|
|
|
|
## 5.2 Gizmo handle picking
|
|
|
|
|
|
|
|
|
|
|
|
当前 gizmo handle 的命中是基于 canonical `handleRecords` 的 CPU hit test。
|
|
|
|
|
|
|
|
|
|
|
|
这不是临时方案,反而是合理的正式方案之一。
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
- gizmo handle 本身就是高度人工设计的 screen-space / mixed-space 交互图元
|
|
|
|
|
|
- CPU 命中更容易做 priority、命中扩张、前后景优先级、hover 宽容度
|
|
|
|
|
|
- 没必要为了“全 GPU 化”把 handles 也做成 object-id pass
|
|
|
|
|
|
|
|
|
|
|
|
最终建议:
|
|
|
|
|
|
- Scene object picking:继续 GPU object-id
|
|
|
|
|
|
- Gizmo handle picking:继续 CPU hit test,但必须建立在统一 canonical handle 数据之上
|
|
|
|
|
|
|
|
|
|
|
|
这与 Unity 的使用体验和工程组织都更接近。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 对当前代码的具体重构建议
|
|
|
|
|
|
|
|
|
|
|
|
## 6.1 立即保留、不要动错的部分
|
|
|
|
|
|
|
|
|
|
|
|
- 保留 `CameraRenderer` 的 pass 时序骨架
|
|
|
|
|
|
- 保留 `overlayPasses`
|
|
|
|
|
|
- 保留 `SceneViewportEditorOverlayData`
|
|
|
|
|
|
- 保留 `SceneViewportEditorOverlayPass`
|
|
|
|
|
|
- 保留 object-id picking
|
|
|
|
|
|
|
|
|
|
|
|
这些是已经验证正确的基础设施,不应推翻重做。
|
|
|
|
|
|
|
|
|
|
|
|
## 6.2 应优先迁出的部分
|
|
|
|
|
|
|
|
|
|
|
|
- `BuiltinPostProcessRequest` 中的 SceneView 语义字段
|
|
|
|
|
|
- `BuiltinInfiniteGridPass`
|
|
|
|
|
|
- `BuiltinObjectIdOutlinePass`
|
|
|
|
|
|
- SceneView 专属 shader 的 engine builtin 注册
|
|
|
|
|
|
|
|
|
|
|
|
## 6.3 应逐步拆分的部分
|
|
|
|
|
|
|
|
|
|
|
|
- `SceneViewportOverlayBuilder`
|
|
|
|
|
|
- `ViewportHostService` 中 SceneView overlay / transient gizmo 的编排逻辑
|
|
|
|
|
|
- `SceneViewPanel` 中仍然残留的 gizmo orchestration 代码
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 推荐落地顺序
|
|
|
|
|
|
|
|
|
|
|
|
为避免大爆炸式重写,建议严格按下面顺序推进:
|
|
|
|
|
|
|
|
|
|
|
|
1. 先做 Phase 1
|
|
|
|
|
|
- editor 拿回 SceneView pass 规划权
|
|
|
|
|
|
- 不要先拆 gizmo provider
|
|
|
|
|
|
|
|
|
|
|
|
2. 再做 Phase 2
|
|
|
|
|
|
- grid / outline 脱离 engine builtin
|
|
|
|
|
|
- 先保证边界正确
|
|
|
|
|
|
|
|
|
|
|
|
3. 再做 Phase 3
|
|
|
|
|
|
- provider registry
|
|
|
|
|
|
- camera / light / transform 分 provider
|
|
|
|
|
|
|
|
|
|
|
|
4. 再做 Phase 4
|
|
|
|
|
|
- 正式命名 HUD 与 world overlay 的分层
|
|
|
|
|
|
|
|
|
|
|
|
5. 然后做 Phase 5
|
|
|
|
|
|
- 资源体系
|
|
|
|
|
|
|
|
|
|
|
|
6. 最后做 Phase 6
|
|
|
|
|
|
- 测试与 packaging 收口
|
|
|
|
|
|
|
|
|
|
|
|
核心原则:
|
|
|
|
|
|
**不要先推翻正在工作的 overlay pass;应当先纠正语义归属,再做 provider 化和资源化。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 非目标
|
|
|
|
|
|
|
|
|
|
|
|
本轮重构不应顺手扩展成以下主题:
|
|
|
|
|
|
|
|
|
|
|
|
- render graph 改造
|
|
|
|
|
|
- gameplay runtime debug draw 系统
|
|
|
|
|
|
- 把所有 ImGui HUD 都迁到 GPU
|
|
|
|
|
|
- 把 gizmo handle picking 也改成 GPU object-id
|
|
|
|
|
|
- 重写整个 editor UI 框架
|
|
|
|
|
|
|
|
|
|
|
|
这些都不是本轮的主目标。
|
|
|
|
|
|
|
|
|
|
|
|
本轮的唯一主目标是:
|
|
|
|
|
|
**把 SceneView gizmo / grid / outline 的系统边界、调度方式、资源归属、测试契约一次性做正规。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 完成态判定标准
|
|
|
|
|
|
|
|
|
|
|
|
当以下条件全部满足时,可以认为本轮正式化重构收口:
|
|
|
|
|
|
|
|
|
|
|
|
1. `engine` 不再公开 SceneView grid / outline 的具体 camera 语义
|
|
|
|
|
|
2. `editor` 自己构建 SceneView post-scene passes 与 world overlay passes
|
|
|
|
|
|
3. camera / light / transform gizmo 由正式 provider 输出
|
|
|
|
|
|
4. orientation gizmo 被正式归类为 HUD overlay
|
|
|
|
|
|
5. gizmo 图标和 shader 拥有 editor 侧资源注册体系
|
|
|
|
|
|
6. player runtime 构建不再依赖 SceneView gizmo 资源
|
|
|
|
|
|
7. 测试覆盖 provider、render plan、resource boundary 三类关键契约
|
|
|
|
|
|
|
|
|
|
|
|
达到这一步后,当前 SceneView gizmo 系统才算真正进入“可持续扩展”的阶段。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 本文档对应的直接行动建议
|
|
|
|
|
|
|
|
|
|
|
|
下一阶段的实施建议如下:
|
|
|
|
|
|
|
|
|
|
|
|
1. 先开一个“SceneView pass ownership 回收”阶段
|
|
|
|
|
|
- 目标只做 Phase 1 + Phase 2
|
|
|
|
|
|
- 不在同一阶段内继续大规模重写 gizmo 样式
|
|
|
|
|
|
|
|
|
|
|
|
2. 该阶段完成后,再开“Gizmo Provider Registry”阶段
|
|
|
|
|
|
- 先把 camera / light provider 正式拆出
|
|
|
|
|
|
- transform gizmo provider 最后并入
|
|
|
|
|
|
|
|
|
|
|
|
3. 再开“Editor Gizmo Resources + Tests 收口”阶段
|
|
|
|
|
|
- 把图标、shader、测试边界一次性清干净
|
|
|
|
|
|
|
|
|
|
|
|
这会比“看到哪改哪、边做边塞进现有 builder”稳定得多。
|
|
|
|
|
|
|
2026-04-03 15:43:21 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 11. 进度更新 2026-04-03
|
|
|
|
|
|
|
|
|
|
|
|
本轮已完成“SceneView pass ownership 回收”的最后一个收口步骤:
|
|
|
|
|
|
|
|
|
|
|
|
1. `engine` 不再注册 SceneView 专属的 `object-id-outline` / `infinite-grid` builtin shader
|
|
|
|
|
|
2. `BuiltinInfiniteGridPass` 与 `BuiltinObjectIdOutlinePass` 改为由调用方注入 shader 路径
|
|
|
|
|
|
3. SceneView grid / outline shader 已迁移到 `editor/resources/shaders/scene-viewport`
|
|
|
|
|
|
4. `editor` 通过自己的 shader 路径入口组装这两个 pass
|
|
|
|
|
|
5. 已补齐 editor 侧 shader 路径与加载测试,并回归验证 runtime builtin shader 测试
|
|
|
|
|
|
|
|
|
|
|
|
对应结论:
|
|
|
|
|
|
|
|
|
|
|
|
- Phase 1:已完成
|
|
|
|
|
|
- Phase 2:已完成并收口
|
|
|
|
|
|
- Phase 3 及后续阶段:仍待继续推进
|
2026-04-03 15:52:13 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 12. 下一阶段执行计划 2026-04-03
|
|
|
|
|
|
|
|
|
|
|
|
基于当前真实代码状态,下一阶段不应继续直接堆叠新 gizmo 功能,而应优先完成 `Phase 3: Gizmo Provider Registry`。当前最主要的结构性问题有三处:
|
|
|
|
|
|
|
|
|
|
|
|
1. `SceneViewportOverlayBuilder` 仍是大单体
|
|
|
|
|
|
- camera gizmo
|
|
|
|
|
|
- light gizmo
|
|
|
|
|
|
- scene icon / frustum / helper 生成逻辑仍堆在同一处
|
|
|
|
|
|
|
|
|
|
|
|
2. `SceneViewPanel` 仍参与 transform gizmo 的 transient overlay 注入
|
|
|
|
|
|
- 仍通过 `SetSceneViewTransientTransformGizmoOverlayData(...)` 把临时 frame data 注入宿主
|
|
|
|
|
|
- 这说明 transform gizmo 还没有真正并入正式 provider 体系
|
|
|
|
|
|
|
|
|
|
|
|
3. `OrientationGizmo` 仍属于 HUD/ImGui 历史链路
|
|
|
|
|
|
- 现在功能上可用
|
|
|
|
|
|
- 但尚未在架构层被正式命名为 HUD overlay
|
|
|
|
|
|
|
|
|
|
|
|
因此,下一阶段推荐拆成如下 4 个可执行小阶段。
|
|
|
|
|
|
|
|
|
|
|
|
### 12.1 Phase 3A:Overlay Provider Registry 落地
|
|
|
|
|
|
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 把“谁负责生成 SceneView world overlay”从 `SceneViewportOverlayBuilder` 中拆出
|
|
|
|
|
|
- 让 `builder` 退化成聚合器,而不是所有 gizmo 规则的实现者
|
|
|
|
|
|
|
|
|
|
|
|
本阶段应新增:
|
|
|
|
|
|
- `ISceneViewportOverlayProvider`
|
|
|
|
|
|
- `SceneViewportOverlayProviderRegistry`
|
|
|
|
|
|
- `SceneViewportOverlayBuildContext`
|
|
|
|
|
|
|
|
|
|
|
|
本阶段应先拆出的 provider:
|
|
|
|
|
|
- `SceneViewportCameraOverlayProvider`
|
|
|
|
|
|
- `SceneViewportLightOverlayProvider`
|
|
|
|
|
|
|
|
|
|
|
|
本阶段不应做:
|
|
|
|
|
|
- 不修改 gizmo 样式
|
|
|
|
|
|
- 不动 transform gizmo 交互算法
|
|
|
|
|
|
- 不改 orientation gizmo
|
|
|
|
|
|
|
|
|
|
|
|
完成标志:
|
|
|
|
|
|
- `SceneViewportOverlayBuilder` 不再直接内嵌 camera/light 具体生成逻辑
|
|
|
|
|
|
- provider 可以按顺序注册并聚合输出 `SceneViewportOverlayFrameData`
|
|
|
|
|
|
- SceneView 现有 camera/light 图标、frustum、directional light helper 视觉结果保持不变
|
|
|
|
|
|
|
|
|
|
|
|
建议测试:
|
|
|
|
|
|
- provider registry 装配顺序测试
|
|
|
|
|
|
- camera provider contract 测试
|
|
|
|
|
|
- light provider contract 测试
|
|
|
|
|
|
- 现有 overlay render flow 测试继续通过
|
|
|
|
|
|
|
|
|
|
|
|
### 12.2 Phase 3B:Transform Gizmo 并入正式 Provider 体系
|
|
|
|
|
|
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 去掉当前的 transient gizmo overlay 桥接层
|
|
|
|
|
|
- 让 move / rotate / scale gizmo 和其他 SceneView overlay 一样,成为正式 provider 输出
|
|
|
|
|
|
|
|
|
|
|
|
本阶段应处理:
|
|
|
|
|
|
- `SceneViewPanel` 中 gizmo frame 组织逻辑
|
|
|
|
|
|
- `ViewportHostService` 中的 transient overlay 存储字段
|
|
|
|
|
|
- `SceneViewportTransformGizmoFrameBuilder`
|
|
|
|
|
|
|
|
|
|
|
|
建议方向:
|
|
|
|
|
|
- 引入 `SceneViewportTransformGizmoOverlayProvider`
|
|
|
|
|
|
- provider 输入来自统一的 gizmo state / selection state / camera state
|
|
|
|
|
|
- 输出仍然是统一的 `worldLines / screenTriangles / handleRecords`
|
|
|
|
|
|
|
|
|
|
|
|
本阶段完成后,应删除或废弃:
|
|
|
|
|
|
- `SetSceneViewTransientTransformGizmoOverlayData(...)`
|
|
|
|
|
|
- `m_sceneViewTransientTransformGizmoOverlay`
|
|
|
|
|
|
- `m_sceneViewTransientTransformGizmoInputs`
|
|
|
|
|
|
|
|
|
|
|
|
完成标志:
|
|
|
|
|
|
- `SceneViewPanel` 不再向宿主注入临时 gizmo overlay 数据
|
|
|
|
|
|
- `ViewportHostService` 只消费正式 overlay provider 输出
|
|
|
|
|
|
- move / rotate / scale gizmo 交互行为不回退
|
|
|
|
|
|
|
|
|
|
|
|
建议测试:
|
|
|
|
|
|
- move/rotate/scale gizmo provider 输出测试
|
|
|
|
|
|
- overlay handle hit test 回归测试
|
|
|
|
|
|
- SceneView render plan 下 gizmo 仍能正常显示与拾取
|
|
|
|
|
|
|
|
|
|
|
|
### 12.3 Phase 4:HUD Overlay 与 World Overlay 正式分层
|
|
|
|
|
|
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 把当前“能工作但还没正式命名”的 HUD 链路正规化
|
|
|
|
|
|
- 明确区分 `world overlay` 与 `HUD overlay`
|
|
|
|
|
|
|
|
|
|
|
|
本阶段应做:
|
|
|
|
|
|
- 保留 `SceneViewportEditorOverlayPass` 作为 world overlay GPU pass
|
|
|
|
|
|
- 将 `SceneViewportOverlayRenderer` 明确归类为 HUD overlay renderer
|
|
|
|
|
|
- 将 `OrientationGizmo` 明确纳入 HUD overlay 体系
|
|
|
|
|
|
|
|
|
|
|
|
本阶段之后的职责边界应为:
|
|
|
|
|
|
- `world overlay`
|
|
|
|
|
|
- scene icon
|
|
|
|
|
|
- camera frustum
|
|
|
|
|
|
- light helper
|
|
|
|
|
|
- transform gizmo
|
|
|
|
|
|
- `HUD overlay`
|
|
|
|
|
|
- orientation gizmo
|
|
|
|
|
|
- Scene toolbar
|
|
|
|
|
|
- 后续 label / hint / debug text
|
|
|
|
|
|
|
|
|
|
|
|
完成标志:
|
|
|
|
|
|
- world/HUD 两条链路命名清楚
|
|
|
|
|
|
- orientation gizmo 不再被视为历史遗留杂项
|
|
|
|
|
|
- 后续 HUD 元素可持续接入,而不再向 world overlay 污染
|
|
|
|
|
|
|
|
|
|
|
|
建议测试:
|
|
|
|
|
|
- HUD overlay 独立渲染入口测试
|
|
|
|
|
|
- SceneView panel 中 HUD/world 顺序与命中关系测试
|
|
|
|
|
|
|
|
|
|
|
|
### 12.4 Phase 5:Editor Gizmo 资源体系继续收口
|
|
|
|
|
|
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 继 shader 之后,把 gizmo 相关 editor 资源定位逻辑继续集中
|
|
|
|
|
|
|
|
|
|
|
|
本阶段建议新增:
|
|
|
|
|
|
- `SceneViewportResourcePaths` 或等价 editor resource locator
|
|
|
|
|
|
|
|
|
|
|
|
本阶段应纳入统一入口的内容:
|
|
|
|
|
|
- gizmo shader 路径
|
|
|
|
|
|
- camera/light icon 路径
|
|
|
|
|
|
- 后续如果引入 mesh/wire helper 资源,也走同一入口
|
|
|
|
|
|
|
|
|
|
|
|
本阶段不要求:
|
|
|
|
|
|
- 不必立刻做 atlas
|
|
|
|
|
|
- 不必引入复杂资源注册中心
|
|
|
|
|
|
|
|
|
|
|
|
完成标志:
|
|
|
|
|
|
- panel/pass 内不再到处手写 `exeDir/../../resources/...`
|
|
|
|
|
|
- editor 资源定位逻辑集中,便于后续 packaging 与迁移
|
|
|
|
|
|
|
|
|
|
|
|
建议测试:
|
|
|
|
|
|
- 资源路径解析测试
|
|
|
|
|
|
- working directory 改变后的 editor 资源加载测试
|
|
|
|
|
|
|
|
|
|
|
|
### 12.5 Phase 6:测试与打包边界收口
|
|
|
|
|
|
|
|
|
|
|
|
目标:
|
|
|
|
|
|
- 把当前已经成型的边界真正测住
|
|
|
|
|
|
|
|
|
|
|
|
需要补齐的关键测试类别:
|
|
|
|
|
|
|
|
|
|
|
|
1. provider contract
|
|
|
|
|
|
- provider 输入什么
|
|
|
|
|
|
- 必须输出什么
|
|
|
|
|
|
- 禁止输出什么
|
|
|
|
|
|
|
|
|
|
|
|
2. render assembly contract
|
|
|
|
|
|
- SceneView render plan 如何装配 post-scene / overlay / HUD
|
|
|
|
|
|
|
|
|
|
|
|
3. resource boundary
|
|
|
|
|
|
- editor-only shader / icon 不污染 runtime builtin
|
|
|
|
|
|
- player/runtime 构建不依赖 SceneView 专属资源
|
|
|
|
|
|
|
|
|
|
|
|
4. interaction regression
|
|
|
|
|
|
- gizmo handle hit test
|
|
|
|
|
|
- scene icon picking
|
|
|
|
|
|
- HUD 与 world overlay 的点击优先级
|
|
|
|
|
|
|
|
|
|
|
|
完成标志:
|
|
|
|
|
|
- 当前 plan 第 9 节中的 7 条完成态判定标准全部可被验证
|
|
|
|
|
|
|
|
|
|
|
|
### 12.6 推荐执行顺序
|
|
|
|
|
|
|
|
|
|
|
|
严格建议按下面顺序推进,不要跳阶段:
|
|
|
|
|
|
|
|
|
|
|
|
1. Phase 3A
|
|
|
|
|
|
2. Phase 3B
|
|
|
|
|
|
3. Phase 4
|
|
|
|
|
|
4. Phase 5
|
|
|
|
|
|
5. Phase 6
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
- 先做 provider 化,才能消除 `builder` 与 `SceneViewPanel` 的持续膨胀
|
|
|
|
|
|
- 先做 transform gizmo provider 化,后面 HUD/world 分层才不会再被临时桥接逻辑牵制
|
|
|
|
|
|
- 资源与测试应在结构稳定后统一收口,而不是提前做成半成品
|
|
|
|
|
|
|
|
|
|
|
|
### 12.7 下一次会话的直接开工点
|
|
|
|
|
|
|
|
|
|
|
|
下一次正式实施时,优先执行 `Phase 3A`,并以如下拆分作为第一批提交目标:
|
|
|
|
|
|
|
|
|
|
|
|
1. 新建 `ISceneViewportOverlayProvider`
|
|
|
|
|
|
2. 新建 `SceneViewportOverlayProviderRegistry`
|
|
|
|
|
|
3. 抽离 `SceneViewportCameraOverlayProvider`
|
|
|
|
|
|
4. 抽离 `SceneViewportLightOverlayProvider`
|
|
|
|
|
|
5. 让 `SceneViewportOverlayBuilder` 改为只负责:
|
|
|
|
|
|
- 构建上下文
|
|
|
|
|
|
- 调用 provider registry
|
|
|
|
|
|
- 合并 `SceneViewportOverlayFrameData`
|
|
|
|
|
|
|
|
|
|
|
|
这一步完成后,当前 SceneView gizmo 系统才算真正进入“可持续扩展”的第二阶段。
|
2026-04-03 16:26:20 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 13. 进度更新 2026-04-03 Phase 3A 已完成
|
|
|
|
|
|
|
|
|
|
|
|
本次已完成 `Phase 3A: Overlay Provider Registry 落地`,且已经通过代码、测试与 editor 编译验证。
|
|
|
|
|
|
|
|
|
|
|
|
已落地内容:
|
|
|
|
|
|
|
|
|
|
|
|
1. 新增 `SceneViewportOverlayBuildContext`
|
|
|
|
|
|
2. 新增 `ISceneViewportOverlayProvider`
|
|
|
|
|
|
3. 新增 `SceneViewportOverlayProviderRegistry`
|
|
|
|
|
|
4. 新增默认 provider:
|
|
|
|
|
|
- `SceneViewportCameraOverlayProvider`
|
|
|
|
|
|
- `SceneViewportLightOverlayProvider`
|
|
|
|
|
|
5. `SceneViewportOverlayBuilder` 已从大单体逻辑改为 provider 聚合器
|
|
|
|
|
|
6. `ViewportHostService` 已改为持有 `SceneViewportOverlayBuilder` 实例,而不是依赖静态构建入口
|
|
|
|
|
|
|
|
|
|
|
|
本阶段行为保持不变的部分:
|
|
|
|
|
|
|
|
|
|
|
|
- `BuildSceneViewEditorOverlayContentSignature(...)` 未改
|
|
|
|
|
|
- `SceneViewPanel` 的 transient transform gizmo 注入链路未改
|
|
|
|
|
|
- orientation gizmo / HUD 分层未改
|
|
|
|
|
|
- grid / outline pass 未改
|
|
|
|
|
|
|
|
|
|
|
|
新增验证:
|
|
|
|
|
|
|
|
|
|
|
|
1. `SceneViewportOverlayProviderRegistryTest.AppendsProvidersInRegistrationOrder`
|
|
|
|
|
|
2. `SceneViewportOverlayProviderRegistryTest.CameraProviderBuildsSceneIconAndSelectedFrustum`
|
|
|
|
|
|
3. `SceneViewportOverlayProviderRegistryTest.LightProviderBuildsSceneIconAndSelectedDirectionalHelper`
|
|
|
|
|
|
4. `SceneViewportOverlayProviderRegistryTest.OverlayBuilderUsesDefaultRegistryToAggregateCameraAndLightProviders`
|
|
|
|
|
|
|
|
|
|
|
|
已执行验证:
|
|
|
|
|
|
|
|
|
|
|
|
- `cmake --build build --config Debug --target editor_tests -- /p:BuildProjectReferences=false`
|
|
|
|
|
|
- `build/tests/Editor/Debug/editor_tests.exe --gtest_filter=SceneViewportOverlayProviderRegistryTest.*:ViewportRenderFlowUtilsTest.*`
|
|
|
|
|
|
- `cmake --build build --config Debug --target XCEditor`
|
|
|
|
|
|
|
|
|
|
|
|
阶段结论:
|
|
|
|
|
|
|
|
|
|
|
|
- Phase 3A 已完成并可作为后续 `Phase 3B: Transform Gizmo 并入正式 Provider 体系` 的稳定起点
|
|
|
|
|
|
- 当前 `camera/light overlay` 的职责边界已经从单体 builder 中抽离,但 `transform gizmo` 仍然保留在 transient 注入链路,需要下一阶段继续收口
|