feat: add runtime play tick and play-mode scene editing semantics

This commit is contained in:
2026-04-02 19:37:35 +08:00
parent e30f5d5ffa
commit fb15d60be9
28 changed files with 2016 additions and 45 deletions

View File

@@ -0,0 +1,83 @@
#include <gtest/gtest.h>
#include "Core/EditorContext.h"
#include "Core/EditorEvents.h"
#include "Core/PlaySessionController.h"
#include <XCEngine/Core/Math/Vector3.h>
namespace XCEngine::Editor {
namespace {
class PlaySessionControllerTest : public ::testing::Test {
protected:
void SetUp() override {
m_context.GetSceneManager().NewScene("Play Session Scene");
}
EditorContext m_context;
PlaySessionController m_controller;
};
TEST_F(PlaySessionControllerTest, StartPlayClonesCurrentSceneAndStopRestoresEditorScene) {
auto* editorEntity = m_context.GetSceneManager().CreateEntity("Persistent");
ASSERT_NE(editorEntity, nullptr);
const uint64_t editorEntityId = editorEntity->GetID();
editorEntity->GetTransform()->SetLocalPosition(Math::Vector3(1.0f, 2.0f, 3.0f));
int startedCount = 0;
int stoppedCount = 0;
const uint64_t startedSubscription = m_context.GetEventBus().Subscribe<PlayModeStartedEvent>(
[&](const PlayModeStartedEvent&) {
++startedCount;
});
const uint64_t stoppedSubscription = m_context.GetEventBus().Subscribe<PlayModeStoppedEvent>(
[&](const PlayModeStoppedEvent&) {
++stoppedCount;
});
ASSERT_TRUE(m_controller.StartPlay(m_context));
EXPECT_EQ(m_context.GetRuntimeMode(), EditorRuntimeMode::Play);
EXPECT_EQ(startedCount, 1);
auto* runtimeEntity = m_context.GetSceneManager().GetEntity(editorEntityId);
ASSERT_NE(runtimeEntity, nullptr);
runtimeEntity->GetTransform()->SetLocalPosition(Math::Vector3(8.0f, 9.0f, 10.0f));
auto* runtimeOnlyEntity = m_context.GetSceneManager().CreateEntity("RuntimeOnly");
ASSERT_NE(runtimeOnlyEntity, nullptr);
const uint64_t runtimeOnlyId = runtimeOnlyEntity->GetID();
ASSERT_TRUE(m_controller.StopPlay(m_context));
EXPECT_EQ(m_context.GetRuntimeMode(), EditorRuntimeMode::Edit);
EXPECT_EQ(stoppedCount, 1);
auto* restoredEntity = m_context.GetSceneManager().GetEntity(editorEntityId);
ASSERT_NE(restoredEntity, nullptr);
EXPECT_EQ(m_context.GetSceneManager().GetEntity(runtimeOnlyId), nullptr);
const Math::Vector3 restoredPosition = restoredEntity->GetTransform()->GetLocalPosition();
EXPECT_NEAR(restoredPosition.x, 1.0f, 1e-4f);
EXPECT_NEAR(restoredPosition.y, 2.0f, 1e-4f);
EXPECT_NEAR(restoredPosition.z, 3.0f, 1e-4f);
m_context.GetEventBus().Unsubscribe<PlayModeStartedEvent>(startedSubscription);
m_context.GetEventBus().Unsubscribe<PlayModeStoppedEvent>(stoppedSubscription);
}
TEST_F(PlaySessionControllerTest, StartAndStopRequestsRouteThroughEventBus) {
auto* editorEntity = m_context.GetSceneManager().CreateEntity("Persistent");
ASSERT_NE(editorEntity, nullptr);
m_controller.Attach(m_context);
m_context.GetEventBus().Publish(PlayModeStartRequestedEvent{});
EXPECT_EQ(m_context.GetRuntimeMode(), EditorRuntimeMode::Play);
m_context.GetEventBus().Publish(PlayModeStopRequestedEvent{});
EXPECT_EQ(m_context.GetRuntimeMode(), EditorRuntimeMode::Edit);
m_controller.Detach(m_context);
}
} // namespace
} // namespace XCEngine::Editor