From c3680258e00e1d19e1dc833cf836e35b4f792cdc Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sat, 4 Apr 2026 01:24:16 +0800 Subject: [PATCH] docs: add scene viewport interaction helper docs --- .../BuildSceneViewportHudOverlayData.md | 38 +++++++++ .../DrawSceneViewportHudOverlay.md | 37 ++++++++ .../HitTestSceneViewportHudOverlay.md | 39 +++++++++ .../SceneViewportHudOverlay.md | 73 ++++++++++++++++ .../SceneViewportHudOverlayData.md | 25 ++++++ .../SceneViewportHudOverlayHitResult.md | 24 ++++++ .../ApplySceneViewportHoveredHandleState.md | 41 +++++++++ .../BuildSceneViewportHoveredHandleState.md | 34 ++++++++ .../BuildSceneViewportInteractionActions.md | 57 +++++++++++++ ...DispatchSceneViewportInteractionActions.md | 68 +++++++++++++++ .../SceneViewportHoveredHandleState.md | 29 +++++++ .../SceneViewportInteractionActions.md | 68 +++++++++++++++ .../ToSceneViewportActiveGizmoKind.md | 29 +++++++ .../ResolveSceneViewportInteraction.md | 51 +++++++++++ .../SceneViewportInteractionResolveRequest.md | 31 +++++++ .../SceneViewportInteractionResolver.md | 72 ++++++++++++++++ .../SceneViewportInteractionResult.md | 30 +++++++ .../BuildSceneViewportAxisDragPlaneNormal.md | 39 +++++++++ .../BuildSceneViewportPlaneFromPointNormal.md | 29 +++++++ .../BuildSceneViewportProjectionMatrix.md | 31 +++++++ .../BuildSceneViewportViewMatrix.md | 28 +++++++ .../BuildSceneViewportViewProjectionMatrix.md | 32 +++++++ .../DistanceToSegmentSquared.md | 33 ++++++++ .../ProjectSceneViewportAxisDirection.md | 32 +++++++ ...rojectSceneViewportAxisDirectionAtPoint.md | 35 ++++++++ .../ProjectSceneViewportWorldPoint.md | 34 ++++++++ .../ProjectSceneViewportWorldPointClamped.md | 35 ++++++++ .../SceneViewportMath/SceneViewportMath.md | 84 +++++++++++++++++++ .../SceneViewportProjectedPoint.md | 35 ++++++++ .../DrawSceneViewportOrientationGizmo.md | 38 +++++++++ .../HitTestSceneViewportOrientationGizmo.md | 43 ++++++++++ .../SceneViewportOrientationGizmo.md | 55 ++++++++++++ docs/api/XCEngine/Editor/Viewport/Viewport.md | 7 ++ 33 files changed, 1336 insertions(+) create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/BuildSceneViewportHudOverlayData.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/DrawSceneViewportHudOverlay.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/HitTestSceneViewportHudOverlay.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlay.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayData.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayHitResult.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ApplySceneViewportHoveredHandleState.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportHoveredHandleState.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportInteractionActions.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/DispatchSceneViewportInteractionActions.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportHoveredHandleState.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportInteractionActions.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ToSceneViewportActiveGizmoKind.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/ResolveSceneViewportInteraction.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolveRequest.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolver.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResult.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportAxisDragPlaneNormal.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportPlaneFromPointNormal.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportProjectionMatrix.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewMatrix.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewProjectionMatrix.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/DistanceToSegmentSquared.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirection.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirectionAtPoint.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPoint.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPointClamped.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportMath.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportProjectedPoint.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/DrawSceneViewportOrientationGizmo.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/HitTestSceneViewportOrientationGizmo.md create mode 100644 docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/BuildSceneViewportHudOverlayData.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/BuildSceneViewportHudOverlayData.md new file mode 100644 index 00000000..9dc44e46 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/BuildSceneViewportHudOverlayData.md @@ -0,0 +1,38 @@ +# BuildSceneViewportHudOverlayData + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +## 签名 + +```cpp +inline SceneViewportHudOverlayData BuildSceneViewportHudOverlayData( + const SceneViewportOverlayData& sceneOverlay, + bool showOrientationGizmo = true); +``` + +## 作用 + +把一份 `SceneViewportOverlayData` 封装成 HUD overlay 输入。 + +## 当前行为 + +- 直接把 `sceneOverlay` 拷入结果 +- 把 `showOrientationGizmo` 写入结果 + +## 关键语义 + +- 这是一个头文件内联 helper,不做额外计算 +- `SceneViewPanel` 当前用它统一组装 hover 判定和最终绘制所需的 HUD 数据 + +## 测试覆盖 + +`tests/Editor/test_scene_viewport_overlay_renderer.cpp` 的 `BuildSceneViewportHudOverlayDataTracksVisibilityIntent` 当前验证了默认可见和显式隐藏两条路径。 + +## 相关文档 + +- [SceneViewportHudOverlay](SceneViewportHudOverlay.md) +- [SceneViewportHudOverlayData](SceneViewportHudOverlayData.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/DrawSceneViewportHudOverlay.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/DrawSceneViewportHudOverlay.md new file mode 100644 index 00000000..6a7166ca --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/DrawSceneViewportHudOverlay.md @@ -0,0 +1,37 @@ +# DrawSceneViewportHudOverlay + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +## 签名 + +```cpp +void DrawSceneViewportHudOverlay( + ImDrawList* drawList, + const SceneViewportHudOverlayData& overlay, + const ImVec2& viewportMin, + const ImVec2& viewportMax); +``` + +## 作用 + +在 Scene View 的 `ImDrawList` 上绘制前端 HUD overlay。 + +## 当前实现行为 + +- 当 `drawList == nullptr`、`overlay.HasVisibleElements() == false` 或 viewport 矩形无效时,直接返回 +- 否则先裁剪到当前 viewport 区域 +- 当前只会在 `showOrientationGizmo` 为真时调用 `DrawSceneViewportOrientationGizmo(...)` + +## 关键语义 + +- 它当前不画 transform gizmo,也不画 scene icon +- 这是一条纯前端 HUD 绘制链,不会把内容送进 GPU world overlay pass + +## 相关文档 + +- [SceneViewportHudOverlay](SceneViewportHudOverlay.md) +- [SceneViewportOrientationGizmo](../SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/HitTestSceneViewportHudOverlay.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/HitTestSceneViewportHudOverlay.md new file mode 100644 index 00000000..b5881174 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/HitTestSceneViewportHudOverlay.md @@ -0,0 +1,39 @@ +# HitTestSceneViewportHudOverlay + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +## 签名 + +```cpp +SceneViewportHudOverlayHitResult HitTestSceneViewportHudOverlay( + const SceneViewportHudOverlayData& overlay, + const ImVec2& viewportMin, + const ImVec2& viewportMax, + const ImVec2& mousePosition); +``` + +## 作用 + +把鼠标绝对位置解析成 HUD overlay 命中结果。 + +## 当前实现行为 + +- 当 HUD 不可见或 viewport 矩形无效时,返回空结果 +- 当前只会对 orientation gizmo 做命中测试 +- 命中成功时,返回: + - `kind = SceneViewportHudOverlayHitKind::OrientationAxis` + - `orientationAxis = 命中的具体轴` + +## 测试覆盖 + +`tests/Editor/test_scene_viewport_overlay_renderer.cpp` 的 `HitTestSceneViewportHudOverlaySkipsInvalidOrHiddenOverlay` 当前验证了无效和显式隐藏时会返回空结果。 + +## 相关文档 + +- [SceneViewportHudOverlay](SceneViewportHudOverlay.md) +- [SceneViewportHudOverlayHitResult](SceneViewportHudOverlayHitResult.md) +- [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlay.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlay.md new file mode 100644 index 00000000..4c29c9f6 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlay.md @@ -0,0 +1,73 @@ +# SceneViewportHudOverlay + +**命名空间**: `XCEngine::Editor` + +**类型**: `enum class + structs + free functions` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +**描述**: 定义 Scene View 前端 HUD overlay 的轻量数据结构、orientation gizmo 绘制入口以及对应的鼠标命中结果。 + +## 概览 + +`SceneViewportHudOverlay` 解决的是 Scene View 里“固定贴在 ImGui 前端的一层 HUD 交互”。 + +和 [SceneViewportEditorOverlayPass](../Passes/SceneViewportEditorOverlayPass/SceneViewportEditorOverlayPass.md) 的 GPU 世界 overlay 不同,这里处理的是: + +- orientation gizmo 的可见性开关 +- orientation gizmo 的 ImGui draw-list 绘制 +- orientation gizmo 的鼠标命中 + +当前这层 HUD 不再承担 move / rotate / scale gizmo、scene icon 或 scene line 的主绘制链路;这些内容已经分别进入 editor overlay handle 命中链和 GPU overlay pass。 + +## 公开类型与函数 + +| 成员 | 说明 | +|------|------| +| `SceneViewportHudOverlayHitKind` | 当前 HUD 命中种类枚举。 | +| [SceneViewportHudOverlayHitResult](SceneViewportHudOverlayHitResult.md) | HUD 命中结果;当前主要承载 orientation axis。 | +| [SceneViewportHudOverlayData](SceneViewportHudOverlayData.md) | 一帧 HUD overlay 的输入数据。 | +| [BuildSceneViewportHudOverlayData](BuildSceneViewportHudOverlayData.md) | 从 `SceneViewportOverlayData` 组装 HUD 数据。 | +| [DrawSceneViewportHudOverlay](DrawSceneViewportHudOverlay.md) | 把 HUD 绘制到 `ImDrawList`。 | +| [HitTestSceneViewportHudOverlay](HitTestSceneViewportHudOverlay.md) | 把鼠标位置解析成 HUD 命中结果。 | + +## 当前实现行为 + +按 `SceneViewportHudOverlay.cpp` 的实现: + +- HUD 只在 viewport 矩形有效时工作 +- 绘制时会先 `PushClipRect(viewportMin, viewportMax, true)` +- 当前唯一的可见 HUD 元素是 orientation gizmo +- 命中测试当前也只会返回 `OrientationAxis` + +## 当前在 `SceneViewPanel` 中的使用方式 + +`SceneViewPanel` 当前会在两条链路里使用它: + +- 交互判定阶段: + - 先 `BuildSceneViewportHudOverlayData(overlay)` + - 再交给 [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) 参与命中合并 +- 最终绘制阶段: + - 调用 [DrawSceneViewportHudOverlay](DrawSceneViewportHudOverlay.md) + - 只补一层 ImGui HUD / orientation gizmo + +## 与测试的对应关系 + +`tests/Editor/test_scene_viewport_overlay_renderer.cpp` 当前验证了: + +- [BuildSceneViewportHudOverlayData](BuildSceneViewportHudOverlayData.md) 会正确追踪显示 / 隐藏意图。 +- [HitTestSceneViewportHudOverlay](HitTestSceneViewportHudOverlay.md) 会在 overlay 无效或 HUD 被隐藏时直接跳过命中。 +- 与 HUD 共用的 [ProjectSceneViewportWorldPoint](../SceneViewportMath/ProjectSceneViewportWorldPoint.md) 投影规则能把场景中心稳定映射到视口中心。 + +## 当前限制 + +- 当前 HUD 只有 orientation gizmo,没有 transform gizmo 或 scene icon +- 命中结果只表达“点中了哪个朝向轴”,不直接执行相机对齐 +- 真正的相机对齐仍由 `ViewportHostService::AlignSceneViewToOrientationAxis(...)` 在更上层调用链中完成 + +## 相关文档 + +- [SceneViewportOrientationGizmo](../SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md) +- [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) +- [SceneViewportEditorOverlayPass](../Passes/SceneViewportEditorOverlayPass/SceneViewportEditorOverlayPass.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayData.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayData.md new file mode 100644 index 00000000..e1ece511 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayData.md @@ -0,0 +1,25 @@ +# SceneViewportHudOverlayData + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +## 字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `sceneOverlay` | `SceneViewportOverlayData` | orientation gizmo 绘制所需的相机/投影输入。 | +| `showOrientationGizmo` | `bool` | 当前是否允许绘制和命中 orientation gizmo。 | + +## 当前语义 + +- [HasVisibleElements](SceneViewportHudOverlay.md) 当前等价于: + - `sceneOverlay.valid && showOrientationGizmo` +- 因此这份数据既承载“相机姿态是否有效”,也承载“HUD 是否应该显示” + +## 相关文档 + +- [SceneViewportHudOverlay](SceneViewportHudOverlay.md) +- [BuildSceneViewportHudOverlayData](BuildSceneViewportHudOverlayData.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayHitResult.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayHitResult.md new file mode 100644 index 00000000..24c8e30c --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportHudOverlay/SceneViewportHudOverlayHitResult.md @@ -0,0 +1,24 @@ +# SceneViewportHudOverlayHitResult + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportHudOverlay.h` + +## 字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `kind` | `SceneViewportHudOverlayHitKind` | 当前命中种类;默认是 `None`。 | +| `orientationAxis` | `SceneViewportOrientationAxis` | 当命中 orientation gizmo 时记录具体轴向。 | + +## 当前语义 + +- `HasHit()` 当前只检查 `kind != None` +- 当前实现里,唯一有效的命中种类是 `OrientationAxis` + +## 相关文档 + +- [SceneViewportHudOverlay](SceneViewportHudOverlay.md) +- [HitTestSceneViewportHudOverlay](HitTestSceneViewportHudOverlay.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ApplySceneViewportHoveredHandleState.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ApplySceneViewportHoveredHandleState.md new file mode 100644 index 00000000..4b2726cb --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ApplySceneViewportHoveredHandleState.md @@ -0,0 +1,41 @@ +# ApplySceneViewportHoveredHandleState + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 签名 + +```cpp +void ApplySceneViewportHoveredHandleState( + const SceneViewportHoveredHandleState& hoveredHandleState, + bool gizmoActive, + bool showingMoveGizmo, + SceneViewportMoveGizmo& moveGizmo, + bool showingRotateGizmo, + SceneViewportRotateGizmo& rotateGizmo, + bool showingScaleGizmo, + SceneViewportScaleGizmo& scaleGizmo); +``` + +## 作用 + +把悬停状态写回当前显示中的各 gizmo。 + +## 当前实现行为 + +- 如果 `gizmoActive == true`,直接早退,不覆盖活动拖拽 gizmo 的句柄状态。 +- 否则按显示开关分别调用: + - `moveGizmo.SetHoveredHandle(...)` + - `rotateGizmo.SetHoveredHandle(...)` + - `scaleGizmo.SetHoveredHandle(...)` + +这保证命中解析层与 gizmo 自身 hover 表现之间只通过一份中间状态通信。 + +## 相关文档 + +- [SceneViewportHoveredHandleState](SceneViewportHoveredHandleState.md) +- [BuildSceneViewportHoveredHandleState](BuildSceneViewportHoveredHandleState.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportHoveredHandleState.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportHoveredHandleState.md new file mode 100644 index 00000000..f3b60853 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportHoveredHandleState.md @@ -0,0 +1,34 @@ +# BuildSceneViewportHoveredHandleState + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 签名 + +```cpp +SceneViewportHoveredHandleState BuildSceneViewportHoveredHandleState( + const SceneViewportInteractionResult& interaction); +``` + +## 作用 + +从统一命中结果中提取各 gizmo 需要的悬停句柄状态。 + +## 当前实现行为 + +- 先通过 `ToSceneViewportActiveGizmoKind(...)` 写入 `hoveredGizmoKind`。 +- 命中 `MoveGizmo` 时写入: + - `moveAxis` + - `movePlane` +- 命中 `RotateGizmo` 时写入 `rotateAxis`。 +- 命中 `ScaleGizmo` 时写入 `scaleHandle`。 +- 其余命中类型返回空状态。 + +## 相关文档 + +- [SceneViewportHoveredHandleState](SceneViewportHoveredHandleState.md) +- [ApplySceneViewportHoveredHandleState](ApplySceneViewportHoveredHandleState.md) +- [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportInteractionActions.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportInteractionActions.md new file mode 100644 index 00000000..7ba7e5ec --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/BuildSceneViewportInteractionActions.md @@ -0,0 +1,57 @@ +# BuildSceneViewportInteractionActions + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 签名 + +```cpp +SceneViewportInteractionActions BuildSceneViewportInteractionActions( + const SceneViewportInteractionResult& interaction, + bool hasInteractiveViewport, + bool clickedLeft, + bool canResolveViewportInteraction); +``` + +## 作用 + +把统一命中结果翻译成当前帧左键点击应该执行的动作集合。 + +## 当前实现行为 + +函数会先从 `interaction` 提取: + +- `hoveredGizmoKind` +- `orientationAxis` +- `sceneIconEntityId` + +随后按当前条件组合四个动作位: + +- `beginTransformGizmo` + - 需要 `hasInteractiveViewport` + - 需要 `clickedLeft` + - 需要命中的是 move / rotate / scale gizmo +- `orientationGizmoClick` + - 需要 `hasInteractiveViewport` + - 需要 `clickedLeft` + - 需要 `orientationAxis != None` +- `sceneIconClick` + - 需要 `hasInteractiveViewport` + - 需要 `clickedLeft` + - 需要 `sceneIconEntityId != 0` +- `selectSceneClick` + - 需要 `hasInteractiveViewport` + - 需要 `clickedLeft` + - 需要 `canResolveViewportInteraction` + - 且 `interaction.HasHit() == false` + +因此“空白区域点选场景”的兜底动作,只有在当前允许解析 viewport 交互且确实没有命中 overlay/HUD 时才会被置位。 + +## 相关文档 + +- [SceneViewportInteractionActions](SceneViewportInteractionActions.md) +- [DispatchSceneViewportInteractionActions](DispatchSceneViewportInteractionActions.md) +- [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/DispatchSceneViewportInteractionActions.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/DispatchSceneViewportInteractionActions.md new file mode 100644 index 00000000..8c2b8379 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/DispatchSceneViewportInteractionActions.md @@ -0,0 +1,68 @@ +# DispatchSceneViewportInteractionActions + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 签名 + +```cpp +void DispatchSceneViewportInteractionActions( + const SceneViewportInteractionActions& actions, + IEditorContext& context, + IViewportHostService& viewportHostService, + const ImVec2& viewportSize, + const Math::Vector2& localMousePosition); +``` + +## 作用 + +执行不属于 gizmo 拖拽生命周期本身的点击副作用:朝向对齐、scene icon 直选与 object-id picking 兜底。 + +## 当前实现行为 + +### orientation gizmo 点击 + +若 `actions.orientationGizmoClick == true`,调用: + +```cpp +viewportHostService.AlignSceneViewToOrientationAxis(actions.orientationAxis); +``` + +### scene icon 点击 + +若 `actions.sceneIconClick == true`,直接: + +```cpp +context.GetSelectionManager().SetSelectedEntity(actions.sceneIconEntityId); +``` + +并立刻返回,不再执行 scene picking。 + +### 空白区域 scene picking + +若 `actions.selectSceneClick == true`,调用: + +```cpp +viewportHostService.PickSceneViewEntity( + context, + viewportSize, + ImVec2(localMousePosition.x, localMousePosition.y)); +``` + +- 命中实体时选择该实体 +- 未命中时清空选择 + +## 当前边界 + +- 该函数不处理 gizmo `TryBeginDrag(...)`;那部分仍由 `SceneViewPanel` 自己控制。 +- 它也不处理 look / pan 导航状态。 +- 它只分发点击后的副作用。 + +## 相关文档 + +- [BuildSceneViewportInteractionActions](BuildSceneViewportInteractionActions.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) +- [IViewportHostService](../IViewportHostService/IViewportHostService.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportHoveredHandleState.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportHoveredHandleState.md new file mode 100644 index 00000000..57300296 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportHoveredHandleState.md @@ -0,0 +1,29 @@ +# SceneViewportHoveredHandleState + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `hoveredGizmoKind` | `SceneViewportActiveGizmoKind` | 当前命中的 gizmo 大类。 | +| `moveAxis` | `SceneViewportGizmoAxis` | move gizmo 轴命中。 | +| `movePlane` | `SceneViewportGizmoPlane` | move gizmo 平面命中。 | +| `rotateAxis` | `SceneViewportRotateGizmoAxis` | rotate gizmo 轴命中。 | +| `scaleHandle` | `SceneViewportScaleGizmoHandle` | scale gizmo 句柄命中。 | + +## 当前语义 + +- 这是面向 gizmo `SetHoveredHandle(...)` 的中间结构。 +- 同一时刻只会真正关心与 `hoveredGizmoKind` 对应的那一组字段。 +- 它不表达点击或选择副作用,只表达“当前鼠标悬停的是哪个 gizmo 句柄”。 + +## 相关文档 + +- [SceneViewportInteractionActions](SceneViewportInteractionActions.md) +- [BuildSceneViewportHoveredHandleState](BuildSceneViewportHoveredHandleState.md) +- [ApplySceneViewportHoveredHandleState](ApplySceneViewportHoveredHandleState.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportInteractionActions.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportInteractionActions.md new file mode 100644 index 00000000..a8b3bb4c --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/SceneViewportInteractionActions.md @@ -0,0 +1,68 @@ +# SceneViewportInteractionActions + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct + free functions` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +**描述**: 把 `SceneViewportInteractionResult` 翻译成 gizmo 悬停状态、点击语义与最终分发动作的辅助层。 + +## 概览 + +`SceneViewportInteractionActions` 是当前 Scene View 交互链路里“命中解析之后、真正执行动作之前”的收口层。 + +它解决三件事: + +- 把统一命中结果映射成各 gizmo 可直接消费的悬停状态。 +- 把“这次左键点击到底意味着什么”收口成动作结构。 +- 把 orientation 对齐、scene icon 直选与 object-id picking 兜底从 `SceneViewPanel` 内联逻辑中抽出来。 + +当前 `SceneViewPanel` 仍然保留: + +- 导航拖拽状态 +- gizmo drag begin / update / end 生命周期 + +但具体“点击语义如何解释”已经交给这层。 + +## `SceneViewportInteractionActions` 字段 + +| 字段 | 说明 | +|------|------| +| `hoveredGizmoKind` | 命中的 transform gizmo 大类。 | +| `orientationAxis` | 命中 orientation gizmo 时的目标轴。 | +| `sceneIconEntityId` | 命中 scene icon 时的实体 id。 | +| `beginTransformGizmo` | 是否应该开始 gizmo 拖拽。 | +| `orientationGizmoClick` | 是否应该执行视角对齐。 | +| `sceneIconClick` | 是否应该直接选择 scene icon 对应实体。 | +| `selectSceneClick` | 是否应该退回 object-id picking。 | + +`HasClickAction()` 当前只检查四个点击布尔位中是否至少有一个为 `true`。 + +## 公开类型与函数 + +| 成员 | 说明 | +|------|------| +| [SceneViewportHoveredHandleState](SceneViewportHoveredHandleState.md) | 各 gizmo 可直接消费的悬停状态。 | +| [ToSceneViewportActiveGizmoKind](ToSceneViewportActiveGizmoKind.md) | 把统一交互种类映射到 gizmo 大类。 | +| [BuildSceneViewportHoveredHandleState](BuildSceneViewportHoveredHandleState.md) | 从统一命中结果提取悬停句柄。 | +| [ApplySceneViewportHoveredHandleState](ApplySceneViewportHoveredHandleState.md) | 把悬停状态写回各 gizmo。 | +| [BuildSceneViewportInteractionActions](BuildSceneViewportInteractionActions.md) | 把命中结果翻译成点击动作。 | +| [DispatchSceneViewportInteractionActions](DispatchSceneViewportInteractionActions.md) | 执行 orientation 对齐、scene icon 直选与 scene picking 兜底。 | + +## 测试锚点 + +`tests/Editor/test_scene_viewport_interaction_actions.cpp` 当前覆盖了: + +- move 命中到 `SceneViewportHoveredHandleState` 的映射 +- orientation gizmo 点击动作生成 +- 空命中到 scene picking 兜底动作的生成 +- orientation 对齐动作分发 +- scene icon 点击分发 +- object-id picking 选择 / 清空选择分发 + +## 相关文档 + +- [SceneViewportInteractionResolver](../SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) +- [IViewportHostService](../IViewportHostService/IViewportHostService.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ToSceneViewportActiveGizmoKind.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ToSceneViewportActiveGizmoKind.md new file mode 100644 index 00000000..949ce00f --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionActions/ToSceneViewportActiveGizmoKind.md @@ -0,0 +1,29 @@ +# ToSceneViewportActiveGizmoKind + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionActions.h` + +## 签名 + +```cpp +SceneViewportActiveGizmoKind ToSceneViewportActiveGizmoKind(SceneViewportInteractionKind kind); +``` + +## 作用 + +把统一的 `SceneViewportInteractionKind` 映射成 gizmo 拖拽系统使用的 `SceneViewportActiveGizmoKind`。 + +## 当前实现行为 + +- `MoveGizmo` -> `SceneViewportActiveGizmoKind::Move` +- `RotateGizmo` -> `SceneViewportActiveGizmoKind::Rotate` +- `ScaleGizmo` -> `SceneViewportActiveGizmoKind::Scale` +- `OrientationGizmo` / `SceneIcon` / `None` -> `SceneViewportActiveGizmoKind::None` + +## 相关文档 + +- [SceneViewportInteractionActions](SceneViewportInteractionActions.md) +- [BuildSceneViewportInteractionActions](BuildSceneViewportInteractionActions.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/ResolveSceneViewportInteraction.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/ResolveSceneViewportInteraction.md new file mode 100644 index 00000000..b0a487ca --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/ResolveSceneViewportInteraction.md @@ -0,0 +1,51 @@ +# ResolveSceneViewportInteraction + +**命名空间**: `XCEngine::Editor` + +**类型**: `function overloads` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionResolver.h` + +## 签名 + +```cpp +SceneViewportInteractionResult ResolveSceneViewportInteraction( + const SceneViewportOverlayHandleHitResult& overlayHandleHit, + const SceneViewportHudOverlayHitResult& hudOverlayHit); + +SceneViewportInteractionResult ResolveSceneViewportInteraction( + const SceneViewportInteractionResolveRequest& request); +``` + +## 作用 + +把 Scene View 的多来源命中结果收敛成统一交互结果。 + +## 当前行为 + +### 直接合并重载 + +- 把 overlay handle 命中和 HUD 命中各自转成候选项 +- 依次比较 `priority`、`distanceSq`、`depth` 和 `secondaryPriority` +- 返回当前最优候选对应的 [SceneViewportInteractionResult](SceneViewportInteractionResult.md) + +### 请求式重载 + +- 如果 `overlayFrameData` 非空,先调用 `HitTestSceneViewportOverlayHandles(...)` +- 如果 `hudOverlay` 非空,先调用 `HitTestSceneViewportHudOverlay(...)` +- 再把两侧结果交给上面的直接合并重载 + +## 测试覆盖 + +`tests/Editor/test_scene_viewport_interaction_resolver.cpp` 当前覆盖了: + +- 两侧都空时返回 `None` +- transform handle 会按优先级压过 HUD orientation 命中 +- HUD orientation 会压过 scene icon 命中 +- 请求式重载会正确委托到 overlay handle hit test + +## 相关文档 + +- [SceneViewportInteractionResolver](SceneViewportInteractionResolver.md) +- [SceneViewportInteractionResolveRequest](SceneViewportInteractionResolveRequest.md) +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolveRequest.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolveRequest.md new file mode 100644 index 00000000..c6924c27 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolveRequest.md @@ -0,0 +1,31 @@ +# SceneViewportInteractionResolveRequest + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionResolver.h` + +## 字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `overlayFrameData` | `const SceneViewportOverlayFrameData*` | world overlay / gizmo handle 命中输入。 | +| `viewportSize` | `Math::Vector2` | 本地 viewport 尺寸。 | +| `localMousePosition` | `Math::Vector2` | viewport 本地鼠标坐标。 | +| `hudOverlay` | `const SceneViewportHudOverlayData*` | HUD overlay 命中输入。 | +| `viewportMin` | `ImVec2` | viewport 左上角绝对坐标。 | +| `viewportMax` | `ImVec2` | viewport 右下角绝对坐标。 | +| `absoluteMousePosition` | `ImVec2` | 鼠标绝对坐标。 | + +## 当前语义 + +- 这是一份“一次交互解析请求”的输入包 +- overlay handle 命中和 HUD 命中各自只消费自己需要的那部分字段 +- 某一侧输入为空时,解析器会把那一侧当作“无命中来源” + +## 相关文档 + +- [SceneViewportInteractionResolver](SceneViewportInteractionResolver.md) +- [ResolveSceneViewportInteraction](ResolveSceneViewportInteraction.md) +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolver.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolver.md new file mode 100644 index 00000000..78440f2c --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResolver.md @@ -0,0 +1,72 @@ +# SceneViewportInteractionResolver + +**命名空间**: `XCEngine::Editor` + +**类型**: `enum class + structs + free functions` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionResolver.h` + +**描述**: 把 Scene View 的 world overlay handle 命中结果和 HUD overlay 命中结果合并成统一交互结果。 + +## 概览 + +`SceneViewportInteractionResolver` 解决的是 Scene View 输入判定里的“最后一层归并”问题。 + +它的输入来自两条链路: + +- [SceneViewportOverlayHitTester](../SceneViewportOverlayHitTester/SceneViewportOverlayHitTester.md) + 产出的 world overlay / gizmo handle 命中 +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) + 产出的 orientation gizmo HUD 命中 + +它的输出是统一的 [SceneViewportInteractionResult](SceneViewportInteractionResult.md),供 `SceneViewPanel` 决定: + +- 是不是开始 move / rotate / scale gizmo 拖拽 +- 是否执行 orientation gizmo 对齐 +- 是否把点击解释为 scene icon 命中 + +## 公开类型与函数 + +| 成员 | 说明 | +|------|------| +| `SceneViewportInteractionKind` | 统一交互种类枚举。 | +| [SceneViewportInteractionResult](SceneViewportInteractionResult.md) | 统一交互结果。 | +| [SceneViewportInteractionResolveRequest](SceneViewportInteractionResolveRequest.md) | 请求式重载的输入包。 | +| [ResolveSceneViewportInteraction](ResolveSceneViewportInteraction.md) | 合并命中结果或从请求对象直接完成命中解析。 | + +## 当前实现行为 + +按 `SceneViewportInteractionResolver.cpp` 的实现: + +- 内部会把 HUD 命中和 overlay handle 命中都转成带优先级的候选项 +- 决策顺序依次比较: + - `priority` + - `distanceSq` + - `depth` + - `secondaryPriority` +- HUD orientation gizmo 当前固定使用更高优先级 +- 请求式重载会先分别调用: + - `HitTestSceneViewportOverlayHandles(...)` + - `HitTestSceneViewportHudOverlay(...)` + 然后再复用同一套候选合并逻辑 + +## 与测试的对应关系 + +`tests/Editor/test_scene_viewport_interaction_resolver.cpp` 当前覆盖了: + +- overlay 与 HUD 都为空时返回 `None`。 +- 高优先级 transform handle 会压过 HUD orientation 命中。 +- HUD orientation 会压过 scene icon 命中。 +- 请求式重载会走完整的 overlay handle hit-test 路径。 + +## 当前限制 + +- 当前只解决“命中了什么”,不执行后续动作 +- 它不持有任何交互状态,也不驱动拖拽生命周期 +- 具体拖拽开始/更新/结束仍由 `SceneViewPanel` 和各 gizmo 类处理 + +## 相关文档 + +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) +- [SceneViewportOverlayHitTester](../SceneViewportOverlayHitTester/SceneViewportOverlayHitTester.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResult.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResult.md new file mode 100644 index 00000000..35d2de54 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportInteractionResolver/SceneViewportInteractionResult.md @@ -0,0 +1,30 @@ +# SceneViewportInteractionResult + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportInteractionResolver.h` + +## 字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `kind` | `SceneViewportInteractionKind` | 当前统一交互种类。 | +| `entityId` | `uint64_t` | scene icon 命中时的对象实体 ID。 | +| `moveAxis` | `SceneViewportGizmoAxis` | move gizmo 轴命中。 | +| `movePlane` | `SceneViewportGizmoPlane` | move gizmo 平面命中。 | +| `rotateAxis` | `SceneViewportRotateGizmoAxis` | rotate gizmo 轴命中。 | +| `scaleHandle` | `SceneViewportScaleGizmoHandle` | scale gizmo 句柄命中。 | +| `orientationAxis` | `SceneViewportOrientationAxis` | orientation gizmo 轴命中。 | + +## 当前语义 + +- `HasHit()` 当前只检查 `kind != None` +- 各字段只在各自对应的 `kind` 下有效 +- 解析器不会帮调用方清理无关字段含义;调用方应按 `kind` 读取对应槽位 + +## 相关文档 + +- [SceneViewportInteractionResolver](SceneViewportInteractionResolver.md) +- [ResolveSceneViewportInteraction](ResolveSceneViewportInteraction.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportAxisDragPlaneNormal.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportAxisDragPlaneNormal.md new file mode 100644 index 00000000..ca8fd247 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportAxisDragPlaneNormal.md @@ -0,0 +1,39 @@ +# BuildSceneViewportAxisDragPlaneNormal + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +bool BuildSceneViewportAxisDragPlaneNormal( + const SceneViewportOverlayData& overlay, + const Math::Vector3& worldAxis, + Math::Vector3& outPlaneNormal); +``` + +## 作用 + +为轴向拖拽推导一个尽量稳定、且不与活动轴平行的平面法线。 + +## 当前实现行为 + +- 若 overlay 无效或轴长度退化为零,则失败。 +- 会先把活动轴归一化。 +- 然后按如下顺序尝试候选法线: + - 相机 `forward` + - 相机 `up` + - 相机 `right` + - 世界 `up` + - 世界 `right` + - 世界 `forward` +- 每个候选都会先投影到“去掉活动轴分量”的平面上;第一个非零结果会被归一化并返回。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [BuildSceneViewportPlaneFromPointNormal](BuildSceneViewportPlaneFromPointNormal.md) +- [SceneViewportMoveGizmo](../SceneViewportMoveGizmo/SceneViewportMoveGizmo.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportPlaneFromPointNormal.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportPlaneFromPointNormal.md new file mode 100644 index 00000000..3b301928 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportPlaneFromPointNormal.md @@ -0,0 +1,29 @@ +# BuildSceneViewportPlaneFromPointNormal + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +Math::Plane BuildSceneViewportPlaneFromPointNormal( + const Math::Vector3& point, + const Math::Vector3& normal); +``` + +## 作用 + +根据一个点和法线构造拖拽或求交所需的平面。 + +## 当前实现行为 + +- 会先把法线归一化。 +- 然后使用 `Math::Plane(planeNormal, -Dot(planeNormal, point))` 构造结果。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [BuildSceneViewportAxisDragPlaneNormal](BuildSceneViewportAxisDragPlaneNormal.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportProjectionMatrix.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportProjectionMatrix.md new file mode 100644 index 00000000..4d0406f3 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportProjectionMatrix.md @@ -0,0 +1,31 @@ +# BuildSceneViewportProjectionMatrix + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +Math::Matrix4x4 BuildSceneViewportProjectionMatrix( + const SceneViewportOverlayData& overlay, + float viewportWidth, + float viewportHeight); +``` + +## 作用 + +根据垂直 FOV、视口尺寸和裁剪面构造透视投影矩阵。 + +## 当前实现行为 + +- 若 `viewportHeight <= 0`,当前会把纵横比回退到 `1.0f`。 +- 其余情况下按 `viewportWidth / viewportHeight` 计算 aspect。 +- 最终调用 `Math::Matrix4x4::Perspective(...)`。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [BuildSceneViewportViewProjectionMatrix](BuildSceneViewportViewProjectionMatrix.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewMatrix.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewMatrix.md new file mode 100644 index 00000000..b2c585ea --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewMatrix.md @@ -0,0 +1,28 @@ +# BuildSceneViewportViewMatrix + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +Math::Matrix4x4 BuildSceneViewportViewMatrix(const SceneViewportOverlayData& overlay); +``` + +## 作用 + +根据当前 Scene View 相机姿态构造视图矩阵。 + +## 当前实现行为 + +- 会把 `cameraRight / cameraUp / cameraForward` 全部归一化。 +- 矩阵前三行分别使用右、上、前方向和相机位置的点积偏移组装。 +- 当前实现不额外检查 `overlay.valid`,默认由调用方保证输入有效。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [BuildSceneViewportViewProjectionMatrix](BuildSceneViewportViewProjectionMatrix.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewProjectionMatrix.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewProjectionMatrix.md new file mode 100644 index 00000000..75702345 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/BuildSceneViewportViewProjectionMatrix.md @@ -0,0 +1,32 @@ +# BuildSceneViewportViewProjectionMatrix + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +Math::Matrix4x4 BuildSceneViewportViewProjectionMatrix( + const SceneViewportOverlayData& overlay, + float viewportWidth, + float viewportHeight); +``` + +## 作用 + +组合视图矩阵与投影矩阵,得到用于世界点投影的 view-projection 矩阵。 + +## 当前实现行为 + +- 当前实现直接返回: + - `Projection * View` +- 它是 [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) 和 [ProjectSceneViewportAxisDirectionAtPoint](ProjectSceneViewportAxisDirectionAtPoint.md) 的基础。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [BuildSceneViewportViewMatrix](BuildSceneViewportViewMatrix.md) +- [BuildSceneViewportProjectionMatrix](BuildSceneViewportProjectionMatrix.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/DistanceToSegmentSquared.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/DistanceToSegmentSquared.md new file mode 100644 index 00000000..ecfc9560 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/DistanceToSegmentSquared.md @@ -0,0 +1,33 @@ +# DistanceToSegmentSquared + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +float DistanceToSegmentSquared( + const Math::Vector2& point, + const Math::Vector2& segmentStart, + const Math::Vector2& segmentEnd, + float* outSegmentT = nullptr); +``` + +## 作用 + +计算一个二维点到线段的平方距离。 + +## 当前实现行为 + +- 若线段长度退化到零,会直接退回“点到起点”的平方距离。 +- 否则会计算线段参数 `t`,并在 `[0, 1]` 内钳制。 +- 若传入了 `outSegmentT`,会回写最近点在线段上的参数位置。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [SceneViewportMoveGizmo](../SceneViewportMoveGizmo/SceneViewportMoveGizmo.md) +- [SceneViewportRotateGizmo](../SceneViewportRotateGizmo/SceneViewportRotateGizmo.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirection.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirection.md new file mode 100644 index 00000000..7e71122f --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirection.md @@ -0,0 +1,32 @@ +# ProjectSceneViewportAxisDirection + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +bool ProjectSceneViewportAxisDirection( + const SceneViewportOverlayData& overlay, + const Math::Vector3& worldAxis, + Math::Vector2& outScreenDirection); +``` + +## 作用 + +估计一个世界轴在当前视口屏幕上的二维方向。 + +## 当前实现行为 + +- 若 `overlay.valid == false`,直接失败。 +- 会先把 `worldAxis` 归一化并变换到当前视图空间。 +- 最终使用 `(viewAxis.x, -viewAxis.y)` 作为屏幕方向。 +- 若结果退化到零长度,则返回 `false`。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [ProjectSceneViewportAxisDirectionAtPoint](ProjectSceneViewportAxisDirectionAtPoint.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirectionAtPoint.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirectionAtPoint.md new file mode 100644 index 00000000..ed969788 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportAxisDirectionAtPoint.md @@ -0,0 +1,35 @@ +# ProjectSceneViewportAxisDirectionAtPoint + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +bool ProjectSceneViewportAxisDirectionAtPoint( + const SceneViewportOverlayData& overlay, + float viewportWidth, + float viewportHeight, + const Math::Vector3& worldPoint, + const Math::Vector3& worldAxis, + Math::Vector2& outScreenDirection, + float sampleDistance = 1.0f); +``` + +## 作用 + +以具体世界采样点为基准,估计一个轴在屏幕上的方向。 + +## 当前实现行为 + +- 会先校验 overlay、视口尺寸、轴长度和 `sampleDistance`。 +- 主路径是投影 `worldPoint` 与 `worldPoint + axis * sampleDistance` 两个点,然后取它们的屏幕差向量。 +- 若任一点投影失败或结果退化到零长度,则回退到 [ProjectSceneViewportAxisDirection](ProjectSceneViewportAxisDirection.md)。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [ProjectSceneViewportAxisDirection](ProjectSceneViewportAxisDirection.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPoint.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPoint.md new file mode 100644 index 00000000..97ea7490 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPoint.md @@ -0,0 +1,34 @@ +# ProjectSceneViewportWorldPoint + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +SceneViewportProjectedPoint ProjectSceneViewportWorldPoint( + const SceneViewportOverlayData& overlay, + float viewportWidth, + float viewportHeight, + const Math::Vector3& worldPoint); +``` + +## 作用 + +把世界空间点投影到 Scene View 屏幕坐标。 + +## 当前实现行为 + +- 若 `overlay` 无效或视口宽高太小,会直接返回默认结果。 +- 会先计算 clip-space 点;`clipPoint.w <= epsilon` 时直接判定不可见。 +- 否则把点除以 `w` 转成 NDC,再换算到屏幕坐标。 +- `visible` 只有在 `x/y/z` 全部位于标准裁剪范围时才为真。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [SceneViewportProjectedPoint](SceneViewportProjectedPoint.md) +- [ProjectSceneViewportWorldPointClamped](ProjectSceneViewportWorldPointClamped.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPointClamped.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPointClamped.md new file mode 100644 index 00000000..6a1e7ba9 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/ProjectSceneViewportWorldPointClamped.md @@ -0,0 +1,35 @@ +# ProjectSceneViewportWorldPointClamped + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 签名 + +```cpp +bool ProjectSceneViewportWorldPointClamped( + const SceneViewportOverlayData& overlay, + float viewportWidth, + float viewportHeight, + const Math::Vector3& worldPoint, + float edgePadding, + SceneViewportProjectedPoint& outProjectedPoint); +``` + +## 作用 + +投影世界点,并把屏幕坐标钳制到给定边缘内。 + +## 当前实现行为 + +- 会先调用 [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md)。 +- 若 overlay 无效、视口尺寸无效或深度小于 `0`,则失败。 +- 否则按 `edgePadding` 把 `screenPosition` 钳制在视口矩形内部。 + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) +- [SceneViewportProjectedPoint](SceneViewportProjectedPoint.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportMath.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportMath.md new file mode 100644 index 00000000..29b656ce --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportMath.md @@ -0,0 +1,84 @@ +# SceneViewportMath + +**命名空间**: `XCEngine::Editor` + +**类型**: `header-helper` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +**描述**: 为 Scene View overlay、gizmo 和 picking 提供统一的投影、屏幕方向、拖拽平面和距离计算 helper。 + +## 概述 + +`SceneViewportMath.h` 是 `Viewport` 模块里最基础的“几何工具层”。它把很多本来容易散落在 gizmo / picker / overlay builder 里的数学过程集中到一个地方,例如: + +- 构建 view / projection / view-projection 矩阵。 +- 世界点投影到视口屏幕坐标。 +- 世界轴投影到屏幕方向。 +- 线段距离计算。 +- 基于相机方向为轴向拖拽自动求稳定拖拽平面。 + +这类 helper 的价值很像商业引擎编辑器里的 `HandleUtility` 一类基础设施。 + +## 主要能力 + +| 函数 | 说明 | +|------|------| +| [SceneViewportProjectedPoint](SceneViewportProjectedPoint.md) | 世界点投影后的屏幕坐标、深度和可见性结果。 | +| [BuildSceneViewportViewMatrix](BuildSceneViewportViewMatrix.md) | 由 `cameraRight / Up / Forward / Position` 组装视图矩阵。 | +| [BuildSceneViewportProjectionMatrix](BuildSceneViewportProjectionMatrix.md) | 基于垂直 FOV 和视口宽高创建透视投影。 | +| [BuildSceneViewportViewProjectionMatrix](BuildSceneViewportViewProjectionMatrix.md) | 组合视图矩阵与投影矩阵。 | +| [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) | 把世界点投影为屏幕坐标和 `ndcDepth`。 | +| [ProjectSceneViewportAxisDirection](ProjectSceneViewportAxisDirection.md) | 计算世界轴在屏幕上的朝向。 | +| [ProjectSceneViewportAxisDirectionAtPoint](ProjectSceneViewportAxisDirectionAtPoint.md) | 以具体采样点为基准估计屏幕轴方向。 | +| [ProjectSceneViewportWorldPointClamped](ProjectSceneViewportWorldPointClamped.md) | 投影后做边缘钳制。 | +| [DistanceToSegmentSquared](DistanceToSegmentSquared.md) | 供 gizmo hit-test 使用的二维距离 helper。 | +| [BuildSceneViewportPlaneFromPointNormal](BuildSceneViewportPlaneFromPointNormal.md) | 由点和法线构建拖拽平面。 | +| [BuildSceneViewportAxisDragPlaneNormal](BuildSceneViewportAxisDragPlaneNormal.md) | 为轴向拖拽推导合适的平面法线。 | + +## 当前实现行为 + +- 这些 helper 全部是 `inline` 函数,没有独立 `.cpp`。 +- [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) 在 `clipPoint.w <= epsilon` 时会直接判定不可见。 +- [ProjectSceneViewportAxisDirectionAtPoint](ProjectSceneViewportAxisDirectionAtPoint.md) 会优先做两点投影采样,失败时回退到纯方向投影。 +- [BuildSceneViewportAxisDragPlaneNormal](BuildSceneViewportAxisDragPlaneNormal.md) 会按相机 forward / up / right 以及世界基轴顺序寻找一个不与拖拽轴平行的候选法线。 + +## 设计说明 + +把这些数学过程集中起来有两个收益: + +- Scene View gizmo 的 hit-test、拖拽和绘制可以共享完全一致的投影逻辑。 +- 当视口投影规则调整时,不需要分别修改 move / rotate / scale 三套代码。 + +这类“统一几何约定层”是编辑器工具质量很重要的一部分。没有它,交互往往会出现看起来能点到、实际拖起来方向不对,或者不同 gizmo 手感不一致的问题。 + +## 与测试的对应关系 + +`tests/Editor/test_scene_viewport_overlay_renderer.cpp` 当前验证了: + +- [BuildSceneViewportViewMatrix](BuildSceneViewportViewMatrix.md) 与编辑器相机 transform 约定一致。 +- [BuildSceneViewportProjectionMatrix](BuildSceneViewportProjectionMatrix.md) 和 [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) 的投影结果符合 Scene View 预期。 +- [BuildSceneViewportAxisDragPlaneNormal](BuildSceneViewportAxisDragPlaneNormal.md) 会在相机 forward 与拖拽轴对齐时回退到其它稳定法线候选。 + +## 当前限制 + +- 当前投影 helper 假设的是标准透视视口语义,不是更一般化的任意裁剪空间工具库。 +- 没有对极端数值稳定性做更重的保护,例如非常接近 near plane 的大规模场景。 + +## 相关文档 + +- [SceneViewportProjectedPoint](SceneViewportProjectedPoint.md) +- [BuildSceneViewportViewMatrix](BuildSceneViewportViewMatrix.md) +- [BuildSceneViewportProjectionMatrix](BuildSceneViewportProjectionMatrix.md) +- [BuildSceneViewportViewProjectionMatrix](BuildSceneViewportViewProjectionMatrix.md) +- [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) +- [ProjectSceneViewportAxisDirection](ProjectSceneViewportAxisDirection.md) +- [ProjectSceneViewportAxisDirectionAtPoint](ProjectSceneViewportAxisDirectionAtPoint.md) +- [ProjectSceneViewportWorldPointClamped](ProjectSceneViewportWorldPointClamped.md) +- [DistanceToSegmentSquared](DistanceToSegmentSquared.md) +- [BuildSceneViewportPlaneFromPointNormal](BuildSceneViewportPlaneFromPointNormal.md) +- [BuildSceneViewportAxisDragPlaneNormal](BuildSceneViewportAxisDragPlaneNormal.md) +- [SceneViewportMoveGizmo](../SceneViewportMoveGizmo/SceneViewportMoveGizmo.md) +- [SceneViewportRotateGizmo](../SceneViewportRotateGizmo/SceneViewportRotateGizmo.md) +- [SceneViewportScaleGizmo](../SceneViewportScaleGizmo/SceneViewportScaleGizmo.md) +- [SceneViewportPicker](../SceneViewportPicker/SceneViewportPicker.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportProjectedPoint.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportProjectedPoint.md new file mode 100644 index 00000000..64c789ce --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportMath/SceneViewportProjectedPoint.md @@ -0,0 +1,35 @@ +# SceneViewportProjectedPoint + +**命名空间**: `XCEngine::Editor` + +**类型**: `struct` + +**源文件**: `editor/src/Viewport/SceneViewportMath.h` + +## 定义 + +```cpp +struct SceneViewportProjectedPoint { + Math::Vector2 screenPosition = Math::Vector2::Zero(); + float ndcDepth = 0.0f; + bool visible = false; +}; +``` + +## 作用 + +表示一个世界点投影到 Scene View 后的屏幕坐标、深度和可见性。 + +## 字段说明 + +| 字段 | 说明 | +|------|------| +| `screenPosition` | 投影后的屏幕坐标。 | +| `ndcDepth` | 投影后的 NDC 深度。 | +| `visible` | 是否位于可见裁剪范围内。 | + +## 相关文档 + +- [SceneViewportMath](SceneViewportMath.md) +- [ProjectSceneViewportWorldPoint](ProjectSceneViewportWorldPoint.md) +- [ProjectSceneViewportWorldPointClamped](ProjectSceneViewportWorldPointClamped.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/DrawSceneViewportOrientationGizmo.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/DrawSceneViewportOrientationGizmo.md new file mode 100644 index 00000000..35ed5cc3 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/DrawSceneViewportOrientationGizmo.md @@ -0,0 +1,38 @@ +# DrawSceneViewportOrientationGizmo + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportOrientationGizmo.h` + +## 签名 + +```cpp +void DrawSceneViewportOrientationGizmo( + ImDrawList* drawList, + const SceneViewportOverlayData& overlay, + const ImVec2& viewportMin, + const ImVec2& viewportMax); +``` + +## 作用 + +在 Scene View 右上角绘制朝向 gizmo,包括中心立方体和六个方向轴帽。 + +## 当前实现行为 + +- `drawList == nullptr` 或 `overlay.valid == false` 时直接返回。 +- 会先根据 `viewportMin / viewportMax` 计算控件中心点。 +- 然后调用 `BuildSortedAxisHandles(overlay)` 生成六个方向 handle 的投影与排序数据。 +- 绘制顺序分为三段: + - 先画 `sortDepth > 0` 的前景轴帽 + - 再画中心 cube + - 最后画 `sortDepth <= 0` 的背面轴帽 +- 这种顺序让前向轴帽保持可见,同时仍然保留中心立方体对背向轴的遮挡关系。 + +## 相关文档 + +- [SceneViewportOrientationGizmo](SceneViewportOrientationGizmo.md) +- [HitTestSceneViewportOrientationGizmo](HitTestSceneViewportOrientationGizmo.md) +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/HitTestSceneViewportOrientationGizmo.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/HitTestSceneViewportOrientationGizmo.md new file mode 100644 index 00000000..18aeee19 --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/HitTestSceneViewportOrientationGizmo.md @@ -0,0 +1,43 @@ +# HitTestSceneViewportOrientationGizmo + +**命名空间**: `XCEngine::Editor` + +**类型**: `function` + +**源文件**: `editor/src/Viewport/SceneViewportOrientationGizmo.h` + +## 签名 + +```cpp +SceneViewportOrientationAxis HitTestSceneViewportOrientationGizmo( + const SceneViewportOverlayData& overlay, + const ImVec2& viewportMin, + const ImVec2& viewportMax, + const ImVec2& mousePosition); +``` + +## 作用 + +检测鼠标当前命中了哪个朝向 gizmo handle,并返回对应的语义朝向轴。 + +## 当前实现行为 + +- `overlay.valid == false` 时直接返回 `SceneViewportOrientationAxis::None`。 +- 会基于当前视口矩形重新计算控件中心。 +- 再构造一份 `AxisHandleVisual` 数组,并按 `sortDepth` 从小到大排序。 +- 随后依次调用 `HitTestAxisHandle(...)` 做命中测试,命中即返回: + - `PositiveX / NegativeX` + - `PositiveY / NegativeY` + - `PositiveZ / NegativeZ` +- 全部失败时返回 `SceneViewportOrientationAxis::None`。 + +## 设计含义 + +- 该函数只负责把 2D 点击解析成朝向语义。 +- 真正的相机对齐动作仍然由视口宿主服务执行。 + +## 相关文档 + +- [SceneViewportOrientationGizmo](SceneViewportOrientationGizmo.md) +- [DrawSceneViewportOrientationGizmo](DrawSceneViewportOrientationGizmo.md) +- [ViewportHostService](../ViewportHostService/ViewportHostService.md) diff --git a/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md new file mode 100644 index 00000000..bd72dcff --- /dev/null +++ b/docs/api/XCEngine/Editor/Viewport/SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md @@ -0,0 +1,55 @@ +# SceneViewportOrientationGizmo + +**命名空间**: `XCEngine::Editor` + +**类型**: `free functions` + +**源文件**: `editor/src/Viewport/SceneViewportOrientationGizmo.h` + +**描述**: 绘制 Scene View 右上角朝向 gizmo,并把鼠标点击解析为 `SceneViewportOrientationAxis`。 + +## 概述 + +`SceneViewportOrientationGizmo` 是 Scene View 里典型的“编辑器导航控件”。它不是变换 gizmo,也不直接修改相机,只负责两件事: + +- 在右上角绘制一个朝向立方体和轴向帽。 +- 根据鼠标点击命中返回目标朝向轴。 + +真正的相机对齐动作仍然由 [IViewportHostService](../IViewportHostService/IViewportHostService.md) / [ViewportHostService](../ViewportHostService/ViewportHostService.md) 执行。 + +## 公开函数 + +| 函数 | 说明 | +|------|------| +| [DrawSceneViewportOrientationGizmo](DrawSceneViewportOrientationGizmo.md) | 绘制右上角朝向 gizmo。 | +| [HitTestSceneViewportOrientationGizmo](HitTestSceneViewportOrientationGizmo.md) | 把鼠标位置解析为 `SceneViewportOrientationAxis`。 | + +## 当前实现行为 + +按 `SceneViewportOrientationGizmo.cpp` 的实现: + +- [DrawSceneViewportOrientationGizmo](DrawSceneViewportOrientationGizmo.md) 会把世界 `X / Y / Z` 轴转换到当前 Scene View 相机空间,并以自定义 cube + 轴向 cap 的方式绘制,而不是直接贴图。 +- [HitTestSceneViewportOrientationGizmo](HitTestSceneViewportOrientationGizmo.md) 会对轴向 handle 做独立命中测试,并返回 `PositiveX / NegativeX / ...` 这样的语义轴。 + +## 设计说明 + +这层分离很合理: + +- UI helper 只关心“点中了哪个方向”。 +- 宿主服务再决定“如何让相机朝那个方向看过去”。 + +这样绘制与状态应用不会耦合在一个类里,后续如果要替换为更复杂的 orientation widget,也不需要重写视口宿主服务。 + +## 当前限制 + +- 当前返回的是轴语义,不包含自由旋转或拖拽环导航。 +- 控件交互是点击式,不是完整的 3D trackball。 + +## 相关文档 + +- [DrawSceneViewportOrientationGizmo](DrawSceneViewportOrientationGizmo.md) +- [HitTestSceneViewportOrientationGizmo](HitTestSceneViewportOrientationGizmo.md) +- [IViewportHostService](../IViewportHostService/IViewportHostService.md) +- [ViewportHostService](../ViewportHostService/ViewportHostService.md) +- [SceneViewportHudOverlay](../SceneViewportHudOverlay/SceneViewportHudOverlay.md) +- [SceneViewPanel](../../panels/SceneViewPanel/SceneViewPanel.md) diff --git a/docs/api/XCEngine/Editor/Viewport/Viewport.md b/docs/api/XCEngine/Editor/Viewport/Viewport.md index ee5c84e6..86f72709 100644 --- a/docs/api/XCEngine/Editor/Viewport/Viewport.md +++ b/docs/api/XCEngine/Editor/Viewport/Viewport.md @@ -21,12 +21,16 @@ 当前宿主实现,持有 editor camera、render target 与 Scene View overlay 缓存。 - [SceneViewportCameraController](SceneViewportCameraController/SceneViewportCameraController.md) 维护 Scene View 相机的焦点、距离、朝向和飞行速度,并把结果写回隐藏相机变换。 +- [SceneViewportMath](SceneViewportMath/SceneViewportMath.md) + 提供投影、屏幕方向、拖拽平面和距离计算等几何 helper,供 gizmo / overlay / picker 共用。 - [SceneViewportPicker](SceneViewportPicker/SceneViewportPicker.md) 提供 CPU 射线选取 helper,当前更多用于辅助 gizmo 命中和保留的几何拾取路径。 - [ViewportObjectIdPicker](ViewportObjectIdPicker/ViewportObjectIdPicker.md) 封装 Scene View object-id 读回请求构建、像素坐标映射与颜色解码,是当前主点击选取链路的底层 helper。 - [SceneViewportHudOverlay](SceneViewportHudOverlay/SceneViewportHudOverlay.md) 负责前端 HUD / orientation gizmo 的构造、绘制和命中。 +- [SceneViewportOrientationGizmo](SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md) + 提供右上角朝向 gizmo 的绘制和点击命中,供 HUD overlay 复用。 - [SceneViewportInteractionResolver](SceneViewportInteractionResolver/SceneViewportInteractionResolver.md) 把 HUD 命中与 overlay handle 命中合并成统一交互结果。 - [SceneViewportInteractionActions](SceneViewportInteractionActions/SceneViewportInteractionActions.md) @@ -55,6 +59,9 @@ - [Editor](../Editor.md) - [SceneViewPanel](../panels/SceneViewPanel/SceneViewPanel.md) - [SceneViewportCameraController](SceneViewportCameraController/SceneViewportCameraController.md) +- [SceneViewportMath](SceneViewportMath/SceneViewportMath.md) - [SceneViewportPicker](SceneViewportPicker/SceneViewportPicker.md) - [ViewportObjectIdPicker](ViewportObjectIdPicker/ViewportObjectIdPicker.md) +- [SceneViewportHudOverlay](SceneViewportHudOverlay/SceneViewportHudOverlay.md) +- [SceneViewportOrientationGizmo](SceneViewportOrientationGizmo/SceneViewportOrientationGizmo.md) - [SceneView Interaction And Gizmo Model](../../../_guides/Editor/SceneView-Interaction-And-Gizmo-Model.md)