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
+15
View File
@@ -55,6 +55,17 @@ public:
// 请求退出(弹确认框;窗口关闭事件走这里)
void RequestQuit() { m_ShowQuitConfirm = true; }
// ---- PIE(Play-In-Editor,UE 工具栏语义)----
bool IsPlaying() const { return m_Playing; }
// Play:内存快照当前场景 → 切游戏渲染(primary 相机)→ 解冻时间;
// Stop:快照原子换血恢复 → 回编辑器渲染 → 冻结时间。
// 编辑器态默认 timeScale=0(物理冻结 = UE 语义),Play 解冻
void TogglePlay();
private:
void DoPlay(); // TogglePlay 的 Play 半程(快照 + 切渲染 + 解冻)
void DoStop(); // TogglePlay 的 Stop 半程(恢复 + 回编辑器 + 冻结)
// ---- 选中状态 ----
// 同步描边:Renderer 落帧后 SelectionMask/Outline 只画选中实体
//(bits = 实体位模式,0 = 清选中)
@@ -109,6 +120,10 @@ private:
bool m_ShowSaveModal = false;
bool m_ShowLoadModal = false;
char m_ScenePathBuf[256] = "scenes/sandbox.scene";
// PIE 状态:Play 时场景 YAML 内存快照,Stop 时原子换血恢复
bool m_Playing = false;
std::string m_PlaySnapshot;
};
#endif //HELLOVULKAN_EDITOR_H