5.8 KiB
GameViewPanel
命名空间: XCEngine::Editor
类型: class
源文件: editor/src/panels/GameViewPanel.h
描述: Game 视图面板,负责在 editor 窗口中承载 EditorViewportKind::Game 视口内容,并把 ImGui 键鼠状态逐帧发布为 GameViewInputFrameEvent。
概述
GameViewPanel 当前已经不是单纯的“薄视口壳层”。按 GameViewPanel.cpp 的真实实现,它承担两条并行职责:
- 调用 ViewportPanelContent 承载
EditorViewportKind::Game对应的视口纹理。 - 从 ImGui 读取当前 Game View 的键鼠状态,打包成 GameViewInputFrameEvent,经 EventBus 逐帧发布给 PlaySessionController。
因此它已经是当前 Editor 里“运行时输入桥”的起点,而不是只负责显示画面。
如果你想顺着一条连续链路理解“Game View 采样到的输入最终怎样进入运行时 InputManager”,可以继续看:
生命周期与公开入口
- Constructor
创建标题固定为
"Game"的 Game 视图面板。 - Render
渲染 Game 视口,并在每帧末尾发布
GameViewInputFrameEvent。
当前执行链路
Render() 当前的真实顺序是:
- 把窗口边框宽度压到
0.0f。 - 打开
PanelWindowScope("Game")。 - 如果面板未打开,立即发布一个空的
GameViewInputFrameEvent{},然后返回。 - 如果面板打开,调用:
RenderViewportPanelContent(*m_context, EditorViewportKind::Game);
- 基于返回的
ViewportPanelContentResult构建GameViewInputFrameEvent。 - 通过
context->GetEventBus().Publish(event)发布这一帧输入快照。 - 调用
Actions::ObserveInactiveActionRoute(*m_context)。
这意味着 GameViewPanel 每一帧都会发事件,不是“只有输入变化时才发”。关闭面板时发布空事件,也是一种有意设计,用来通知下游桥接层释放之前维持的运行时输入状态。
GameViewInputFrameEvent 是什么
GameViewPanel 发布的不是离散键盘事件,而是逐帧快照。当前快照包含:
hoveredfocusedmousePositionmouseDeltamouseWheelkeyDown[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-Z0-9Space/Tab/Enter/Escape- 左右
Shift/Ctrl/Alt - 方向键、
Home/End/PageUp/PageDown Delete/BackspaceF1-F12- 若干标点键
所以 GameViewPanel 当前不是把所有 ImGui 按键原样透传,而是只透传这张映射表覆盖到的子集。
鼠标
FillGameViewMouseState(...) 当前只采集:
- Left
- Right
- Middle
并把它们写进 mouseButtonDown 数组。
hovered / focused 门控
只有在:
event.hovered == true- 或
event.focused == true
时,GameViewPanel 才会填充键盘和鼠标按钮状态。
这条规则很关键,因为它决定了:
- 视口失焦时不会继续把旧键盘状态送进运行时
- 只要视口仍有焦点,即使鼠标暂时不在上面,键盘状态仍然可以继续驱动 play mode
和 PlaySessionController 的关系
GameViewPanel 自己不会直接调用运行时 InputManager。它只负责:
- 采集 ImGui 输入快照
- 经
EventBus发布GameViewInputFrameEvent
真正的桥接发生在 PlaySessionController:
GameViewPanel -> EventBus.Publish(GameViewInputFrameEvent) -> PlaySessionController::ApplyGameViewInputFrame() -> InputManager::Process*
这条拆分让 GameViewPanel 仍然保持在面板层,而不会直接知道 play mode 状态机和运行时输入细节。
与 SceneView 的关系
当前 GameViewPanel 与 SceneViewPanel 的关系是:
- 两者都复用 ViewportPanelContent 作为视口承载 helper。
SceneViewPanel把输入主要送给 editor camera / gizmo 交互。GameViewPanel把输入主要送进GameViewInputFrameEvent,再桥接到运行时InputManager。
所以两者虽然共用 viewport 承载层,但输入去向完全不同。
当前实现边界
- 当前页本身不提供 play / pause / step 控件;这些仍属于菜单栏、动作路由和
PlaySessionController。 - 当前没有额外的 Game View toolbar、缩放菜单或 aspect 预设逻辑。
- 当前发布的是状态快照,不是字符输入或完整原始平台消息。