2026-02-21 06:00:02 +08:00
|
|
|
/**
|
|
|
|
|
* @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);
|
|
|
|
|
|
2026-02-21 12:33:40 +08:00
|
|
|
std::vector<Ref<TestScene>> scenes;
|
|
|
|
|
scenes.push_back(scene1);
|
|
|
|
|
|
2026-02-21 06:00:02 +08:00
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
|
auto newScene = ptr::make<TestScene>();
|
|
|
|
|
newScene->setName("Scene" + std::to_string(i + 2));
|
|
|
|
|
director.replace(newScene);
|
2026-02-21 12:33:40 +08:00
|
|
|
scenes.push_back(newScene);
|
2026-02-21 06:00:02 +08:00
|
|
|
}
|
|
|
|
|
|
2026-02-21 12:33:40 +08:00
|
|
|
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);
|
2026-02-21 06:00:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// 场景渲染测试
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
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());
|
|
|
|
|
}
|