Files
XCEngine/docs/api/XCEngine/Editor/panels/GameViewPanel/GameViewPanel.md

5.8 KiB
Raw Blame History

GameViewPanel

命名空间: XCEngine::Editor

类型: class

源文件: editor/src/panels/GameViewPanel.h

描述: Game 视图面板,负责在 editor 窗口中承载 EditorViewportKind::Game 视口内容,并把 ImGui 键鼠状态逐帧发布为 GameViewInputFrameEvent

概述

GameViewPanel 当前已经不是单纯的“薄视口壳层”。按 GameViewPanel.cpp 的真实实现,它承担两条并行职责:

  1. 调用 ViewportPanelContent 承载 EditorViewportKind::Game 对应的视口纹理。
  2. 从 ImGui 读取当前 Game View 的键鼠状态,打包成 GameViewInputFrameEvent,经 EventBus 逐帧发布给 PlaySessionController

因此它已经是当前 Editor 里“运行时输入桥”的起点,而不是只负责显示画面。

如果你想顺着一条连续链路理解“Game View 采样到的输入最终怎样进入运行时 InputManager”,可以继续看:

生命周期与公开入口

  • Constructor 创建标题固定为 "Game" 的 Game 视图面板。
  • Render 渲染 Game 视口,并在每帧末尾发布 GameViewInputFrameEvent

当前执行链路

Render() 当前的真实顺序是:

  1. 把窗口边框宽度压到 0.0f
  2. 打开 PanelWindowScope("Game")
  3. 如果面板未打开,立即发布一个空的 GameViewInputFrameEvent{},然后返回。
  4. 如果面板打开,调用:
RenderViewportPanelContent(*m_context, EditorViewportKind::Game);
  1. 基于返回的 ViewportPanelContentResult 构建 GameViewInputFrameEvent
  2. 通过 context->GetEventBus().Publish(event) 发布这一帧输入快照。
  3. 调用 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。它只负责:

  • 采集 ImGui 输入快照
  • EventBus 发布 GameViewInputFrameEvent

真正的桥接发生在 PlaySessionController

GameViewPanel -> EventBus.Publish(GameViewInputFrameEvent) -> PlaySessionController::ApplyGameViewInputFrame() -> InputManager::Process*

这条拆分让 GameViewPanel 仍然保持在面板层,而不会直接知道 play mode 状态机和运行时输入细节。

与 SceneView 的关系

当前 GameViewPanelSceneViewPanel 的关系是:

  • 两者都复用 ViewportPanelContent 作为视口承载 helper。
  • SceneViewPanel 把输入主要送给 editor camera / gizmo 交互。
  • GameViewPanel 把输入主要送进 GameViewInputFrameEvent,再桥接到运行时 InputManager

所以两者虽然共用 viewport 承载层,但输入去向完全不同。

当前实现边界

  • 当前页本身不提供 play / pause / step 控件;这些仍属于菜单栏、动作路由和 PlaySessionController
  • 当前没有额外的 Game View toolbar、缩放菜单或 aspect 预设逻辑。
  • 当前发布的是状态快照,不是字符输入或完整原始平台消息。

相关文档