437 lines
12 KiB
C++
437 lines
12 KiB
C++
/**
|
|
* @file test_win_adapt.cpp
|
|
* @brief Window Adaptation 单元测试
|
|
*
|
|
* 测试窗口适配模式、坐标转换、视口计算等功能。
|
|
*/
|
|
|
|
#include "test_framework.h"
|
|
#include <extra2d/win/win_adapt.h>
|
|
#include <extra2d/core/math_extended.h>
|
|
#include <glm/glm.hpp>
|
|
#include <cmath>
|
|
|
|
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;
|
|
}
|
|
|
|
bool rectEqual(const Rect& a, const Rect& b, f32 eps = EPSILON) {
|
|
return std::abs(a.origin.x - b.origin.x) < eps &&
|
|
std::abs(a.origin.y - b.origin.y) < eps &&
|
|
std::abs(a.size.width - b.size.width) < eps &&
|
|
std::abs(a.size.height - b.size.height) < eps;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// WinAdapt 基本测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, Create) {
|
|
WinAdapt adapt;
|
|
|
|
WinAdaptCfg cfg = adapt.cfg();
|
|
TEST_ASSERT_TRUE(cfg.mode == AdaptMode::Fit);
|
|
TEST_ASSERT_TRUE(std::abs(cfg.refW - 1280) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(cfg.refH - 720) < EPSILON);
|
|
}
|
|
|
|
TEST(WinAdapt, SetConfig) {
|
|
WinAdapt adapt;
|
|
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fill;
|
|
cfg.refW = 1920;
|
|
cfg.refH = 1080;
|
|
cfg.autoScale = false;
|
|
|
|
adapt.cfg(cfg);
|
|
|
|
WinAdaptCfg retrieved = adapt.cfg();
|
|
TEST_ASSERT_TRUE(retrieved.mode == AdaptMode::Fill);
|
|
TEST_ASSERT_TRUE(std::abs(retrieved.refW - 1920) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(retrieved.refH - 1080) < EPSILON);
|
|
TEST_ASSERT_FALSE(retrieved.autoScale);
|
|
}
|
|
|
|
TEST(WinAdapt, SetRef) {
|
|
WinAdapt adapt;
|
|
|
|
adapt.ref(800, 600);
|
|
|
|
Vec2 ref = adapt.ref();
|
|
TEST_ASSERT_TRUE(vec2Equal(ref, Vec2(800, 600)));
|
|
}
|
|
|
|
TEST(WinAdapt, SetWin) {
|
|
WinAdapt adapt;
|
|
adapt.ref(1280, 720);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Vec2 win = adapt.win();
|
|
TEST_ASSERT_TRUE(vec2Equal(win, Vec2(1920, 1080)));
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Exact 模式测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, ExactMode) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Exact;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Rect vp = adapt.viewport();
|
|
TEST_ASSERT_TRUE(rectEqual(vp, Rect(0, 0, 1920, 1080)));
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - 1.0f) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Stretch 模式测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, StretchMode) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Stretch;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Rect vp = adapt.viewport();
|
|
TEST_ASSERT_TRUE(rectEqual(vp, Rect(0, 0, 1920, 1080)));
|
|
|
|
Vec2 scale2D = adapt.scale2D();
|
|
TEST_ASSERT_TRUE(std::abs(scale2D.x - 1.5f) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(scale2D.y - 1.5f) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Fit 模式测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, FitModeSameAspect) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Rect vp = adapt.viewport();
|
|
TEST_ASSERT_TRUE(rectEqual(vp, Rect(0, 0, 1920, 1080)));
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - 1.5f) < EPSILON);
|
|
}
|
|
|
|
TEST(WinAdapt, FitModeWiderWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 800);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 expectedScale = 800.0f / 720.0f;
|
|
f32 expectedW = 1280.0f * expectedScale;
|
|
f32 expectedX = (1920.0f - expectedW) / 2.0f;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.x - expectedX) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.y) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.width - expectedW) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.height - 800) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - expectedScale) < EPSILON);
|
|
}
|
|
|
|
TEST(WinAdapt, FitModeTallerWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1280, 900);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 expectedScale = 1280.0f / 1280.0f;
|
|
f32 expectedH = 720.0f * expectedScale;
|
|
f32 expectedY = (900.0f - expectedH) / 2.0f;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.x) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.y - expectedY) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.width - 1280) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.height - expectedH) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Fill 模式测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, FillModeWiderWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fill;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 800);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 expectedScale = 1920.0f / 1280.0f;
|
|
f32 expectedH = 720.0f * expectedScale;
|
|
f32 expectedY = (800.0f - expectedH) / 2.0f;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.x) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.y - expectedY) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - expectedScale) < EPSILON);
|
|
}
|
|
|
|
TEST(WinAdapt, FillModeTallerWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fill;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1280, 900);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 expectedScale = 900.0f / 720.0f;
|
|
f32 expectedW = 1280.0f * expectedScale;
|
|
f32 expectedX = (1280.0f - expectedW) / 2.0f;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.x - expectedX) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.y) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - expectedScale) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Center 模式测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, CenterMode) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Center;
|
|
cfg.refW = 800;
|
|
cfg.refH = 600;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 expectedX = (1920.0f - 800.0f) / 2.0f;
|
|
f32 expectedY = (1080.0f - 600.0f) / 2.0f;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.x - expectedX) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.origin.y - expectedY) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.width - 800) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.height - 600) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(adapt.scale() - 1.0f) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 坐标转换测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, WinToRef) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Vec2 winPos(960, 540);
|
|
Vec2 refPos = adapt.winToRef(winPos);
|
|
|
|
TEST_ASSERT_TRUE(vec2Equal(refPos, Vec2(640, 360)));
|
|
}
|
|
|
|
TEST(WinAdapt, RefToWin) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Vec2 refPos(640, 360);
|
|
Vec2 winPos = adapt.refToWin(refPos);
|
|
|
|
TEST_ASSERT_TRUE(vec2Equal(winPos, Vec2(960, 540)));
|
|
}
|
|
|
|
TEST(WinAdapt, WinToRefRoundTrip) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1600, 900);
|
|
|
|
Vec2 originalRef(500, 300);
|
|
Vec2 win = adapt.refToWin(originalRef);
|
|
Vec2 backToRef = adapt.winToRef(win);
|
|
|
|
TEST_ASSERT_TRUE(vec2Equal(originalRef, backToRef, 0.1f));
|
|
}
|
|
|
|
TEST(WinAdapt, ScreenToRef) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Vec2 screenPos(960, 540);
|
|
Vec2 refPos = adapt.screenToRef(screenPos);
|
|
|
|
TEST_ASSERT_TRUE(vec2Equal(refPos, Vec2(640, 360)));
|
|
}
|
|
|
|
TEST(WinAdapt, RefToScreen) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Vec2 refPos(640, 360);
|
|
Vec2 screenPos = adapt.refToScreen(refPos);
|
|
|
|
TEST_ASSERT_TRUE(vec2Equal(screenPos, Vec2(960, 540)));
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 矩阵测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, Matrix) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(1920, 1080);
|
|
|
|
Mat4 m = adapt.matrix();
|
|
|
|
Vec4 origin(0, 0, 0, 1);
|
|
Vec4 transformed = m * origin;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(transformed.x) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(transformed.y) < EPSILON);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 边界情况测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, ZeroWindowSize) {
|
|
WinAdapt adapt;
|
|
adapt.ref(1280, 720);
|
|
|
|
adapt.win(0, 0);
|
|
|
|
Rect vp = adapt.viewport();
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.width) < EPSILON);
|
|
TEST_ASSERT_TRUE(std::abs(vp.size.height) < EPSILON);
|
|
}
|
|
|
|
TEST(WinAdapt, VerySmallWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(100, 100);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
TEST_ASSERT_TRUE(vp.size.width > 0);
|
|
TEST_ASSERT_TRUE(vp.size.height > 0);
|
|
TEST_ASSERT_TRUE(adapt.scale() > 0);
|
|
}
|
|
|
|
TEST(WinAdapt, VeryLargeWindow) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(7680, 4320);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
TEST_ASSERT_TRUE(vp.size.width > 0);
|
|
TEST_ASSERT_TRUE(vp.size.height > 0);
|
|
TEST_ASSERT_TRUE(adapt.scale() > 1.0f);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 不同宽高比测试
|
|
// ---------------------------------------------------------------------------
|
|
|
|
TEST(WinAdapt, AspectRatioPreservation) {
|
|
WinAdapt adapt;
|
|
WinAdaptCfg cfg;
|
|
cfg.mode = AdaptMode::Fit;
|
|
cfg.refW = 1280;
|
|
cfg.refH = 720;
|
|
adapt.cfg(cfg);
|
|
|
|
adapt.win(2560, 1440);
|
|
|
|
Rect vp = adapt.viewport();
|
|
|
|
f32 refAspect = 1280.0f / 720.0f;
|
|
f32 vpAspect = vp.size.width / vp.size.height;
|
|
|
|
TEST_ASSERT_TRUE(std::abs(refAspect - vpAspect) < EPSILON);
|
|
}
|