Extra2D/Tests/test_scene.cpp

340 lines
8.6 KiB
C++

/**
* @file test_scene.cpp
* @brief Scene 管理单元测试
*
* 测试场景的生命周期、Director 场景管理、场景转换等功能。
*/
#include "test_framework.h"
#include <extra2d/scene/scene.h>
#include <extra2d/scene/director.h>
#include <extra2d/scene/trans.h>
#include <extra2d/node/node.h>
#include <extra2d/cam/ortho_cam.h>
#include <extra2d/act/act_move.h>
#include <extra2d/core/math_extended.h>
using namespace extra2d;
using namespace extra2d::test;
namespace {
constexpr f32 EPSILON = 0.001f;
bool vec2Equal(const Vec2& a, const Vec2& b, f32 eps = EPSILON) {
return std::abs(a.x - b.x) < eps && std::abs(a.y - b.y) < eps;
}
}
// ---------------------------------------------------------------------------
// Scene 基本测试
// ---------------------------------------------------------------------------
class TestScene : public Scene {
public:
TestScene() {
setName("TestScene");
}
void onEnter() override { enterCount++; }
void onExit() override { exitCount++; }
void onPause() override { pauseCount++; }
void onResume() override { resumeCount++; }
int enterCount = 0;
int exitCount = 0;
int pauseCount = 0;
int resumeCount = 0;
};
TEST(Scene, Create) {
auto scene = ptr::make<TestScene>();
TEST_ASSERT_EQ("TestScene", scene->name());
TEST_ASSERT_FALSE(scene->running());
TEST_ASSERT_NOT_NULL(scene->graph());
TEST_ASSERT_NOT_NULL(scene->cam());
}
TEST(Scene, SetName) {
auto scene = ptr::make<TestScene>();
scene->setName("MyScene");
TEST_ASSERT_EQ("MyScene", scene->name());
}
TEST(Scene, SetRunning) {
auto scene = ptr::make<TestScene>();
scene->setRunning(true);
TEST_ASSERT_TRUE(scene->running());
scene->setRunning(false);
TEST_ASSERT_FALSE(scene->running());
}
TEST(Scene, LifecycleCallbacks) {
auto scene = ptr::make<TestScene>();
scene->onEnter();
TEST_ASSERT_EQ(1, scene->enterCount);
scene->onExit();
TEST_ASSERT_EQ(1, scene->exitCount);
scene->onPause();
TEST_ASSERT_EQ(1, scene->pauseCount);
scene->onResume();
TEST_ASSERT_EQ(1, scene->resumeCount);
}
TEST(Scene, Update) {
auto scene = ptr::make<TestScene>();
auto node = scene->graph()->create<Node>();
node->setName("TestNode");
scene->update(0.016f);
Node* found = scene->graph()->find("TestNode");
TEST_ASSERT_NOT_NULL(found);
}
// ---------------------------------------------------------------------------
// Director 基本测试
// ---------------------------------------------------------------------------
TEST(Director, Create) {
Director director;
TEST_ASSERT_NULL(director.cur());
}
TEST(Director, RunScene) {
Director director;
auto scene = ptr::make<TestScene>();
director.run(scene);
TEST_ASSERT_EQ(scene.get(), director.cur());
TEST_ASSERT_TRUE(scene->running());
TEST_ASSERT_EQ(1, scene->enterCount);
}
TEST(Director, ReplaceScene) {
Director director;
auto scene1 = ptr::make<TestScene>();
scene1->setName("Scene1");
director.run(scene1);
auto scene2 = ptr::make<TestScene>();
scene2->setName("Scene2");
director.replace(scene2);
TEST_ASSERT_EQ(scene2.get(), director.cur());
TEST_ASSERT_EQ(1, scene1->exitCount);
TEST_ASSERT_EQ(1, scene2->enterCount);
}
TEST(Director, PushPopScene) {
Director director;
auto scene1 = ptr::make<TestScene>();
scene1->setName("Scene1");
director.run(scene1);
auto scene2 = ptr::make<TestScene>();
scene2->setName("Scene2");
director.push(scene2);
TEST_ASSERT_EQ(scene2.get(), director.cur());
TEST_ASSERT_EQ(1, scene1->pauseCount);
TEST_ASSERT_EQ(1, scene2->enterCount);
director.pop();
TEST_ASSERT_EQ(scene1.get(), director.cur());
TEST_ASSERT_EQ(1, scene2->exitCount);
TEST_ASSERT_EQ(1, scene1->resumeCount);
}
TEST(Director, Update) {
Director director;
auto scene = ptr::make<TestScene>();
director.run(scene);
auto node = scene->graph()->create<Node>();
node->setPos(0, 0);
node->run(new MoveTo(1.0f, Vec2(100, 0)));
director.update(0.5f);
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(50, 0)));
}
TEST(Director, SceneStack) {
Director director;
auto scene1 = ptr::make<TestScene>();
scene1->setName("Scene1");
director.run(scene1);
auto scene2 = ptr::make<TestScene>();
scene2->setName("Scene2");
director.push(scene2);
auto scene3 = ptr::make<TestScene>();
scene3->setName("Scene3");
director.push(scene3);
TEST_ASSERT_EQ(scene3.get(), director.cur());
director.pop();
TEST_ASSERT_EQ(scene2.get(), director.cur());
director.pop();
TEST_ASSERT_EQ(scene1.get(), director.cur());
director.pop();
TEST_ASSERT_NULL(director.cur());
}
// ---------------------------------------------------------------------------
// Trans 场景转换测试
// ---------------------------------------------------------------------------
TEST(TransFade, Create) {
auto scene1 = ptr::make<TestScene>();
auto scene2 = ptr::make<TestScene>();
TransFade trans;
trans.init(1.0f, scene1, scene2);
TEST_ASSERT_TRUE(std::abs(trans.duration() - 1.0f) < EPSILON);
}
TEST(TransFade, Progress) {
auto scene1 = ptr::make<TestScene>();
auto scene2 = ptr::make<TestScene>();
TransFade trans;
trans.init(2.0f, scene1, scene2);
trans.update(1.0f);
TEST_ASSERT_TRUE(std::abs(trans.progress() - 0.5f) < EPSILON);
}
// ---------------------------------------------------------------------------
// 场景图集成测试
// ---------------------------------------------------------------------------
TEST(Scene, GraphIntegration) {
auto scene = ptr::make<TestScene>();
auto parent = scene->graph()->create<Node>();
parent->setName("Parent");
parent->setPos(100, 100);
auto child = ptr::make<Node>();
child->setName("Child");
child->setPos(50, 50);
parent->addChild(child);
Vec2 worldPos = child->worldPos();
TEST_ASSERT_TRUE(vec2Equal(worldPos, Vec2(150, 150)));
}
TEST(Scene, CameraIntegration) {
auto scene = ptr::make<TestScene>();
auto cam = dynamic_cast<OrthoCam*>(scene->cam());
TEST_ASSERT_NOT_NULL(cam);
cam->setOrthoFromSize(1280, 720);
cam->setPosition(Vec2(0, 0));
}
// ---------------------------------------------------------------------------
// 多场景测试
// ---------------------------------------------------------------------------
TEST(Director, MultipleSceneSwitches) {
Director director;
auto scene1 = ptr::make<TestScene>();
scene1->setName("Scene1");
director.run(scene1);
std::vector<Ref<TestScene>> scenes;
scenes.push_back(scene1);
for (int i = 0; i < 5; ++i) {
auto newScene = ptr::make<TestScene>();
newScene->setName("Scene" + std::to_string(i + 2));
director.replace(newScene);
scenes.push_back(newScene);
}
TEST_ASSERT_EQ(1, scenes[0]->exitCount);
TEST_ASSERT_EQ(1, scenes[1]->exitCount);
TEST_ASSERT_EQ(1, scenes[2]->exitCount);
TEST_ASSERT_EQ(1, scenes[3]->exitCount);
TEST_ASSERT_EQ(1, scenes[4]->exitCount);
TEST_ASSERT_EQ(0, scenes[5]->exitCount);
}
// ---------------------------------------------------------------------------
// 场景渲染测试
// ---------------------------------------------------------------------------
class RenderTestScene : public Scene {
public:
RenderTestScene() { setName("RenderTestScene"); }
void render(RenderCmdBuffer& cmdBuffer) override {
renderCalled = true;
}
bool renderCalled = false;
};
TEST(Scene, RenderCallback) {
auto scene = ptr::make<RenderTestScene>();
RenderCmdBuffer cmdBuffer;
scene->render(cmdBuffer);
TEST_ASSERT_TRUE(scene->renderCalled);
}
// ---------------------------------------------------------------------------
// 边界情况测试
// ---------------------------------------------------------------------------
TEST(Director, ReplaceWhenNoRunning) {
Director director;
auto scene = ptr::make<TestScene>();
director.replace(scene);
TEST_ASSERT_EQ(scene.get(), director.cur());
}
TEST(Director, PopWhenEmpty) {
Director director;
director.pop();
TEST_ASSERT_NULL(director.cur());
}
TEST(Director, PushWhenNoRunning) {
Director director;
auto scene = ptr::make<TestScene>();
director.push(scene);
TEST_ASSERT_EQ(scene.get(), director.cur());
}