Make editor play mode transactional
This commit is contained in:
@@ -96,6 +96,89 @@ std::string ResolveUniqueSceneName(
|
||||
static_cast<std::uint64_t>(sceneManager.GetAllScenes().size() + 1u));
|
||||
}
|
||||
|
||||
bool IsSceneLoaded(
|
||||
const SceneManager& sceneManager,
|
||||
const Scene* scene) {
|
||||
if (scene == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<Scene*> scenes = sceneManager.GetAllScenes();
|
||||
return std::find(scenes.begin(), scenes.end(), scene) != scenes.end();
|
||||
}
|
||||
|
||||
Scene* CreateSceneFromSerializedSnapshot(
|
||||
SceneManager& sceneManager,
|
||||
ResourceManager& resourceManager,
|
||||
std::string_view requestedName,
|
||||
const std::string& serializedScene) {
|
||||
const std::string sceneName =
|
||||
ResolveUniqueSceneName(sceneManager, requestedName);
|
||||
Scene* scene = sceneManager.CreateScene(sceneName);
|
||||
if (scene == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
ResourceManager::ScopedDeferredSceneLoad deferredSceneLoad(resourceManager);
|
||||
scene->DeserializeFromString(serializedScene);
|
||||
}
|
||||
sceneManager.SetActiveScene(scene);
|
||||
return scene;
|
||||
}
|
||||
|
||||
class EngineEditorScenePlaySession final : public EditorScenePlaySession {
|
||||
public:
|
||||
EngineEditorScenePlaySession(
|
||||
SceneManager& sceneManager,
|
||||
ResourceManager& resourceManager,
|
||||
Scene* runtimeScene,
|
||||
std::string editSceneName,
|
||||
std::string editSceneSnapshot)
|
||||
: m_sceneManager(sceneManager)
|
||||
, m_resourceManager(resourceManager)
|
||||
, m_runtimeScene(runtimeScene)
|
||||
, m_editSceneName(std::move(editSceneName))
|
||||
, m_editSceneSnapshot(std::move(editSceneSnapshot)) {}
|
||||
|
||||
~EngineEditorScenePlaySession() override {
|
||||
RestoreEditScene();
|
||||
}
|
||||
|
||||
Scene* GetRuntimeScene() const override {
|
||||
return m_runtimeScene;
|
||||
}
|
||||
|
||||
private:
|
||||
void RestoreEditScene() {
|
||||
if (m_restored) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSceneLoaded(m_sceneManager, m_runtimeScene)) {
|
||||
m_sceneManager.UnloadScene(m_runtimeScene);
|
||||
}
|
||||
m_runtimeScene = nullptr;
|
||||
|
||||
if (!m_editSceneSnapshot.empty()) {
|
||||
CreateSceneFromSerializedSnapshot(
|
||||
m_sceneManager,
|
||||
m_resourceManager,
|
||||
m_editSceneName,
|
||||
m_editSceneSnapshot);
|
||||
}
|
||||
|
||||
m_restored = true;
|
||||
}
|
||||
|
||||
SceneManager& m_sceneManager;
|
||||
ResourceManager& m_resourceManager;
|
||||
Scene* m_runtimeScene = nullptr;
|
||||
std::string m_editSceneName = {};
|
||||
std::string m_editSceneSnapshot = {};
|
||||
bool m_restored = false;
|
||||
};
|
||||
|
||||
std::pair<std::string, std::string> SerializeComponent(
|
||||
const Component* component) {
|
||||
std::ostringstream payload = {};
|
||||
@@ -1824,6 +1907,43 @@ public:
|
||||
return ResolvePrimaryScene(m_sceneManager);
|
||||
}
|
||||
|
||||
std::unique_ptr<EditorScenePlaySession> BeginPlaySession() override {
|
||||
Scene* editScene = ResolvePrimaryScene(m_sceneManager);
|
||||
if (editScene == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string editSceneName = editScene->GetName().empty()
|
||||
? std::string("Untitled")
|
||||
: editScene->GetName();
|
||||
const std::string editSceneSnapshot = editScene->SerializeToString();
|
||||
if (editSceneSnapshot.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_sceneManager.UnloadScene(editScene);
|
||||
Scene* runtimeScene = CreateSceneFromSerializedSnapshot(
|
||||
m_sceneManager,
|
||||
m_resourceManager,
|
||||
editSceneName + " Play",
|
||||
editSceneSnapshot);
|
||||
if (runtimeScene == nullptr) {
|
||||
CreateSceneFromSerializedSnapshot(
|
||||
m_sceneManager,
|
||||
m_resourceManager,
|
||||
editSceneName,
|
||||
editSceneSnapshot);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<EngineEditorScenePlaySession>(
|
||||
m_sceneManager,
|
||||
m_resourceManager,
|
||||
runtimeScene,
|
||||
editSceneName,
|
||||
editSceneSnapshot);
|
||||
}
|
||||
|
||||
std::optional<EditorSceneObjectSnapshot> GetObjectSnapshot(
|
||||
std::string_view itemId) const override {
|
||||
const GameObject* gameObject = FindGameObject(itemId);
|
||||
|
||||
Reference in New Issue
Block a user