feat: Play-In-Editor (PIE) with in-memory scene snapshot

Editor toolbar gains Play/Stop (Ctrl+P) with UE semantics:

- Play: serialize current scene to an in-memory YAML snapshot via new
  SceneSerializer::SerializeToString, switch display to kDisplayDirect
  (primary camera entity renders), unfreeze time (timeScale 0 -> 1)
- Stop: DeserializeFromString atomically rebuilds the pre-play scene,
  back to kDisplayViewport (editor camera), refreeze time; selection
  cleared and gizmo drag reset since all entity handles dangle
- SceneSerializer refactored: SerializeDoc/ParseRoot shared by file
  and memory variants; file Save/Load behavior unchanged
- Running state disables gizmo + editor hotkeys in the viewport (input
  goes to game scripts), draws yellow PLAYING hint and a no-camera
  warning; File->Save/Load disabled while playing (UE behavior)

Physics bodies/constraints/characters and script instances are
reconciled automatically by the existing per-frame sync on restore.
This commit is contained in:
2026-10-04 02:22:49 +08:00
parent c949e8684b
commit 2577809ee4
6 changed files with 291 additions and 59 deletions
@@ -55,6 +55,23 @@ namespace Engine::Serialization {
Assets::AssetManager& assets,
const std::string& inPath,
std::string& outEnvironmentPath);
// ---- 内存快照(同一套实体读写,不同载体)----
// 消费者:编辑器 Play-In-Editor 快照恢复、Prefab、运行时动态
// 拼装场景。documentName 仅写入文档头 "Scene" 字段(注释性),
// 快照可传实体名或留空;environmentPath 语义同文件版。
static std::string SerializeToString(
const ECS::Scene& scene,
Assets::AssetManager& assets,
const std::string& documentName = {},
const std::string& environmentPath = {});
// 失败(YAML 异常/版本过高)返回 false 且不动现场。
// 实体悬空语义同文件版 Deserialize。
static bool DeserializeFromString(ECS::Scene& scene,
Assets::AssetManager& assets,
const std::string& yamlText,
std::string& outEnvironmentPath);
};
} // namespace Engine::Serialization