docs: add editor runtime flow docs

This commit is contained in:
2026-04-04 00:45:13 +08:00
parent 8abca3dec5
commit 2620b5914b
41 changed files with 2367 additions and 126 deletions

View File

@@ -6,23 +6,151 @@
**源文件**: `editor/src/panels/GameViewPanel.h`
**描述**: Game 视图面板,占位承载 Game 窗口并标记动作路由焦点
**描述**: Game 视图面板,负责在 editor 窗口中承载 `EditorViewportKind::Game` 视口内容,并把 ImGui 键鼠状态逐帧发布为 `GameViewInputFrameEvent`
## 概述
当前 `GameViewPanel` 和 [SceneViewPanel](../SceneViewPanel/SceneViewPanel.md) 一样,都属于轻量占位面板。
`GameViewPanel` 当前已经不是单纯的“薄视口壳层”。按 `GameViewPanel.cpp` 的真实实现,它承担两条并行职责:
它目前主要做两件事:
1. 调用 [ViewportPanelContent](../ViewportPanelContent/ViewportPanelContent.md) 承载 `EditorViewportKind::Game` 对应的视口纹理。
2. 从 ImGui 读取当前 Game View 的键鼠状态,打包成 [GameViewInputFrameEvent](../../Core/EditorEvents/EditorEvents.md),经 [EventBus](../../Core/EventBus/EventBus.md) 逐帧发布给 [PlaySessionController](../../Core/PlaySessionController/PlaySessionController.md)。
-`"Game"` 为名字打开一个面板窗口
- 在该窗口激活时通知 `Actions` 层观察焦点路由
因此它已经是当前 Editor 里“运行时输入桥”的起点,而不是只负责显示画面。
如果你想顺着一条连续链路理解“Game View 采样到的输入最终怎样进入运行时 `InputManager`”,可以继续看:
- [Game View Runtime Input Bridge](../../../../_guides/Editor/Game-View-Runtime-Input-Bridge.md)
## 生命周期与公开入口
- [Constructor](Constructor.md)
创建标题固定为 `"Game"` 的 Game 视图面板。
- [Render](Render.md)
渲染 Game 视口,并在每帧末尾发布 `GameViewInputFrameEvent`
## 当前执行链路
`Render()` 当前的真实顺序是:
1. 把窗口边框宽度压到 `0.0f`
2. 打开 `PanelWindowScope("Game")`
3. 如果面板未打开,立即发布一个空的 `GameViewInputFrameEvent{}`,然后返回。
4. 如果面板打开,调用:
```cpp
RenderViewportPanelContent(*m_context, EditorViewportKind::Game);
```
5. 基于返回的 `ViewportPanelContentResult` 构建 `GameViewInputFrameEvent`
6. 通过 `context->GetEventBus().Publish(event)` 发布这一帧输入快照。
7. 调用 `Actions::ObserveInactiveActionRoute(*m_context)`
这意味着 `GameViewPanel` 每一帧都会发事件,不是“只有输入变化时才发”。关闭面板时发布空事件,也是一种有意设计,用来通知下游桥接层释放之前维持的运行时输入状态。
## `GameViewInputFrameEvent` 是什么
`GameViewPanel` 发布的不是离散键盘事件,而是逐帧快照。当前快照包含:
- `hovered`
- `focused`
- `mousePosition`
- `mouseDelta`
- `mouseWheel`
- `keyDown[256]`
- `mouseButtonDown[5]`
它的含义是:
- `mousePosition`
- 以 Game View 视口左上角为原点的局部坐标。
- `mouseDelta`
- 当前帧 ImGui 观察到的鼠标位移。
- `mouseWheel`
- 只有在 `content.hovered == true` 时才会写入 `io.MouseWheel`,否则强制为 `0.0f`
- `keyDown` / `mouseButtonDown`
- 表示“这一帧视图认为当前哪些键 / 鼠标按钮处于按住态”。
它是状态快照,不是 down/up 事件流。
## 键鼠采集规则
### 键盘
`FillGameViewKeyboardState(...)` 当前维护一张固定映射表,把 `ImGuiKey` 映射到 `XCEngine::Input::KeyCode`,包括:
- `A-Z`
- `0-9`
- `Space` / `Tab` / `Enter` / `Escape`
- 左右 `Shift` / `Ctrl` / `Alt`
- 方向键、`Home/End/PageUp/PageDown`
- `Delete` / `Backspace`
- `F1-F12`
- 若干标点键
所以 `GameViewPanel` 当前不是把所有 ImGui 按键原样透传,而是只透传这张映射表覆盖到的子集。
### 鼠标
`FillGameViewMouseState(...)` 当前只采集:
- Left
- Right
- Middle
并把它们写进 `mouseButtonDown` 数组。
### hovered / focused 门控
只有在:
- `event.hovered == true`
-
- `event.focused == true`
时,`GameViewPanel` 才会填充键盘和鼠标按钮状态。
这条规则很关键,因为它决定了:
- 视口失焦时不会继续把旧键盘状态送进运行时
- 只要视口仍有焦点,即使鼠标暂时不在上面,键盘状态仍然可以继续驱动 play mode
## 和 `PlaySessionController` 的关系
`GameViewPanel` 自己不会直接调用运行时 [InputManager](../../../Input/InputManager/InputManager.md)。它只负责:
- 采集 ImGui 输入快照
-`EventBus` 发布 `GameViewInputFrameEvent`
真正的桥接发生在 [PlaySessionController](../../Core/PlaySessionController/PlaySessionController.md)
`GameViewPanel` -> `EventBus.Publish(GameViewInputFrameEvent)` -> `PlaySessionController::ApplyGameViewInputFrame()` -> `InputManager::Process*`
这条拆分让 `GameViewPanel` 仍然保持在面板层,而不会直接知道 play mode 状态机和运行时输入细节。
## 与 SceneView 的关系
当前 `GameViewPanel` 与 [SceneViewPanel](../SceneViewPanel/SceneViewPanel.md) 的关系是:
- 两者都复用 [ViewportPanelContent](../ViewportPanelContent/ViewportPanelContent.md) 作为视口承载 helper。
- `SceneViewPanel` 把输入主要送给 editor camera / gizmo 交互。
- `GameViewPanel` 把输入主要送进 `GameViewInputFrameEvent`,再桥接到运行时 `InputManager`
所以两者虽然共用 viewport 承载层,但输入去向完全不同。
## 当前实现边界
- 当前没有真正的 runtime frame 嵌入或 play mode 画面输出
- 它现在更像未来 Game View 能力的承载容器
- 当前页本身不提供 play / pause / step 控件;这些仍属于菜单栏、动作路由和 `PlaySessionController`
- 当前没有额外的 Game View toolbar、缩放菜单或 aspect 预设逻辑
- 当前发布的是状态快照,不是字符输入或完整原始平台消息。
## 相关文档
- [panels](../panels.md)
- [Actions](../../Actions/Actions.md)
- [Constructor](Constructor.md)
- [Render](Render.md)
- [ViewportPanelContent](../ViewportPanelContent/ViewportPanelContent.md)
- [EditorEvents](../../Core/EditorEvents/EditorEvents.md)
- [EventBus](../../Core/EventBus/EventBus.md)
- [PlaySessionController](../../Core/PlaySessionController/PlaySessionController.md)
- [Game View Runtime Input Bridge](../../../../_guides/Editor/Game-View-Runtime-Input-Bridge.md)
- [SceneViewPanel](../SceneViewPanel/SceneViewPanel.md)