新增 GameFlow 运行时状态机:PIE 与独立运行统一生命周期

Stopped→Loading→Running↔Paused 单一状态源,编辑器 Play/Stop
与 main.cpp 独立运行共用同一套加载/恢复/暂停语义
This commit is contained in:
2026-10-08 17:02:09 +08:00
parent f73e52926f
commit f327f44269
7 changed files with 329 additions and 62 deletions
+39 -8
View File
@@ -23,9 +23,12 @@
#include <Engine/Core/Stats.h>
#include <Engine/Renderer/Renderer.h>
#include <Engine/Renderer/EditorCamera.h>
#include <Engine/Serialization/SceneSerializer.h>
#include <Engine/Core/Input.h>
#include <filesystem>
// editor/game 编译期分离(HELLOVULKAN_EDITOR CMake option):editor 形态
// 挂接 docking Editor;game 形态 = Direct 直渲 + primary 相机,零编辑器代码
#ifdef HELLO_EDITOR
@@ -66,7 +69,9 @@ namespace
InitEditor();
#else
// game 形态:全窗口 Direct 直渲(Renderer 默认即 kDisplayDirect),
// 相机由场景 primary camera 提供,无 UI
// 相机由场景 primary camera 提供,无 UI。
// 游戏流:Stopped → Loading(OnUpdate 泵场景加载)→ Running
GetGameFlow().RequestStart();
#endif
}
@@ -84,7 +89,31 @@ namespace
GetRenderer().GetEditorCamera().Update(frameTime.UnscaledDt());
}
#else
(void)frameTime; // game 形态:本沙盒无游戏逻辑
// Loading 泵(同步示例):场景文件存在则加载,不存在 =
// 空场景照常进 Running(引擎冒烟路径)。加载完成后必须
// CompleteLoading,否则物理/脚本门控永远跳过(卡死 Loading)
if (GetGameFlow().IsIn(GameFlowState::Loading))
{
if (std::filesystem::exists(m_ScenePath))
{
if (Serialization::SceneSerializer::Deserialize(
GetScene(), GetAssets(), m_ScenePath))
{
ENGINE_INFO("Game: scene loaded from {}", m_ScenePath);
}
else
{
ENGINE_ERROR("Game: scene load failed: {}",
m_ScenePath);
}
}
else
{
ENGINE_WARN("Game: scene file not found ({}), "
"starting empty", m_ScenePath);
}
GetGameFlow().CompleteLoading();
}
#endif
}
@@ -99,16 +128,14 @@ namespace
// ---- 事件 ----
#ifdef HELLO_EDITOR
void OnWindowClose(const Event& event) override
{
#ifdef HELLO_EDITOR
// 退出确认走 Editor 的模态框(ImGui 必须可见才有 UI)
SetImGuiEnabled(true);
m_Editor->RequestQuit();
#else
(void)event;
#endif
}
#endif
void OnKeyPress(const Event& event) override
{
@@ -141,9 +168,10 @@ namespace
ctx.scene = &GetScene();
ctx.assets = &GetAssets();
ctx.app = this;
ctx.flow = &GetGameFlow();
ctx.editorCamera = &GetRenderer().GetEditorCamera();
// 继承原沙盒默认:初始暂停(StatsPanel 的 Pause Simulation 开关恢复)
Time::SetTimeScale(0.0f);
// 编辑器态默认冻结:GameFlow 构造即 timeScale=0(Stopped 语义),
// timeScale 权威在 GameFlow,此处不再手设
m_Editor->Init(ctx);
// 输入归属:覆盖 EnableImGui 的全局 WantCapture* 谓词
@@ -158,6 +186,9 @@ namespace
private:
std::unique_ptr<Editor> m_Editor = std::make_unique<Editor>();
#else
// game 形态:启动场景路径(CWD = bin;编辑器 Save 的产物位置)
const char* m_ScenePath = "assets/scenes/sandbox.scene";
#endif
};
}