docs: add editor runtime flow docs
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user