refactor(渲染系统): 重命名 RenderBackend 为 Renderer 并统一相关接口命名

将渲染后端基类从 RenderBackend 重命名为 Renderer,使其更简洁直观
更新所有相关派生类和接口引用,保持命名一致性
修改渲染器相关方法参数类型为 Renderer&
调整部分成员函数命名风格,如 getWidth()/getHeight() 改为 width()/height()
更新文档和注释中的渲染后端相关描述
This commit is contained in:
ChestnutYueyue 2026-02-26 00:59:16 +08:00
parent bd3cebf0b5
commit 7b1e1299e0
68 changed files with 555 additions and 521 deletions

View File

@ -114,7 +114,7 @@ mindmap
触摸 Touch 触摸 Touch
输入码 InputCodes 输入码 InputCodes
渲染系统 渲染系统
渲染后端 RenderBackend 渲染后端 Renderer
OpenGL 实现 OpenGL 实现
GLRenderer GLRenderer
GLShader GLShader

View File

@ -23,7 +23,7 @@ public:
height_); height_);
} }
void onRender(RenderBackend &renderer) override { void onRender(Renderer &renderer) override {
Vec2 position = pos(); Vec2 position = pos();
// 绘制填充矩形 // 绘制填充矩形

View File

@ -21,8 +21,8 @@ void BaseScene::onEnter() {
void BaseScene::updateViewport() { void BaseScene::updateViewport() {
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float windowWidth = static_cast<float>(app.window().getWidth()); float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().getHeight()); float windowHeight = static_cast<float>(app.window().height());
// 计算游戏内容在窗口中的居中位置 // 计算游戏内容在窗口中的居中位置
// 保持游戏原始宽高比,进行"黑边"适配 // 保持游戏原始宽高比,进行"黑边"适配
@ -48,11 +48,11 @@ void BaseScene::updateViewport() {
setCamera(camera); setCamera(camera);
} }
void BaseScene::onRender(extra2d::RenderBackend &renderer) { void BaseScene::onRender(extra2d::Renderer &renderer) {
// 检查窗口大小是否改变,如果改变则更新视口 // 检查窗口大小是否改变,如果改变则更新视口
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float currentWindowWidth = static_cast<float>(app.window().getWidth()); float currentWindowWidth = static_cast<float>(app.window().width());
float currentWindowHeight = static_cast<float>(app.window().getHeight()); float currentWindowHeight = static_cast<float>(app.window().height());
// 如果窗口大小改变,重新计算视口 // 如果窗口大小改变,重新计算视口
float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f; float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f;
@ -75,7 +75,7 @@ void BaseScene::onRender(extra2d::RenderBackend &renderer) {
extra2d::Scene::onRender(renderer); extra2d::Scene::onRender(renderer);
} }
void BaseScene::renderContent(extra2d::RenderBackend &renderer) { void BaseScene::renderContent(extra2d::Renderer &renderer) {
// 如果视口参数未初始化onEnter 还没被调用),先初始化 // 如果视口参数未初始化onEnter 还没被调用),先初始化
if (scaledGameWidth_ <= 0.0f || scaledGameHeight_ <= 0.0f) { if (scaledGameWidth_ <= 0.0f || scaledGameHeight_ <= 0.0f) {
updateViewport(); updateViewport();
@ -83,8 +83,8 @@ void BaseScene::renderContent(extra2d::RenderBackend &renderer) {
// 检查窗口大小是否改变 // 检查窗口大小是否改变
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float currentWindowWidth = static_cast<float>(app.window().getWidth()); float currentWindowWidth = static_cast<float>(app.window().width());
float currentWindowHeight = static_cast<float>(app.window().getHeight()); float currentWindowHeight = static_cast<float>(app.window().height());
float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f; float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f;
float expectedHeight = scaledGameHeight_ + viewportOffsetY_ * 2.0f; float expectedHeight = scaledGameHeight_ + viewportOffsetY_ * 2.0f;

View File

@ -33,13 +33,13 @@ public:
* @brief * @brief
* @param renderer * @param renderer
*/ */
void onRender(extra2d::RenderBackend &renderer) override; void onRender(extra2d::Renderer &renderer) override;
/** /**
* @brief * @brief
* @param renderer * @param renderer
*/ */
void renderContent(extra2d::RenderBackend &renderer) override; void renderContent(extra2d::Renderer &renderer) override;
protected: protected:
/** /**

View File

@ -73,8 +73,8 @@ ResLoader::getKeyFrame(const std::string &name) {
// 检查纹理尺寸 // 检查纹理尺寸
if (atlasTexture_) { if (atlasTexture_) {
E2D_LOG_INFO("图集纹理尺寸: {}x{}", atlasTexture_->getWidth(), E2D_LOG_INFO("图集纹理尺寸: {}x{}", atlasTexture_->width(),
atlasTexture_->getHeight()); atlasTexture_->height());
} }
return extra2d::makePtr<extra2d::SpriteFrame>( return extra2d::makePtr<extra2d::SpriteFrame>(

View File

@ -89,7 +89,7 @@ void Bird::onUpdate(float dt) {
} }
} }
void Bird::onRender(extra2d::RenderBackend &renderer) { void Bird::onRender(extra2d::Renderer &renderer) {
// 精灵会自动渲染,这里只需要处理旋转和偏移 // 精灵会自动渲染,这里只需要处理旋转和偏移
if (sprite_) { if (sprite_) {
sprite_->setRotation(rotation_); sprite_->setRotation(rotation_);

View File

@ -45,7 +45,7 @@ public:
* @brief * @brief
* @param renderer * @param renderer
*/ */
void onRender(extra2d::RenderBackend &renderer) override; void onRender(extra2d::Renderer &renderer) override;
/** /**
* @brief * @brief

View File

@ -3,75 +3,77 @@
// ============================================================================ // ============================================================================
#include "Ground.h" #include "Ground.h"
#include "ResLoader.h"
#include "BaseScene.h" #include "BaseScene.h"
#include "ResLoader.h"
namespace flappybird { namespace flappybird {
Ground::Ground() { Ground::Ground() {
moving_ = true; moving_ = true;
// 使用游戏逻辑高度,而不是窗口高度 // 使用游戏逻辑高度,而不是窗口高度
float screenHeight = GAME_HEIGHT; float screenHeight = GAME_HEIGHT;
// 获取地面纹理帧 // 获取地面纹理帧
auto landFrame = ResLoader::getKeyFrame("land"); auto landFrame = ResLoader::getKeyFrame("land");
if (!landFrame) return; if (!landFrame)
return;
// 获取地面纹理和矩形 // 获取地面纹理和矩形
auto texture = landFrame->getTexture(); auto texture = landFrame->getTexture();
auto rect = landFrame->getRect(); auto rect = landFrame->getRect();
float groundWidth = rect.size.width; float groundWidth = rect.size.width;
float groundHeight = rect.size.height; float groundHeight = rect.size.height;
// 创建第一块地面 // 创建第一块地面
ground1_ = extra2d::Sprite::create(texture, rect); ground1_ = extra2d::Sprite::create(texture, rect);
ground1_->setAnchor(extra2d::Vec2(0.0f, 1.0f)); // 锚点设在左下角 ground1_->setAnchor(extra2d::Vec2(0.0f, 1.0f)); // 锚点设在左下角
ground1_->setPosition(extra2d::Vec2(0.0f, screenHeight)); ground1_->setPosition(extra2d::Vec2(0.0f, screenHeight));
addChild(ground1_); addChild(ground1_);
// 创建第二块地面,紧挨在第一块右边 // 创建第二块地面,紧挨在第一块右边
ground2_ = extra2d::Sprite::create(texture, rect); ground2_ = extra2d::Sprite::create(texture, rect);
ground2_->setAnchor(extra2d::Vec2(0.0f, 1.0f)); ground2_->setAnchor(extra2d::Vec2(0.0f, 1.0f));
ground2_->setPosition(extra2d::Vec2(groundWidth - 1.0f, screenHeight)); ground2_->setPosition(extra2d::Vec2(groundWidth - 1.0f, screenHeight));
addChild(ground2_); addChild(ground2_);
} }
void Ground::onUpdate(float dt) { void Ground::onUpdate(float dt) {
extra2d::Node::onUpdate(dt); extra2d::Node::onUpdate(dt);
if (!moving_) return; if (!moving_)
if (!ground1_ || !ground2_) return; return;
if (!ground1_ || !ground2_)
return;
// 获取地面宽度(从纹理矩形获取) // 获取地面宽度(从纹理矩形获取)
float groundWidth = ground1_->getTextureRect().size.width; float groundWidth = ground1_->getTextureRect().size.width;
// 移动两块地面 // 移动两块地面
extra2d::Vec2 pos1 = ground1_->pos(); extra2d::Vec2 pos1 = ground1_->pos();
extra2d::Vec2 pos2 = ground2_->pos(); extra2d::Vec2 pos2 = ground2_->pos();
pos1.x -= speed * dt; pos1.x -= speed * dt;
pos2.x -= speed * dt; pos2.x -= speed * dt;
// 当地面完全移出屏幕左侧时,重置到右侧 // 当地面完全移出屏幕左侧时,重置到右侧
if (pos1.x <= -groundWidth) { if (pos1.x <= -groundWidth) {
pos1.x = pos2.x + groundWidth - 1.0f; pos1.x = pos2.x + groundWidth - 1.0f;
} }
if (pos2.x <= -groundWidth) { if (pos2.x <= -groundWidth) {
pos2.x = pos1.x + groundWidth - 1.0f; pos2.x = pos1.x + groundWidth - 1.0f;
} }
ground1_->setPosition(pos1); ground1_->setPosition(pos1);
ground2_->setPosition(pos2); ground2_->setPosition(pos2);
} }
void Ground::stop() { void Ground::stop() { moving_ = false; }
moving_ = false;
}
float Ground::getHeight() const { float Ground::height() const {
auto landFrame = ResLoader::getKeyFrame("land"); auto landFrame = ResLoader::getKeyFrame("land");
return landFrame ? landFrame->getRect().size.height : 112.0f; return landFrame ? landFrame->getRect().size.height : 112.0f;
} }
} // namespace flappybird } // namespace flappybird

View File

@ -15,34 +15,34 @@ namespace flappybird {
*/ */
class Ground : public extra2d::Node { class Ground : public extra2d::Node {
public: public:
/** /**
* @brief * @brief
*/ */
Ground(); Ground();
/** /**
* @brief * @brief
* @param dt * @param dt
*/ */
void onUpdate(float dt) override; void onUpdate(float dt) override;
/** /**
* @brief * @brief
*/ */
void stop(); void stop();
/** /**
* @brief * @brief
* @return * @return
*/ */
float getHeight() const; float height() const;
private: private:
extra2d::Ptr<extra2d::Sprite> ground1_; // 第一块地面 extra2d::Ptr<extra2d::Sprite> ground1_; // 第一块地面
extra2d::Ptr<extra2d::Sprite> ground2_; // 第二块地面 extra2d::Ptr<extra2d::Sprite> ground2_; // 第二块地面
static constexpr float speed = 120.0f; // 滚动速度(像素/秒) static constexpr float speed = 120.0f; // 滚动速度(像素/秒)
bool moving_ = true; // 是否正在滚动 bool moving_ = true; // 是否正在滚动
}; };
} // namespace flappybird } // namespace flappybird

View File

@ -24,8 +24,8 @@ void BaseScene::onEnter() {
*/ */
void BaseScene::updateViewport() { void BaseScene::updateViewport() {
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float windowWidth = static_cast<float>(app.window().getWidth()); float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().getHeight()); float windowHeight = static_cast<float>(app.window().height());
// 计算游戏内容在窗口中的居中位置 // 计算游戏内容在窗口中的居中位置
// 保持游戏原始宽高比,进行"黑边"适配 // 保持游戏原始宽高比,进行"黑边"适配
@ -55,11 +55,11 @@ void BaseScene::updateViewport() {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void BaseScene::onRender(extra2d::RenderBackend &renderer) { void BaseScene::onRender(extra2d::Renderer &renderer) {
// 检查窗口大小是否改变,如果改变则更新视口 // 检查窗口大小是否改变,如果改变则更新视口
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float currentWindowWidth = static_cast<float>(app.window().getWidth()); float currentWindowWidth = static_cast<float>(app.window().width());
float currentWindowHeight = static_cast<float>(app.window().getHeight()); float currentWindowHeight = static_cast<float>(app.window().height());
// 如果窗口大小改变,重新计算视口 // 如果窗口大小改变,重新计算视口
float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f; float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f;
@ -86,7 +86,7 @@ void BaseScene::onRender(extra2d::RenderBackend &renderer) {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void BaseScene::renderContent(extra2d::RenderBackend &renderer) { void BaseScene::renderContent(extra2d::Renderer &renderer) {
// 如果视口参数未初始化onEnter 还没被调用),先初始化 // 如果视口参数未初始化onEnter 还没被调用),先初始化
if (scaledGameWidth_ <= 0.0f || scaledGameHeight_ <= 0.0f) { if (scaledGameWidth_ <= 0.0f || scaledGameHeight_ <= 0.0f) {
updateViewport(); updateViewport();
@ -94,8 +94,8 @@ void BaseScene::renderContent(extra2d::RenderBackend &renderer) {
// 检查窗口大小是否改变 // 检查窗口大小是否改变
auto &app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
float currentWindowWidth = static_cast<float>(app.window().getWidth()); float currentWindowWidth = static_cast<float>(app.window().width());
float currentWindowHeight = static_cast<float>(app.window().getHeight()); float currentWindowHeight = static_cast<float>(app.window().height());
float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f; float expectedWidth = scaledGameWidth_ + viewportOffsetX_ * 2.0f;
float expectedHeight = scaledGameHeight_ + viewportOffsetY_ * 2.0f; float expectedHeight = scaledGameHeight_ + viewportOffsetY_ * 2.0f;

View File

@ -19,39 +19,39 @@ static constexpr float GAME_HEIGHT = 480.0f;
*/ */
class BaseScene : public extra2d::Scene { class BaseScene : public extra2d::Scene {
public: public:
/** /**
* @brief * @brief
*/ */
BaseScene(); BaseScene();
/** /**
* @brief * @brief
*/ */
void onEnter() override; void onEnter() override;
/** /**
* @brief * @brief
* @param renderer * @param renderer
*/ */
void onRender(extra2d::RenderBackend &renderer) override; void onRender(extra2d::Renderer &renderer) override;
/** /**
* @brief * @brief
* @param renderer * @param renderer
*/ */
void renderContent(extra2d::RenderBackend &renderer) override; void renderContent(extra2d::Renderer &renderer) override;
protected: protected:
/** /**
* @brief 使 * @brief 使
*/ */
void updateViewport(); void updateViewport();
// 视口适配参数(用于在窗口中居中显示游戏内容) // 视口适配参数(用于在窗口中居中显示游戏内容)
float scaledGameWidth_ = 0.0f; // 缩放后的游戏宽度 float scaledGameWidth_ = 0.0f; // 缩放后的游戏宽度
float scaledGameHeight_ = 0.0f; // 缩放后的游戏高度 float scaledGameHeight_ = 0.0f; // 缩放后的游戏高度
float viewportOffsetX_ = 0.0f; // 视口水平偏移 float viewportOffsetX_ = 0.0f; // 视口水平偏移
float viewportOffsetY_ = 0.0f; // 视口垂直偏移 float viewportOffsetY_ = 0.0f; // 视口垂直偏移
}; };
} // namespace pushbox } // namespace pushbox

View File

@ -238,8 +238,8 @@ void PlayScene::executeMenuItem() {
void PlayScene::flush() { void PlayScene::flush() {
mapLayer_->removeAllChildren(); mapLayer_->removeAllChildren();
int tileW = texFloor_ ? texFloor_->getWidth() : 32; int tileW = texFloor_ ? texFloor_->width() : 32;
int tileH = texFloor_ ? texFloor_->getHeight() : 32; int tileH = texFloor_ ? texFloor_->height() : 32;
// 使用游戏逻辑分辨率 // 使用游戏逻辑分辨率
float gameWidth = GAME_WIDTH; float gameWidth = GAME_WIDTH;
@ -298,7 +298,7 @@ void PlayScene::flush() {
void PlayScene::setLevel(int level) { void PlayScene::setLevel(int level) {
g_CurrentLevel = level; g_CurrentLevel = level;
saveCurrentLevel(g_CurrentLevel); saveCurrentLevel(g_CurrentLevel);
// 清空移动历史(智能指针自动回收到对象池) // 清空移动历史(智能指针自动回收到对象池)
while (!moveHistory_.empty()) { while (!moveHistory_.empty()) {
moveHistory_.pop(); moveHistory_.pop();
@ -368,7 +368,8 @@ void PlayScene::move(int dx, int dy, int direct) {
} }
// 使用对象池创建移动记录(自动管理内存) // 使用对象池创建移动记录(自动管理内存)
auto record = E2D_MAKE_POOLED(MoveRecord, map_.roleX, map_.roleY, targetX, targetY, false); auto record = E2D_MAKE_POOLED(MoveRecord, map_.roleX, map_.roleY, targetX,
targetY, false);
if (map_.value[targetY][targetX].type == TYPE::Ground) { if (map_.value[targetY][targetX].type == TYPE::Ground) {
g_Pushing = false; g_Pushing = false;
@ -480,7 +481,7 @@ void PlayScene::undoMove() {
// record 智能指针离开作用域后自动回收到对象池 // record 智能指针离开作用域后自动回收到对象池
setStep(step_ - 1); setStep(step_ - 1);
flush(); flush();
E2D_LOG_INFO("Undo move, step: {}", step_); E2D_LOG_INFO("Undo move, step: {}", step_);
} }

View File

@ -38,8 +38,8 @@ void StartScene::onEnter() {
auto bgTex = resources.loadTexture("assets/images/start.jpg"); auto bgTex = resources.loadTexture("assets/images/start.jpg");
if (bgTex) { if (bgTex) {
auto background = extra2d::Sprite::create(bgTex); auto background = extra2d::Sprite::create(bgTex);
float bgWidth = static_cast<float>(bgTex->getWidth()); float bgWidth = static_cast<float>(bgTex->width());
float bgHeight = static_cast<float>(bgTex->getHeight()); float bgHeight = static_cast<float>(bgTex->height());
float offsetX = (screenW - bgWidth) / 2.0f; float offsetX = (screenW - bgWidth) / 2.0f;
float offsetY = (screenH - bgHeight) / 2.0f; float offsetY = (screenH - bgHeight) / 2.0f;

View File

@ -9,73 +9,73 @@
namespace pushbox { namespace pushbox {
SuccessScene::SuccessScene() : BaseScene() { SuccessScene::SuccessScene() : BaseScene() {
// BaseScene 已处理视口设置 // BaseScene 已处理视口设置
} }
/** /**
* @brief * @brief
*/ */
static extra2d::Ptr<extra2d::FontAtlas> loadMenuFont() { static extra2d::Ptr<extra2d::FontAtlas> loadMenuFont() {
auto& resources = extra2d::Application::instance().resources(); auto &resources = extra2d::Application::instance().resources();
auto font = resources.loadFont("assets/font.ttf", 28); auto font = resources.loadFont("assets/font.ttf", 28);
return font; return font;
} }
void SuccessScene::onEnter() { void SuccessScene::onEnter() {
BaseScene::onEnter(); BaseScene::onEnter();
auto& app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
auto& resources = app.resources(); auto &resources = app.resources();
if (children().empty()) { if (children().empty()) {
// 使用游戏逻辑分辨率 // 使用游戏逻辑分辨率
float screenW = GAME_WIDTH; float screenW = GAME_WIDTH;
float screenH = GAME_HEIGHT; float screenH = GAME_HEIGHT;
auto bgTex = resources.loadTexture("assets/images/success.jpg"); auto bgTex = resources.loadTexture("assets/images/success.jpg");
if (bgTex) { if (bgTex) {
auto background = extra2d::Sprite::create(bgTex); auto background = extra2d::Sprite::create(bgTex);
float bgWidth = static_cast<float>(bgTex->getWidth()); float bgWidth = static_cast<float>(bgTex->width());
float bgHeight = static_cast<float>(bgTex->getHeight()); float bgHeight = static_cast<float>(bgTex->height());
float offsetX = (screenW - bgWidth) / 2.0f; float offsetX = (screenW - bgWidth) / 2.0f;
float offsetY = (screenH - bgHeight) / 2.0f; float offsetY = (screenH - bgHeight) / 2.0f;
background->setAnchor(0.0f, 0.0f);
background->setPosition(offsetX, offsetY);
addChild(background);
float centerX = screenW / 2.0f;
auto font = loadMenuFont();
if (font) {
// 创建按钮文本(仅显示,不响应鼠标)
auto backText = extra2d::Text::create("回主菜单", font);
backText->setPosition(centerX, offsetY + 350.0f);
backText->setTextColor(extra2d::Colors::Black);
addChild(backText);
// 创建选择指示器(箭头) background->setAnchor(0.0f, 0.0f);
selectorText_ = extra2d::Text::create(">", font); background->setPosition(offsetX, offsetY);
selectorText_->setTextColor(extra2d::Colors::Red); addChild(background);
selectorText_->setPosition(centerX - 80.0f, offsetY + 350.0f);
addChild(selectorText_); float centerX = screenW / 2.0f;
}
} auto font = loadMenuFont();
if (font) {
// 创建按钮文本(仅显示,不响应鼠标)
auto backText = extra2d::Text::create("回主菜单", font);
backText->setPosition(centerX, offsetY + 350.0f);
backText->setTextColor(extra2d::Colors::Black);
addChild(backText);
// 创建选择指示器(箭头)
selectorText_ = extra2d::Text::create(">", font);
selectorText_->setTextColor(extra2d::Colors::Red);
selectorText_->setPosition(centerX - 80.0f, offsetY + 350.0f);
addChild(selectorText_);
}
} }
}
} }
void SuccessScene::onUpdate(float dt) { void SuccessScene::onUpdate(float dt) {
BaseScene::onUpdate(dt); BaseScene::onUpdate(dt);
auto& app = extra2d::Application::instance(); auto &app = extra2d::Application::instance();
auto& input = app.input(); auto &input = app.input();
// A键确认返回主菜单 // A键确认返回主菜单
if (input.isButtonPressed(extra2d::GamepadButton::A)) { if (input.isButtonPressed(extra2d::GamepadButton::A)) {
auto& scenes = extra2d::Application::instance().scenes(); auto &scenes = extra2d::Application::instance().scenes();
scenes.popScene(extra2d::TransitionType::Fade, 0.5f); scenes.popScene(extra2d::TransitionType::Fade, 0.5f);
scenes.popScene(extra2d::TransitionType::Fade, 0.5f); scenes.popScene(extra2d::TransitionType::Fade, 0.5f);
} }
} }
} // namespace pushbox } // namespace pushbox

View File

@ -60,7 +60,7 @@ public:
setPosition(position); setPosition(position);
} }
void onRender(RenderBackend &renderer) override { void onRender(Renderer &renderer) override {
Vec2 position = pos(); Vec2 position = pos();
// 碰撞时变红色 // 碰撞时变红色
@ -175,7 +175,7 @@ public:
} }
} }
void onRender(RenderBackend &renderer) override { void onRender(Renderer &renderer) override {
auto renderStart = std::chrono::high_resolution_clock::now(); auto renderStart = std::chrono::high_resolution_clock::now();
Scene::onRender(renderer); Scene::onRender(renderer);
@ -460,7 +460,7 @@ private:
/** /**
* @brief * @brief
*/ */
void drawLegend(RenderBackend &renderer) { void drawLegend(Renderer &renderer) {
float legendX = screenWidth_ - 200.0f; float legendX = screenWidth_ - 200.0f;
float legendY = 20.0f + 25.0f; // 在标题下方 float legendY = 20.0f + 25.0f; // 在标题下方

View File

@ -2,11 +2,11 @@
#include <animation/sprite_frame.h> #include <animation/sprite_frame.h>
#include <graphics/texture.h> #include <graphics/texture.h>
#include <resource/resource_manager.h>
#include <utils/logger.h>
#include <mutex> #include <mutex>
#include <resource/resource_manager.h>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <utils/logger.h>
namespace extra2d { namespace extra2d {
@ -56,8 +56,8 @@ public:
if (!texture) if (!texture)
return; return;
int texW = texture->getWidth(); int texW = texture->width();
int texH = texture->getHeight(); int texH = texture->height();
int usableW = texW - 2 * margin; int usableW = texW - 2 * margin;
int usableH = texH - 2 * margin; int usableH = texH - 2 * margin;
int cols = (usableW + spacing) / (frameWidth + spacing); int cols = (usableW + spacing) / (frameWidth + spacing);
@ -112,8 +112,8 @@ public:
return nullptr; return nullptr;
// 默认整张纹理作为一帧index=0或用整张纹理 // 默认整张纹理作为一帧index=0或用整张纹理
Rect rect(0.0f, 0.0f, static_cast<float>(texture->getWidth()), Rect rect(0.0f, 0.0f, static_cast<float>(texture->width()),
static_cast<float>(texture->getHeight())); static_cast<float>(texture->height()));
auto frame = SpriteFrame::create(texture, rect); auto frame = SpriteFrame::create(texture, rect);
frame->setName(key); frame->setName(key);
@ -172,21 +172,21 @@ private:
// 使用 ResourceManager 的纹理缓存机制 // 使用 ResourceManager 的纹理缓存机制
// 这样可以享受 LRU 缓存、自动清理和缓存统计等功能 // 这样可以享受 LRU 缓存、自动清理和缓存统计等功能
auto &resources = ResourceManager::getInstance(); auto &resources = ResourceManager::getInstance();
// 先检查缓存中是否已有该纹理 // 先检查缓存中是否已有该纹理
auto texture = resources.getTexture(filepath); auto texture = resources.getTexture(filepath);
if (texture) { if (texture) {
E2D_TRACE("SpriteFrameCache: 使用缓存纹理: {}", filepath); E2D_TRACE("SpriteFrameCache: 使用缓存纹理: {}", filepath);
return texture; return texture;
} }
// 缓存未命中,通过 ResourceManager 加载 // 缓存未命中,通过 ResourceManager 加载
texture = resources.loadTexture(filepath); texture = resources.loadTexture(filepath);
if (!texture) { if (!texture) {
E2D_ERROR("SpriteFrameCache: 加载纹理失败: {}", filepath); E2D_ERROR("SpriteFrameCache: 加载纹理失败: {}", filepath);
return nullptr; return nullptr;
} }
E2D_TRACE("SpriteFrameCache: 加载新纹理: {}", filepath); E2D_TRACE("SpriteFrameCache: 加载新纹理: {}", filepath);
return texture; return texture;
} }

View File

@ -3,8 +3,9 @@
#include <core/string.h> #include <core/string.h>
#include <core/types.h> #include <core/types.h>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <platform/window.h>
#include <memory> #include <memory>
#include <platform/window.h>
namespace extra2d { namespace extra2d {
@ -22,11 +23,7 @@ class Camera;
// Application 配置 // Application 配置
// ============================================================================ // ============================================================================
enum class PlatformType { enum class PlatformType { Auto = 0, PC, Switch };
Auto = 0,
PC,
Switch
};
struct AppConfig { struct AppConfig {
std::string title = "Easy2D Application"; std::string title = "Easy2D Application";
@ -36,12 +33,12 @@ struct AppConfig {
bool resizable = true; bool resizable = true;
bool vsync = true; bool vsync = true;
int fpsLimit = 0; int fpsLimit = 0;
BackendType renderBackend = BackendType::OpenGL; BackendType Renderer = BackendType::OpenGL;
int msaaSamples = 0; int msaaSamples = 0;
PlatformType platform = PlatformType::Auto; PlatformType platform = PlatformType::Auto;
// 窗口高级配置 // 窗口高级配置
bool enableCursors = true; // 是否启用光标 bool enableCursors = true; // 是否启用光标
bool enableDpiScale = false; // 是否启用DPI缩放 bool enableDpiScale = false; // 是否启用DPI缩放
}; };
// ============================================================================ // ============================================================================
@ -76,7 +73,7 @@ public:
// 子系统访问 // 子系统访问
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
Window &window() { return *window_; } Window &window() { return *window_; }
RenderBackend &renderer() { return *renderer_; } Renderer &renderer() { return *renderer_; }
Input &input(); Input &input();
AudioEngine &audio(); AudioEngine &audio();
SceneManager &scenes(); SceneManager &scenes();
@ -90,7 +87,8 @@ public:
// 便捷方法 // 便捷方法
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void enterScene(Ptr<class Scene> scene); void enterScene(Ptr<class Scene> scene);
void enterScene(Ptr<class Scene> scene, Ptr<class TransitionScene> transitionScene); void enterScene(Ptr<class Scene> scene,
Ptr<class TransitionScene> transitionScene);
float deltaTime() const { return deltaTime_; } float deltaTime() const { return deltaTime_; }
float totalTime() const { return totalTime_; } float totalTime() const { return totalTime_; }
@ -113,7 +111,7 @@ private:
// 子系统 // 子系统
UniquePtr<Window> window_; UniquePtr<Window> window_;
UniquePtr<RenderBackend> renderer_; UniquePtr<Renderer> renderer_;
UniquePtr<SceneManager> sceneManager_; UniquePtr<SceneManager> sceneManager_;
UniquePtr<ResourceManager> resourceManager_; UniquePtr<ResourceManager> resourceManager_;
UniquePtr<TimerManager> timerManager_; UniquePtr<TimerManager> timerManager_;

View File

@ -28,8 +28,8 @@ public:
bool isValid(int x, int y) const; bool isValid(int x, int y) const;
/// 获取遮罩尺寸 /// 获取遮罩尺寸
int getWidth() const { return width_; } int width() const { return width_; }
int getHeight() const { return height_; } int height() const { return height_; }
Size size() const { Size size() const {
return Size(static_cast<float>(width_), static_cast<float>(height_)); return Size(static_cast<float>(width_), static_cast<float>(height_));
} }

View File

@ -15,12 +15,12 @@ class Window;
// ============================================================================ // ============================================================================
// OpenGL 渲染器实现 // OpenGL 渲染器实现
// ============================================================================ // ============================================================================
class GLRenderer : public RenderBackend { class GLRenderer : public Renderer {
public: public:
GLRenderer(); GLRenderer();
~GLRenderer() override; ~GLRenderer() override;
// RenderBackend 接口实现 // Renderer 接口实现
bool init(Window *window) override; bool init(Window *window) override;
void shutdown() override; void shutdown() override;

View File

@ -3,7 +3,6 @@
#include <graphics/alpha_mask.h> #include <graphics/alpha_mask.h>
#include <graphics/texture.h> #include <graphics/texture.h>
#include <glad/glad.h> #include <glad/glad.h>
#include <memory> #include <memory>
@ -21,8 +20,8 @@ public:
~GLTexture(); ~GLTexture();
// Texture 接口实现 // Texture 接口实现
int getWidth() const override { return width_; } int width() const override { return width_; }
int getHeight() const override { return height_; } int height() const override { return height_; }
Size size() const override { Size size() const override {
return Size(static_cast<float>(width_), static_cast<float>(height_)); return Size(static_cast<float>(width_), static_cast<float>(height_));
} }

View File

@ -37,9 +37,9 @@ enum class BlendMode {
// ============================================================================ // ============================================================================
// 渲染后端抽象接口 // 渲染后端抽象接口
// ============================================================================ // ============================================================================
class RenderBackend { class Renderer {
public: public:
virtual ~RenderBackend() = default; virtual ~Renderer() = default;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 生命周期 // 生命周期
@ -132,7 +132,7 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 工厂方法 // 工厂方法
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
static UniquePtr<RenderBackend> create(BackendType type); static UniquePtr<Renderer> create(BackendType type);
}; };
} // namespace extra2d } // namespace extra2d

View File

@ -76,8 +76,8 @@ public:
// 尺寸和格式 // 尺寸和格式
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
int getWidth() const { return width_; } int width() const { return width_; }
int getHeight() const { return height_; } int height() const { return height_; }
Vec2 size() const { Vec2 size() const {
return Vec2(static_cast<float>(width_), static_cast<float>(height_)); return Vec2(static_cast<float>(width_), static_cast<float>(height_));
} }

View File

@ -3,7 +3,6 @@
#include <core/math_types.h> #include <core/math_types.h>
#include <core/types.h> #include <core/types.h>
namespace extra2d { namespace extra2d {
// ============================================================================ // ============================================================================
@ -39,8 +38,8 @@ public:
virtual ~Texture() = default; virtual ~Texture() = default;
// 获取尺寸 // 获取尺寸
virtual int getWidth() const = 0; virtual int width() const = 0;
virtual int getHeight() const = 0; virtual int height() const = 0;
virtual Size size() const = 0; virtual Size size() const = 0;
// 获取通道数 // 获取通道数

View File

@ -3,12 +3,12 @@
#include <core/color.h> #include <core/color.h>
#include <core/math_types.h> #include <core/math_types.h>
#include <core/types.h> #include <core/types.h>
#include <graphics/texture.h>
#include <graphics/opengl/gl_texture.h> #include <graphics/opengl/gl_texture.h>
#include <string> #include <graphics/texture.h>
#include <vector>
#include <unordered_map>
#include <memory> #include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace extra2d { namespace extra2d {
@ -20,11 +20,11 @@ namespace extra2d {
* @brief * @brief
*/ */
struct AtlasEntry { struct AtlasEntry {
std::string name; // 原始纹理名称/路径 std::string name; // 原始纹理名称/路径
Rect uvRect; // 在图集中的 UV 坐标范围 Rect uvRect; // 在图集中的 UV 坐标范围
Vec2 originalSize; // 原始纹理尺寸 Vec2 originalSize; // 原始纹理尺寸
uint32_t padding; // 边距(用于避免纹理 bleeding uint32_t padding; // 边距(用于避免纹理 bleeding
AtlasEntry() : uvRect(), originalSize(), padding(2) {} AtlasEntry() : uvRect(), originalSize(), padding(2) {}
}; };
@ -36,56 +36,56 @@ class TextureAtlasPage {
public: public:
static constexpr int DEFAULT_SIZE = 2048; static constexpr int DEFAULT_SIZE = 2048;
static constexpr int MAX_SIZE = 4096; static constexpr int MAX_SIZE = 4096;
static constexpr int MIN_TEXTURE_SIZE = 32; // 小于此大小的纹理才考虑合并 static constexpr int MIN_TEXTURE_SIZE = 32; // 小于此大小的纹理才考虑合并
static constexpr int PADDING = 2; // 纹理间边距 static constexpr int PADDING = 2; // 纹理间边距
TextureAtlasPage(int width = DEFAULT_SIZE, int height = DEFAULT_SIZE); TextureAtlasPage(int width = DEFAULT_SIZE, int height = DEFAULT_SIZE);
~TextureAtlasPage(); ~TextureAtlasPage();
// 尝试添加纹理到图集 // 尝试添加纹理到图集
// 返回是否成功,如果成功则输出 uvRect // 返回是否成功,如果成功则输出 uvRect
bool tryAddTexture(const std::string& name, int texWidth, int texHeight, bool tryAddTexture(const std::string &name, int texWidth, int texHeight,
const uint8_t* pixels, Rect& outUvRect); const uint8_t *pixels, Rect &outUvRect);
// 获取图集纹理 // 获取图集纹理
Ptr<Texture> getTexture() const { return texture_; } Ptr<Texture> getTexture() const { return texture_; }
// 获取条目 // 获取条目
const AtlasEntry* getEntry(const std::string& name) const; const AtlasEntry *getEntry(const std::string &name) const;
// 获取使用率 // 获取使用率
float getUsageRatio() const; float getUsageRatio() const;
// 获取尺寸 // 获取尺寸
int getWidth() const { return width_; } int width() const { return width_; }
int getHeight() const { return height_; } int height() const { return height_; }
// 是否已满 // 是否已满
bool isFull() const { return isFull_; } bool isFull() const { return isFull_; }
private: private:
int width_, height_; int width_, height_;
Ptr<Texture> texture_; Ptr<Texture> texture_;
std::unordered_map<std::string, AtlasEntry> entries_; std::unordered_map<std::string, AtlasEntry> entries_;
// 矩形打包数据 // 矩形打包数据
struct PackNode { struct PackNode {
int x, y, width, height; int x, y, width, height;
bool used; bool used;
std::unique_ptr<PackNode> left; std::unique_ptr<PackNode> left;
std::unique_ptr<PackNode> right; std::unique_ptr<PackNode> right;
PackNode(int x_, int y_, int w, int h) PackNode(int x_, int y_, int w, int h)
: x(x_), y(y_), width(w), height(h), used(false) {} : x(x_), y(y_), width(w), height(h), used(false) {}
}; };
std::unique_ptr<PackNode> root_; std::unique_ptr<PackNode> root_;
bool isFull_; bool isFull_;
int usedArea_; int usedArea_;
// 递归插入 // 递归插入
PackNode* insert(PackNode* node, int width, int height); PackNode *insert(PackNode *node, int width, int height);
void writePixels(int x, int y, int w, int h, const uint8_t* pixels); void writePixels(int x, int y, int w, int h, const uint8_t *pixels);
}; };
/** /**
@ -96,47 +96,49 @@ class TextureAtlas {
public: public:
TextureAtlas(); TextureAtlas();
~TextureAtlas(); ~TextureAtlas();
// 初始化 // 初始化
void init(int pageSize = TextureAtlasPage::DEFAULT_SIZE); void init(int pageSize = TextureAtlasPage::DEFAULT_SIZE);
// 添加纹理到图集 // 添加纹理到图集
// 如果纹理太大,返回 false应该作为独立纹理加载 // 如果纹理太大,返回 false应该作为独立纹理加载
bool addTexture(const std::string& name, int width, int height, bool addTexture(const std::string &name, int width, int height,
const uint8_t* pixels); const uint8_t *pixels);
// 查询纹理是否在图集中 // 查询纹理是否在图集中
bool contains(const std::string& name) const; bool contains(const std::string &name) const;
// 获取纹理在图集中的信息 // 获取纹理在图集中的信息
// 返回图集纹理和 UV 坐标 // 返回图集纹理和 UV 坐标
const Texture* getAtlasTexture(const std::string& name) const; const Texture *getAtlasTexture(const std::string &name) const;
Rect getUVRect(const std::string& name) const; Rect getUVRect(const std::string &name) const;
// 获取原始纹理尺寸 // 获取原始纹理尺寸
Vec2 getOriginalSize(const std::string& name) const; Vec2 getOriginalSize(const std::string &name) const;
// 获取所有图集页面 // 获取所有图集页面
const std::vector<std::unique_ptr<TextureAtlasPage>>& getPages() const { return pages_; } const std::vector<std::unique_ptr<TextureAtlasPage>> &getPages() const {
return pages_;
}
// 获取总使用率 // 获取总使用率
float getTotalUsageRatio() const; float getTotalUsageRatio() const;
// 清空所有图集 // 清空所有图集
void clear(); void clear();
// 设置是否启用自动图集 // 设置是否启用自动图集
void setEnabled(bool enabled) { enabled_ = enabled; } void setEnabled(bool enabled) { enabled_ = enabled; }
bool isEnabled() const { return enabled_; } bool isEnabled() const { return enabled_; }
// 设置纹理大小阈值(小于此大小的纹理才进入图集) // 设置纹理大小阈值(小于此大小的纹理才进入图集)
void setSizeThreshold(int threshold) { sizeThreshold_ = threshold; } void setSizeThreshold(int threshold) { sizeThreshold_ = threshold; }
int getSizeThreshold() const { return sizeThreshold_; } int getSizeThreshold() const { return sizeThreshold_; }
private: private:
std::vector<std::unique_ptr<TextureAtlasPage>> pages_; std::vector<std::unique_ptr<TextureAtlasPage>> pages_;
std::unordered_map<std::string, TextureAtlasPage*> entryToPage_; std::unordered_map<std::string, TextureAtlasPage *> entryToPage_;
int pageSize_; int pageSize_;
int sizeThreshold_; int sizeThreshold_;
bool enabled_; bool enabled_;
@ -148,36 +150,34 @@ private:
*/ */
class TextureAtlasManager { class TextureAtlasManager {
public: public:
static TextureAtlasManager& getInstance(); static TextureAtlasManager &getInstance();
// 获取主图集 // 获取主图集
TextureAtlas& getAtlas() { return atlas_; } TextureAtlas &getAtlas() { return atlas_; }
// 快捷方法 // 快捷方法
bool addTexture(const std::string& name, int width, int height, bool addTexture(const std::string &name, int width, int height,
const uint8_t* pixels) { const uint8_t *pixels) {
return atlas_.addTexture(name, width, height, pixels); return atlas_.addTexture(name, width, height, pixels);
} }
bool contains(const std::string& name) const { bool contains(const std::string &name) const { return atlas_.contains(name); }
return atlas_.contains(name);
} const Texture *getAtlasTexture(const std::string &name) const {
const Texture* getAtlasTexture(const std::string& name) const {
return atlas_.getAtlasTexture(name); return atlas_.getAtlasTexture(name);
} }
Rect getUVRect(const std::string& name) const { Rect getUVRect(const std::string &name) const {
return atlas_.getUVRect(name); return atlas_.getUVRect(name);
} }
private: private:
TextureAtlasManager() = default; TextureAtlasManager() = default;
~TextureAtlasManager() = default; ~TextureAtlasManager() = default;
TextureAtlasManager(const TextureAtlasManager&) = delete; TextureAtlasManager(const TextureAtlasManager &) = delete;
TextureAtlasManager& operator=(const TextureAtlasManager&) = delete; TextureAtlasManager &operator=(const TextureAtlasManager &) = delete;
TextureAtlas atlas_; TextureAtlas atlas_;
}; };

View File

@ -5,7 +5,6 @@
#include <core/types.h> #include <core/types.h>
#include <functional> #include <functional>
#include <SDL.h> #include <SDL.h>
namespace extra2d { namespace extra2d {
@ -75,8 +74,8 @@ public:
void setResizable(bool resizable); void setResizable(bool resizable);
// 获取窗口属性 // 获取窗口属性
int getWidth() const { return width_; } int width() const { return width_; }
int getHeight() const { return height_; } int height() const { return height_; }
Size size() const { Size size() const {
return Size(static_cast<float>(width_), static_cast<float>(height_)); return Size(static_cast<float>(width_), static_cast<float>(height_));
} }

View File

@ -11,12 +11,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace extra2d { namespace extra2d {
// 前向声明 // 前向声明
class Scene; class Scene;
class RenderBackend; class Renderer;
struct RenderCommand; struct RenderCommand;
class Tween; class Tween;
enum class TweenEasing : uint8_t; enum class TweenEasing : uint8_t;
@ -142,7 +141,7 @@ public:
virtual void onEnter(); virtual void onEnter();
virtual void onExit(); virtual void onExit();
virtual void onUpdate(float dt); virtual void onUpdate(float dt);
virtual void onRender(RenderBackend &renderer); virtual void onRender(Renderer &renderer);
virtual void onAttachToScene(Scene *scene); virtual void onAttachToScene(Scene *scene);
virtual void onDetachFromScene(); virtual void onDetachFromScene();
@ -246,7 +245,7 @@ public:
// 内部方法 // 内部方法
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void update(float dt); void update(float dt);
void render(RenderBackend &renderer); void render(Renderer &renderer);
void sortChildren(); void sortChildren();
bool isRunning() const { return running_; } bool isRunning() const { return running_; }
@ -258,7 +257,7 @@ public:
protected: protected:
// 子类重写 // 子类重写
virtual void onDraw(RenderBackend &renderer) {} virtual void onDraw(Renderer &renderer) {}
virtual void onUpdateNode(float dt) {} virtual void onUpdateNode(float dt) {}
virtual void generateRenderCommand(std::vector<RenderCommand> &commands, virtual void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) {}; int zOrder) {};

View File

@ -42,8 +42,8 @@ public:
void setViewportSize(const Size &size); void setViewportSize(const Size &size);
Size getViewportSize() const { return viewportSize_; } Size getViewportSize() const { return viewportSize_; }
float getWidth() const { return viewportSize_.width; } float width() const { return viewportSize_.width; }
float getHeight() const { return viewportSize_.height; } float height() const { return viewportSize_.height; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 场景状态 // 场景状态
@ -55,11 +55,11 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 渲染和更新 // 渲染和更新
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void renderScene(RenderBackend &renderer); void renderScene(Renderer &renderer);
virtual void renderContent(RenderBackend &renderer); virtual void renderContent(Renderer &renderer);
void updateScene(float dt); void updateScene(float dt);
void collectRenderCommands(std::vector<RenderCommand> &commands, void collectRenderCommands(std::vector<RenderCommand> &commands,
int parentZOrder = 0) override; int parentZOrder = 0) override;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 空间索引系统 // 空间索引系统

View File

@ -1,14 +1,15 @@
#pragma once #pragma once
#include <core/types.h> #include <core/types.h>
#include <functional>
#include <scene/scene.h> #include <scene/scene.h>
#include <scene/transition_scene.h> #include <scene/transition_scene.h>
#include <functional>
#include <stack> #include <stack>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
namespace extra2d { namespace extra2d {
// 前向声明 // 前向声明
@ -78,7 +79,7 @@ public:
// 更新和渲染 // 更新和渲染
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void update(float dt); void update(float dt);
void render(RenderBackend &renderer); void render(Renderer &renderer);
void collectRenderCommands(std::vector<RenderCommand> &commands); void collectRenderCommands(std::vector<RenderCommand> &commands);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -114,8 +115,8 @@ private:
// 创建过渡场景 // 创建过渡场景
Ptr<TransitionScene> createTransitionScene(TransitionType type, Ptr<TransitionScene> createTransitionScene(TransitionType type,
float duration, float duration,
Ptr<Scene> inScene); Ptr<Scene> inScene);
std::stack<Ptr<Scene>> sceneStack_; std::stack<Ptr<Scene>> sceneStack_;
std::unordered_map<std::string, Ptr<Scene>> namedScenes_; std::unordered_map<std::string, Ptr<Scene>> namedScenes_;

View File

@ -88,7 +88,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDraw(RenderBackend &renderer) override; void onDraw(Renderer &renderer) override;
void generateRenderCommand(std::vector<RenderCommand> &commands, void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) override; int zOrder) override;

View File

@ -40,7 +40,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDraw(RenderBackend &renderer) override; void onDraw(Renderer &renderer) override;
void generateRenderCommand(std::vector<RenderCommand> &commands, void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) override; int zOrder) override;

View File

@ -25,7 +25,7 @@ public:
protected: protected:
void onTransitionStart() override; void onTransitionStart() override;
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
private: private:
int divisions_; int divisions_;

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <scene/transition_scene.h>
#include <scene/sprite.h>
#include <core/color.h> #include <core/color.h>
#include <scene/sprite.h>
#include <scene/transition_scene.h>
namespace extra2d { namespace extra2d {
@ -39,7 +40,7 @@ protected:
* @brief * @brief
* *
*/ */
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
private: private:
/** /**
@ -47,8 +48,8 @@ private:
*/ */
void hideOutShowIn(); void hideOutShowIn();
Color maskColor_; // 遮罩颜色 Color maskColor_; // 遮罩颜色
bool hasSwitched_ = false; // 是否已经切换场景 bool hasSwitched_ = false; // 是否已经切换场景
}; };
} // namespace extra2d } // namespace extra2d

View File

@ -28,7 +28,7 @@ public:
protected: protected:
void onTransitionStart() override; void onTransitionStart() override;
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
private: private:
Axis axis_; Axis axis_;

View File

@ -23,7 +23,7 @@ public:
protected: protected:
void onTransitionStart() override; void onTransitionStart() override;
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
}; };
} // namespace extra2d } // namespace extra2d

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <scene/scene.h>
#include <functional> #include <functional>
#include <scene/scene.h>
namespace extra2d { namespace extra2d {
@ -63,7 +64,9 @@ public:
/** /**
* @brief * @brief
*/ */
void setFinishCallback(FinishCallback callback) { finishCallback_ = callback; } void setFinishCallback(FinishCallback callback) {
finishCallback_ = callback;
}
/** /**
* @brief * @brief
@ -88,7 +91,7 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 渲染 - 在 TransitionScene 上渲染新旧两个子场景 // 渲染 - 在 TransitionScene 上渲染新旧两个子场景
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 生命周期 // 生命周期
@ -106,20 +109,20 @@ protected:
/** /**
* @brief * @brief
*/ */
virtual void drawOutScene(RenderBackend &renderer); virtual void drawOutScene(Renderer &renderer);
/** /**
* @brief * @brief
*/ */
virtual void drawInScene(RenderBackend &renderer); virtual void drawInScene(Renderer &renderer);
float duration_; float duration_;
float elapsed_ = 0.0f; float elapsed_ = 0.0f;
float progress_ = 0.0f; float progress_ = 0.0f;
bool isFinished_ = false; bool isFinished_ = false;
Ptr<Scene> inScene_; // 要进入的场景 Ptr<Scene> inScene_; // 要进入的场景
Ptr<Scene> outScene_; // 要退出的场景 Ptr<Scene> outScene_; // 要退出的场景
FinishCallback finishCallback_; FinishCallback finishCallback_;
}; };

View File

@ -26,7 +26,7 @@ public:
protected: protected:
void onTransitionStart() override; void onTransitionStart() override;
void renderContent(RenderBackend &renderer) override; void renderContent(Renderer &renderer) override;
private: private:
TransitionDirection direction_; TransitionDirection direction_;

View File

@ -181,12 +181,12 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
void drawBackgroundImage(RenderBackend &renderer, const Rect &rect); void drawBackgroundImage(Renderer &renderer, const Rect &rect);
void drawRoundedRect(RenderBackend &renderer, const Rect &rect, void drawRoundedRect(Renderer &renderer, const Rect &rect, const Color &color,
const Color &color, float radius); float radius);
void fillRoundedRect(RenderBackend &renderer, const Rect &rect, void fillRoundedRect(Renderer &renderer, const Rect &rect, const Color &color,
const Color &color, float radius); float radius);
Vec2 calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize); Vec2 calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize);
// 状态访问(供子类使用) // 状态访问(供子类使用)

View File

@ -74,7 +74,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
bool onMousePress(const MouseEvent &event) override; bool onMousePress(const MouseEvent &event) override;
bool onMouseRelease(const MouseEvent &event) override; bool onMouseRelease(const MouseEvent &event) override;

View File

@ -111,7 +111,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
private: private:
std::string text_; std::string text_;
@ -138,8 +138,7 @@ private:
mutable bool sizeDirty_ = true; mutable bool sizeDirty_ = true;
void updateCache() const; void updateCache() const;
void drawText(RenderBackend &renderer, const Vec2 &position, void drawText(Renderer &renderer, const Vec2 &position, const Color &color);
const Color &color);
Vec2 calculateDrawPosition() const; Vec2 calculateDrawPosition() const;
std::vector<std::string> splitLines() const; std::vector<std::string> splitLines() const;
}; };

View File

@ -151,7 +151,7 @@ public:
protected: protected:
void onUpdate(float deltaTime) override; void onUpdate(float deltaTime) override;
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
private: private:
// 数值 // 数值
@ -210,11 +210,11 @@ private:
Color getCurrentFillColor() const; Color getCurrentFillColor() const;
std::string formatText() const; std::string formatText() const;
void drawRoundedRect(RenderBackend &renderer, const Rect &rect, void drawRoundedRect(Renderer &renderer, const Rect &rect, const Color &color,
const Color &color, float radius); float radius);
void fillRoundedRect(RenderBackend &renderer, const Rect &rect, void fillRoundedRect(Renderer &renderer, const Rect &rect, const Color &color,
const Color &color, float radius); float radius);
void drawStripes(RenderBackend &renderer, const Rect &rect); void drawStripes(Renderer &renderer, const Rect &rect);
}; };
} // namespace extra2d } // namespace extra2d

View File

@ -79,7 +79,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
bool onMousePress(const MouseEvent &event) override; bool onMousePress(const MouseEvent &event) override;
bool onMouseRelease(const MouseEvent &event) override; bool onMouseRelease(const MouseEvent &event) override;

View File

@ -106,7 +106,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
bool onMousePress(const MouseEvent &event) override; bool onMousePress(const MouseEvent &event) override;
bool onMouseRelease(const MouseEvent &event) override; bool onMouseRelease(const MouseEvent &event) override;
bool onMouseMove(const MouseEvent &event) override; bool onMouseMove(const MouseEvent &event) override;

View File

@ -8,7 +8,6 @@
#include <string> #include <string>
#include <ui/widget.h> #include <ui/widget.h>
namespace extra2d { namespace extra2d {
// ============================================================================ // ============================================================================
@ -102,7 +101,7 @@ public:
Rect boundingBox() const override; Rect boundingBox() const override;
protected: protected:
void onDrawWidget(RenderBackend &renderer) override; void onDrawWidget(Renderer &renderer) override;
private: private:
std::string text_; std::string text_;

View File

@ -59,10 +59,10 @@ protected:
} }
// 子类重写此方法以支持自定义渲染 // 子类重写此方法以支持自定义渲染
virtual void onDrawWidget(RenderBackend &renderer) {} virtual void onDrawWidget(Renderer &renderer) {}
// 重写 Node 的 onDraw // 重写 Node 的 onDraw
void onDraw(RenderBackend &renderer) override; void onDraw(Renderer &renderer) override;
private: private:
Size size_ = Size::Zero(); Size size_ = Size::Zero();

View File

@ -13,7 +13,6 @@
#include <utils/object_pool.h> #include <utils/object_pool.h>
#include <utils/timer.h> #include <utils/timer.h>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
@ -121,7 +120,7 @@ bool Application::init(const AppConfig &config) {
// ======================================== // ========================================
// 4. 初始化渲染器 // 4. 初始化渲染器
// ======================================== // ========================================
renderer_ = RenderBackend::create(config.renderBackend); renderer_ = Renderer::create(config.Renderer);
if (!renderer_ || !renderer_->init(window_.get())) { if (!renderer_ || !renderer_->init(window_.get())) {
E2D_LOG_ERROR("Failed to initialize renderer"); E2D_LOG_ERROR("Failed to initialize renderer");
window_->destroy(); window_->destroy();
@ -136,8 +135,8 @@ bool Application::init(const AppConfig &config) {
timerManager_ = makeUnique<TimerManager>(); timerManager_ = makeUnique<TimerManager>();
eventQueue_ = makeUnique<EventQueue>(); eventQueue_ = makeUnique<EventQueue>();
eventDispatcher_ = makeUnique<EventDispatcher>(); eventDispatcher_ = makeUnique<EventDispatcher>();
camera_ = makeUnique<Camera>(0, static_cast<float>(window_->getWidth()), camera_ = makeUnique<Camera>(0, static_cast<float>(window_->width()),
static_cast<float>(window_->getHeight()), 0); static_cast<float>(window_->height()), 0);
// 窗口大小回调 // 窗口大小回调
window_->setResizeCallback([this](int width, int height) { window_->setResizeCallback([this](int width, int height) {
@ -356,7 +355,7 @@ void Application::render() {
return; return;
} }
renderer_->setViewport(0, 0, window_->getWidth(), window_->getHeight()); renderer_->setViewport(0, 0, window_->width(), window_->height());
if (sceneManager_) { if (sceneManager_) {
sceneManager_->render(*renderer_); sceneManager_->render(*renderer_);
@ -388,8 +387,8 @@ void Application::enterScene(Ptr<Scene> scene) { enterScene(scene, nullptr); }
void Application::enterScene(Ptr<Scene> scene, void Application::enterScene(Ptr<Scene> scene,
Ptr<class TransitionScene> transitionScene) { Ptr<class TransitionScene> transitionScene) {
if (sceneManager_ && scene) { if (sceneManager_ && scene) {
scene->setViewportSize(static_cast<float>(window_->getWidth()), scene->setViewportSize(static_cast<float>(window_->width()),
static_cast<float>(window_->getHeight())); static_cast<float>(window_->height()));
sceneManager_->enterScene(scene, transitionScene); sceneManager_->enterScene(scene, transitionScene);
} }
} }

View File

@ -1,8 +1,8 @@
#include <SDL.h> #include <SDL.h>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstring>
#include <core/string.h> #include <core/string.h>
#include <cstring>
#include <graphics/gpu_context.h> #include <graphics/gpu_context.h>
#include <graphics/opengl/gl_font_atlas.h> #include <graphics/opengl/gl_font_atlas.h>
#include <graphics/opengl/gl_renderer.h> #include <graphics/opengl/gl_renderer.h>
@ -227,8 +227,8 @@ void GLRenderer::drawSprite(const Texture &texture, const Rect &destRect,
data.size = glm::vec2(destRect.size.width, destRect.size.height); data.size = glm::vec2(destRect.size.width, destRect.size.height);
Texture *tex = const_cast<Texture *>(&texture); Texture *tex = const_cast<Texture *>(&texture);
float texW = static_cast<float>(tex->getWidth()); float texW = static_cast<float>(tex->width());
float texH = static_cast<float>(tex->getHeight()); float texH = static_cast<float>(tex->height());
// 纹理坐标计算 // 纹理坐标计算
float u1 = srcRect.origin.x / texW; float u1 = srcRect.origin.x / texW;
@ -249,10 +249,10 @@ void GLRenderer::drawSprite(const Texture &texture, const Rect &destRect,
void GLRenderer::drawSprite(const Texture &texture, const Vec2 &position, void GLRenderer::drawSprite(const Texture &texture, const Vec2 &position,
const Color &tint) { const Color &tint) {
Rect destRect(position.x, position.y, static_cast<float>(texture.getWidth()), Rect destRect(position.x, position.y, static_cast<float>(texture.width()),
static_cast<float>(texture.getHeight())); static_cast<float>(texture.height()));
Rect srcRect(0, 0, static_cast<float>(texture.getWidth()), Rect srcRect(0, 0, static_cast<float>(texture.width()),
static_cast<float>(texture.getHeight())); static_cast<float>(texture.height()));
drawSprite(texture, destRect, srcRect, tint, 0.0f, Vec2(0, 0)); drawSprite(texture, destRect, srcRect, tint, 0.0f, Vec2(0, 0));
} }
@ -446,7 +446,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
// 收集所有字符数据用于批处理 // 收集所有字符数据用于批处理
std::vector<GLSpriteBatch::SpriteData> sprites; std::vector<GLSpriteBatch::SpriteData> sprites;
sprites.reserve(text.size()); // 预分配空间 sprites.reserve(text.size()); // 预分配空间
for (char32_t codepoint : utf8ToUtf32(text)) { for (char32_t codepoint : utf8ToUtf32(text)) {
if (codepoint == '\n') { if (codepoint == '\n') {
@ -477,7 +477,7 @@ void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
data.rotation = 0.0f; data.rotation = 0.0f;
data.anchor = glm::vec2(0.0f, 0.0f); data.anchor = glm::vec2(0.0f, 0.0f);
data.isSDF = font.isSDF(); data.isSDF = font.isSDF();
sprites.push_back(data); sprites.push_back(data);
} }
} }

View File

@ -3,7 +3,7 @@
namespace extra2d { namespace extra2d {
UniquePtr<RenderBackend> RenderBackend::create(BackendType type) { UniquePtr<Renderer> Renderer::create(BackendType type) {
switch (type) { switch (type) {
case BackendType::OpenGL: case BackendType::OpenGL:
return makeUnique<GLRenderer>(); return makeUnique<GLRenderer>();

View File

@ -81,8 +81,8 @@ bool RenderTarget::createFromTexture(Ptr<Texture> texture, bool hasDepth) {
destroy(); destroy();
width_ = texture->getWidth(); width_ = texture->width();
height_ = texture->getHeight(); height_ = texture->height();
colorFormat_ = texture->getFormat(); colorFormat_ = texture->getFormat();
hasDepth_ = hasDepth; hasDepth_ = hasDepth;
hasStencil_ = false; hasStencil_ = false;
@ -238,8 +238,8 @@ void RenderTarget::blitTo(RenderTarget &target, bool color, bool depth) {
} }
if (mask != 0) { if (mask != 0) {
glBlitFramebuffer(0, 0, width_, height_, 0, 0, target.getWidth(), glBlitFramebuffer(0, 0, width_, height_, 0, 0, target.width(),
target.getHeight(), mask, GL_LINEAR); target.height(), mask, GL_LINEAR);
} }
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -453,8 +453,8 @@ void MultisampleRenderTarget::resolveTo(RenderTarget &target) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_); glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.getFBO()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.getFBO());
glBlitFramebuffer(0, 0, width_, height_, 0, 0, target.getWidth(), glBlitFramebuffer(0, 0, width_, height_, 0, 0, target.width(),
target.getHeight(), GL_COLOR_BUFFER_BIT, GL_LINEAR); target.height(), GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }

View File

@ -1,11 +1,11 @@
#include <algorithm> #include <algorithm>
#include <cstring>
#include <audio/audio_engine.h> #include <audio/audio_engine.h>
#include <cstring>
#include <graphics/opengl/gl_font_atlas.h> #include <graphics/opengl/gl_font_atlas.h>
#include <graphics/opengl/gl_texture.h> #include <graphics/opengl/gl_texture.h>
#include <resource/resource_manager.h> #include <resource/resource_manager.h>
#include <utils/logger.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <utils/logger.h>
// Windows 平台需要包含的头文件 // Windows 平台需要包含的头文件
#ifdef _WIN32 #ifdef _WIN32
@ -41,7 +41,8 @@ static std::string getExecutableDirectory() {
} }
#endif #endif
// 解析资源路径(优先尝试 romfs:/ 前缀,然后 sdmc:/,最后尝试相对于可执行文件的路径) // 解析资源路径(优先尝试 romfs:/ 前缀,然后
// sdmc:/,最后尝试相对于可执行文件的路径)
static std::string resolveResourcePath(const std::string &filepath) { static std::string resolveResourcePath(const std::string &filepath) {
// 如果已经是 romfs 或 sdmc 路径,直接返回 // 如果已经是 romfs 或 sdmc 路径,直接返回
if (isRomfsPath(filepath) || filepath.find("sdmc:/") == 0) { if (isRomfsPath(filepath) || filepath.find("sdmc:/") == 0) {
@ -81,9 +82,7 @@ static std::string resolveResourcePath(const std::string &filepath) {
ResourceManager::ResourceManager() = default; ResourceManager::ResourceManager() = default;
ResourceManager::~ResourceManager() { ResourceManager::~ResourceManager() { shutdownAsyncLoader(); }
shutdownAsyncLoader();
}
ResourceManager &ResourceManager::getInstance() { ResourceManager &ResourceManager::getInstance() {
static ResourceManager instance; static ResourceManager instance;
@ -98,9 +97,10 @@ void ResourceManager::initAsyncLoader() {
if (asyncRunning_) { if (asyncRunning_) {
return; return;
} }
asyncRunning_ = true; asyncRunning_ = true;
asyncThread_ = std::make_unique<std::thread>(&ResourceManager::asyncLoadLoop, this); asyncThread_ =
std::make_unique<std::thread>(&ResourceManager::asyncLoadLoop, this);
E2D_LOG_INFO("ResourceManager: async loader initialized"); E2D_LOG_INFO("ResourceManager: async loader initialized");
} }
@ -108,14 +108,14 @@ void ResourceManager::shutdownAsyncLoader() {
if (!asyncRunning_) { if (!asyncRunning_) {
return; return;
} }
asyncRunning_ = false; asyncRunning_ = false;
asyncCondition_.notify_all(); asyncCondition_.notify_all();
if (asyncThread_ && asyncThread_->joinable()) { if (asyncThread_ && asyncThread_->joinable()) {
asyncThread_->join(); asyncThread_->join();
} }
E2D_LOG_INFO("ResourceManager: async loader shutdown"); E2D_LOG_INFO("ResourceManager: async loader shutdown");
} }
@ -132,34 +132,35 @@ bool ResourceManager::hasPendingAsyncLoads() const {
void ResourceManager::asyncLoadLoop() { void ResourceManager::asyncLoadLoop() {
while (asyncRunning_) { while (asyncRunning_) {
AsyncLoadTask task; AsyncLoadTask task;
{ {
std::unique_lock<std::mutex> lock(asyncQueueMutex_); std::unique_lock<std::mutex> lock(asyncQueueMutex_);
asyncCondition_.wait(lock, [this] { return !asyncTaskQueue_.empty() || !asyncRunning_; }); asyncCondition_.wait(
lock, [this] { return !asyncTaskQueue_.empty() || !asyncRunning_; });
if (!asyncRunning_) { if (!asyncRunning_) {
break; break;
} }
if (asyncTaskQueue_.empty()) { if (asyncTaskQueue_.empty()) {
continue; continue;
} }
task = std::move(asyncTaskQueue_.front()); task = std::move(asyncTaskQueue_.front());
asyncTaskQueue_.pop(); asyncTaskQueue_.pop();
} }
// 执行加载 // 执行加载
auto texture = loadTextureInternal(task.filepath, task.format); auto texture = loadTextureInternal(task.filepath, task.format);
// 回调 // 回调
if (task.callback) { if (task.callback) {
task.callback(texture); task.callback(texture);
} }
// 设置 promise // 设置 promise
task.promise.set_value(texture); task.promise.set_value(texture);
pendingAsyncLoads_--; pendingAsyncLoads_--;
} }
} }
@ -172,25 +173,30 @@ Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath) {
return loadTexture(filepath, false, TextureFormat::Auto); return loadTexture(filepath, false, TextureFormat::Auto);
} }
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath, bool async) { Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath,
bool async) {
return loadTexture(filepath, async, TextureFormat::Auto); return loadTexture(filepath, async, TextureFormat::Auto);
} }
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath, bool async, TextureFormat format) { Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath,
bool async, TextureFormat format) {
if (async) { if (async) {
// 异步加载:返回空指针,实际纹理通过回调获取 // 异步加载:返回空指针,实际纹理通过回调获取
loadTextureAsync(filepath, format, nullptr); loadTextureAsync(filepath, format, nullptr);
return nullptr; return nullptr;
} }
return loadTextureInternal(filepath, format); return loadTextureInternal(filepath, format);
} }
void ResourceManager::loadTextureAsync(const std::string &filepath, TextureLoadCallback callback) { void ResourceManager::loadTextureAsync(const std::string &filepath,
TextureLoadCallback callback) {
loadTextureAsync(filepath, TextureFormat::Auto, callback); loadTextureAsync(filepath, TextureFormat::Auto, callback);
} }
void ResourceManager::loadTextureAsync(const std::string &filepath, TextureFormat format, TextureLoadCallback callback) { void ResourceManager::loadTextureAsync(const std::string &filepath,
TextureFormat format,
TextureLoadCallback callback) {
// 确保异步加载系统已启动 // 确保异步加载系统已启动
if (!asyncRunning_) { if (!asyncRunning_) {
initAsyncLoader(); initAsyncLoader();
@ -229,7 +235,8 @@ void ResourceManager::loadTextureAsync(const std::string &filepath, TextureForma
E2D_LOG_DEBUG("ResourceManager: queued async texture load: {}", filepath); E2D_LOG_DEBUG("ResourceManager: queued async texture load: {}", filepath);
} }
Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, TextureFormat format) { Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath,
TextureFormat format) {
std::lock_guard<std::mutex> lock(textureMutex_); std::lock_guard<std::mutex> lock(textureMutex_);
// 检查缓存 // 检查缓存
@ -273,7 +280,8 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, T
evictTexturesIfNeeded(); evictTexturesIfNeeded();
// 计算纹理大小 // 计算纹理大小
size_t textureSize = calculateTextureSize(texture->getWidth(), texture->getHeight(), texture->getFormat()); size_t textureSize = calculateTextureSize(
texture->width(), texture->height(), texture->getFormat());
// 分配LRU节点 // 分配LRU节点
uint32_t lruIndex = allocateLRUNode(filepath); uint32_t lruIndex = allocateLRUNode(filepath);
@ -292,7 +300,8 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath, T
// 添加到LRU链表头部 // 添加到LRU链表头部
moveToFront(lruIndex); moveToFront(lruIndex);
E2D_LOG_DEBUG("ResourceManager: loaded texture: {} ({} KB)", filepath, textureSize / 1024); E2D_LOG_DEBUG("ResourceManager: loaded texture: {} ({} KB)", filepath,
textureSize / 1024);
return texture; return texture;
} catch (...) { } catch (...) {
E2D_LOG_ERROR("ResourceManager: exception loading texture: {}", filepath); E2D_LOG_ERROR("ResourceManager: exception loading texture: {}", filepath);
@ -304,24 +313,26 @@ TextureFormat ResourceManager::selectBestFormat(TextureFormat requested) const {
if (requested != TextureFormat::Auto) { if (requested != TextureFormat::Auto) {
return requested; return requested;
} }
// 自动选择最佳格式 // 自动选择最佳格式
// 检查支持的扩展 // 检查支持的扩展
// 这里简化处理,实际应该查询 OpenGL 扩展 // 这里简化处理,实际应该查询 OpenGL 扩展
// 桌面平台优先 DXT // 桌面平台优先 DXT
// 移动平台优先 ETC2 或 ASTC // 移动平台优先 ETC2 或 ASTC
// 默认返回 RGBA8 // 默认返回 RGBA8
return TextureFormat::RGBA8; return TextureFormat::RGBA8;
} }
std::vector<uint8_t> ResourceManager::compressTexture(const uint8_t* data, int width, int height, std::vector<uint8_t> ResourceManager::compressTexture(const uint8_t *data,
int channels, TextureFormat format) { int width, int height,
int channels,
TextureFormat format) {
// 纹理压缩实现 // 纹理压缩实现
// 这里需要根据格式使用相应的压缩库 // 这里需要根据格式使用相应的压缩库
// 如squish (DXT), etcpack (ETC2), astc-encoder (ASTC) // 如squish (DXT), etcpack (ETC2), astc-encoder (ASTC)
// 目前返回原始数据 // 目前返回原始数据
std::vector<uint8_t> result(data, data + width * height * channels); std::vector<uint8_t> result(data, data + width * height * channels);
return result; return result;
@ -383,9 +394,9 @@ Ptr<Texture> ResourceManager::getTexture(const std::string &key) const {
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
const_cast<ResourceManager*>(this)->touchTexture(key); const_cast<ResourceManager *>(this)->touchTexture(key);
const_cast<ResourceManager*>(this)->textureHitCount_++; const_cast<ResourceManager *>(this)->textureHitCount_++;
const_cast<uint32_t&>(it->second.accessCount)++; const_cast<uint32_t &>(it->second.accessCount)++;
return it->second.texture; return it->second.texture;
} }
return nullptr; return nullptr;
@ -402,8 +413,9 @@ void ResourceManager::unloadTexture(const std::string &key) {
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
// 从LRU链表中移除 // 从LRU链表中移除
auto nodeIt = std::find_if(lruNodes_.begin(), lruNodes_.end(), auto nodeIt = std::find_if(
[&key](const LRUNode &node) { return node.valid && node.key == key; }); lruNodes_.begin(), lruNodes_.end(),
[&key](const LRUNode &node) { return node.valid && node.key == key; });
if (nodeIt != lruNodes_.end()) { if (nodeIt != lruNodes_.end()) {
removeFromList(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1); removeFromList(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1);
freeLRUNode(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1); freeLRUNode(static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1);
@ -648,7 +660,8 @@ size_t ResourceManager::getTextureCacheSize() const {
// LRU 缓存管理 // LRU 缓存管理
// ============================================================================ // ============================================================================
void ResourceManager::setTextureCache(size_t maxCacheSize, size_t maxTextureCount, void ResourceManager::setTextureCache(size_t maxCacheSize,
size_t maxTextureCount,
float unloadInterval) { float unloadInterval) {
std::lock_guard<std::mutex> lock(textureMutex_); std::lock_guard<std::mutex> lock(textureMutex_);
maxCacheSize_ = maxCacheSize; maxCacheSize_ = maxCacheSize;
@ -694,7 +707,8 @@ void ResourceManager::update(float dt) {
size_t targetSize = static_cast<size_t>(maxCacheSize_ * 0.5f); size_t targetSize = static_cast<size_t>(maxCacheSize_ * 0.5f);
while (totalTextureSize_ > targetSize && lruTail_ != 0) { while (totalTextureSize_ > targetSize && lruTail_ != 0) {
std::string key = evictLRU(); std::string key = evictLRU();
if (key.empty()) break; if (key.empty())
break;
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
@ -703,7 +717,8 @@ void ResourceManager::update(float dt) {
E2D_LOG_DEBUG("ResourceManager: auto-evicted texture: {}", key); E2D_LOG_DEBUG("ResourceManager: auto-evicted texture: {}", key);
} }
} }
E2D_LOG_INFO("ResourceManager: texture cache trimmed to {} MB", totalTextureSize_ / (1024 * 1024)); E2D_LOG_INFO("ResourceManager: texture cache trimmed to {} MB",
totalTextureSize_ / (1024 * 1024));
} }
} }
} }
@ -733,7 +748,8 @@ uint32_t ResourceManager::allocateLRUNode(const std::string &key) {
} }
void ResourceManager::freeLRUNode(uint32_t index) { void ResourceManager::freeLRUNode(uint32_t index) {
if (index == 0 || index > lruNodes_.size()) return; if (index == 0 || index > lruNodes_.size())
return;
LRUNode &node = lruNodes_[index - 1]; LRUNode &node = lruNodes_[index - 1];
node.valid = false; node.valid = false;
@ -744,7 +760,8 @@ void ResourceManager::freeLRUNode(uint32_t index) {
} }
void ResourceManager::moveToFront(uint32_t index) { void ResourceManager::moveToFront(uint32_t index) {
if (index == 0 || index > lruNodes_.size() || index == lruHead_) return; if (index == 0 || index > lruNodes_.size() || index == lruHead_)
return;
removeFromList(index); removeFromList(index);
@ -763,7 +780,8 @@ void ResourceManager::moveToFront(uint32_t index) {
} }
void ResourceManager::removeFromList(uint32_t index) { void ResourceManager::removeFromList(uint32_t index) {
if (index == 0 || index > lruNodes_.size()) return; if (index == 0 || index > lruNodes_.size())
return;
LRUNode &node = lruNodes_[index - 1]; LRUNode &node = lruNodes_[index - 1];
@ -781,7 +799,8 @@ void ResourceManager::removeFromList(uint32_t index) {
} }
std::string ResourceManager::evictLRU() { std::string ResourceManager::evictLRU() {
if (lruTail_ == 0) return ""; if (lruTail_ == 0)
return "";
uint32_t index = lruTail_; uint32_t index = lruTail_;
std::string key = lruNodes_[index - 1].key; std::string key = lruNodes_[index - 1].key;
@ -794,8 +813,9 @@ std::string ResourceManager::evictLRU() {
void ResourceManager::touchTexture(const std::string &key) { void ResourceManager::touchTexture(const std::string &key) {
// 查找对应的LRU节点 // 查找对应的LRU节点
auto nodeIt = std::find_if(lruNodes_.begin(), lruNodes_.end(), auto nodeIt = std::find_if(
[&key](const LRUNode &node) { return node.valid && node.key == key; }); lruNodes_.begin(), lruNodes_.end(),
[&key](const LRUNode &node) { return node.valid && node.key == key; });
if (nodeIt != lruNodes_.end()) { if (nodeIt != lruNodes_.end()) {
uint32_t index = static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1; uint32_t index = static_cast<uint32_t>(nodeIt - lruNodes_.begin()) + 1;
moveToFront(index); moveToFront(index);
@ -813,7 +833,8 @@ void ResourceManager::evictTexturesIfNeeded() {
textureCache_.size() >= maxTextureCount_) && textureCache_.size() >= maxTextureCount_) &&
lruTail_ != 0) { lruTail_ != 0) {
std::string key = evictLRU(); std::string key = evictLRU();
if (key.empty()) break; if (key.empty())
break;
auto it = textureCache_.find(key); auto it = textureCache_.find(key);
if (it != textureCache_.end()) { if (it != textureCache_.end()) {
@ -824,24 +845,25 @@ void ResourceManager::evictTexturesIfNeeded() {
} }
} }
size_t ResourceManager::calculateTextureSize(int width, int height, PixelFormat format) const { size_t ResourceManager::calculateTextureSize(int width, int height,
PixelFormat format) const {
int bytesPerPixel = 4; int bytesPerPixel = 4;
switch (format) { switch (format) {
case PixelFormat::R8: case PixelFormat::R8:
bytesPerPixel = 1; bytesPerPixel = 1;
break; break;
case PixelFormat::RG8: case PixelFormat::RG8:
bytesPerPixel = 2; bytesPerPixel = 2;
break; break;
case PixelFormat::RGB8: case PixelFormat::RGB8:
bytesPerPixel = 3; bytesPerPixel = 3;
break; break;
case PixelFormat::RGBA8: case PixelFormat::RGBA8:
bytesPerPixel = 4; bytesPerPixel = 4;
break; break;
default: default:
bytesPerPixel = 4; bytesPerPixel = 4;
break; break;
} }
return static_cast<size_t>(width * height * bytesPerPixel); return static_cast<size_t>(width * height * bytesPerPixel);
} }
@ -864,7 +886,8 @@ std::string ResourceManager::loadTextFile(const std::string &filepath) {
return loadTextFile(filepath, "UTF-8"); return loadTextFile(filepath, "UTF-8");
} }
std::string ResourceManager::loadTextFile(const std::string &filepath, const std::string &encoding) { std::string ResourceManager::loadTextFile(const std::string &filepath,
const std::string &encoding) {
(void)encoding; // 目前只支持 UTF-8 (void)encoding; // 目前只支持 UTF-8
std::lock_guard<std::mutex> lock(textFileMutex_); std::lock_guard<std::mutex> lock(textFileMutex_);
@ -888,13 +911,15 @@ std::string ResourceManager::loadTextFile(const std::string &filepath, const std
#ifdef _WIN32 #ifdef _WIN32
errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb"); errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb");
if (err != 0 || !file) { if (err != 0 || !file) {
E2D_LOG_ERROR("ResourceManager: failed to open text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open text file: {}",
resolvedPath);
return ""; return "";
} }
#else #else
file = fopen(resolvedPath.c_str(), "rb"); file = fopen(resolvedPath.c_str(), "rb");
if (!file) { if (!file) {
E2D_LOG_ERROR("ResourceManager: failed to open text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open text file: {}",
resolvedPath);
return ""; return "";
} }
#endif #endif
@ -917,13 +942,15 @@ std::string ResourceManager::loadTextFile(const std::string &filepath, const std
fclose(file); fclose(file);
if (readSize != static_cast<size_t>(fileSize)) { if (readSize != static_cast<size_t>(fileSize)) {
E2D_LOG_ERROR("ResourceManager: failed to read text file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to read text file: {}",
resolvedPath);
return ""; return "";
} }
// 缓存内容 // 缓存内容
textFileCache_[filepath] = content; textFileCache_[filepath] = content;
E2D_LOG_DEBUG("ResourceManager: loaded text file: {} ({} bytes)", filepath, content.size()); E2D_LOG_DEBUG("ResourceManager: loaded text file: {} ({} bytes)", filepath,
content.size());
return content; return content;
} }
@ -989,13 +1016,15 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
#ifdef _WIN32 #ifdef _WIN32
errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb"); errno_t err = fopen_s(&file, resolvedPath.c_str(), "rb");
if (err != 0 || !file) { if (err != 0 || !file) {
E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}",
resolvedPath);
return ""; return "";
} }
#else #else
file = fopen(resolvedPath.c_str(), "rb"); file = fopen(resolvedPath.c_str(), "rb");
if (!file) { if (!file) {
E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to open JSON file: {}",
resolvedPath);
return ""; return "";
} }
#endif #endif
@ -1018,7 +1047,8 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
fclose(file); fclose(file);
if (readSize != static_cast<size_t>(fileSize)) { if (readSize != static_cast<size_t>(fileSize)) {
E2D_LOG_ERROR("ResourceManager: failed to read JSON file: {}", resolvedPath); E2D_LOG_ERROR("ResourceManager: failed to read JSON file: {}",
resolvedPath);
return ""; return "";
} }
@ -1032,7 +1062,8 @@ std::string ResourceManager::loadJsonFile(const std::string &filepath) {
// 缓存内容 // 缓存内容
jsonFileCache_[filepath] = content; jsonFileCache_[filepath] = content;
E2D_LOG_DEBUG("ResourceManager: loaded JSON file: {} ({} bytes)", filepath, content.size()); E2D_LOG_DEBUG("ResourceManager: loaded JSON file: {} ({} bytes)", filepath,
content.size());
return content; return content;
} }

View File

@ -6,7 +6,6 @@
#include <scene/scene.h> #include <scene/scene.h>
#include <utils/logger.h> #include <utils/logger.h>
namespace extra2d { namespace extra2d {
Node::Node() = default; Node::Node() = default;
@ -343,7 +342,7 @@ void Node::onUpdate(float dt) {
} }
} }
void Node::onRender(RenderBackend &renderer) { void Node::onRender(Renderer &renderer) {
if (!visible_) if (!visible_)
return; return;
@ -402,7 +401,7 @@ void Node::updateSpatialIndex() {
void Node::update(float dt) { onUpdate(dt); } void Node::update(float dt) { onUpdate(dt); }
void Node::render(RenderBackend &renderer) { void Node::render(Renderer &renderer) {
if (childrenOrderDirty_) { if (childrenOrderDirty_) {
sortChildren(); sortChildren();
} }

View File

@ -22,7 +22,7 @@ void Scene::setViewportSize(const Size &size) {
setViewportSize(size.width, size.height); setViewportSize(size.width, size.height);
} }
void Scene::renderScene(RenderBackend &renderer) { void Scene::renderScene(Renderer &renderer) {
if (!visible()) if (!visible())
return; return;
@ -32,7 +32,7 @@ void Scene::renderScene(RenderBackend &renderer) {
renderer.endFrame(); renderer.endFrame();
} }
void Scene::renderContent(RenderBackend &renderer) { void Scene::renderContent(Renderer &renderer) {
if (!visible()) if (!visible())
return; return;

View File

@ -479,7 +479,7 @@ void SceneManager::update(float dt) {
} }
} }
void SceneManager::render(RenderBackend &renderer) { void SceneManager::render(Renderer &renderer) {
Color clearColor = Colors::Black; Color clearColor = Colors::Black;
if (!sceneStack_.empty()) { if (!sceneStack_.empty()) {
clearColor = sceneStack_.top()->getBackgroundColor(); clearColor = sceneStack_.top()->getBackgroundColor();

View File

@ -5,7 +5,6 @@
#include <limits> #include <limits>
#include <scene/shape_node.h> #include <scene/shape_node.h>
namespace extra2d { namespace extra2d {
ShapeNode::ShapeNode() = default; ShapeNode::ShapeNode() = default;
@ -167,7 +166,7 @@ Rect ShapeNode::boundingBox() const {
(maxY - minY) + inflate * 2.0f); (maxY - minY) + inflate * 2.0f);
} }
void ShapeNode::onDraw(RenderBackend &renderer) { void ShapeNode::onDraw(Renderer &renderer) {
if (points_.empty()) { if (points_.empty()) {
return; return;
} }

View File

@ -14,8 +14,8 @@ Sprite::Sprite(Ptr<Texture> texture) { setTexture(texture); }
void Sprite::setTexture(Ptr<Texture> texture) { void Sprite::setTexture(Ptr<Texture> texture) {
texture_ = texture; texture_ = texture;
if (texture_) { if (texture_) {
textureRect_ = Rect(0, 0, static_cast<float>(texture_->getWidth()), textureRect_ = Rect(0, 0, static_cast<float>(texture_->width()),
static_cast<float>(texture_->getHeight())); static_cast<float>(texture_->height()));
} }
updateSpatialIndex(); updateSpatialIndex();
} }
@ -67,7 +67,7 @@ Rect Sprite::boundingBox() const {
return Rect(l, t, std::abs(w), std::abs(h)); return Rect(l, t, std::abs(w), std::abs(h));
} }
void Sprite::onDraw(RenderBackend &renderer) { void Sprite::onDraw(Renderer &renderer) {
if (!texture_ || !texture_->isValid()) { if (!texture_ || !texture_->isValid()) {
return; return;
} }
@ -91,7 +91,7 @@ void Sprite::onDraw(RenderBackend &renderer) {
auto anchorPt = anchor(); auto anchorPt = anchor();
// 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸 // 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY); Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
// Adjust source rect for flipping // Adjust source rect for flipping
@ -137,7 +137,7 @@ void Sprite::generateRenderCommand(std::vector<RenderCommand> &commands,
auto anchorPt = anchor(); auto anchorPt = anchor();
// 锚点由 RenderBackend 在绘制时处理,这里只传递位置和尺寸 // 锚点由 Renderer 在绘制时处理,这里只传递位置和尺寸
Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY); Rect destRect(worldX, worldY, width * worldScaleX, height * worldScaleY);
// 调整源矩形(翻转) // 调整源矩形(翻转)

View File

@ -1,9 +1,9 @@
#include <scene/transition_box_scene.h> #include <algorithm>
#include <app/application.h> #include <app/application.h>
#include <graphics/render_backend.h>
#include <core/color.h> #include <core/color.h>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <algorithm> #include <graphics/render_backend.h>
#include <scene/transition_box_scene.h>
namespace extra2d { namespace extra2d {
@ -11,9 +11,8 @@ TransitionBoxScene::TransitionBoxScene(float duration, Ptr<Scene> inScene,
int divisions) int divisions)
: TransitionScene(duration, inScene), divisions_(divisions) {} : TransitionScene(duration, inScene), divisions_(divisions) {}
Ptr<TransitionBoxScene> TransitionBoxScene::create(float duration, Ptr<TransitionBoxScene>
Ptr<Scene> inScene, TransitionBoxScene::create(float duration, Ptr<Scene> inScene, int divisions) {
int divisions) {
return makePtr<TransitionBoxScene>(duration, inScene, divisions); return makePtr<TransitionBoxScene>(duration, inScene, divisions);
} }
@ -21,11 +20,11 @@ void TransitionBoxScene::onTransitionStart() {
// 方块过渡不需要特殊的初始化 // 方块过渡不需要特殊的初始化
} }
void TransitionBoxScene::renderContent(RenderBackend &renderer) { void TransitionBoxScene::renderContent(Renderer &renderer) {
// 获取窗口大小 // 获取窗口大小
auto &app = Application::instance(); auto &app = Application::instance();
float windowWidth = static_cast<float>(app.window().getWidth()); float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().getHeight()); float windowHeight = static_cast<float>(app.window().height());
// 更新进度 // 更新进度
elapsed_ += 1.0f / 60.0f; elapsed_ += 1.0f / 60.0f;

View File

@ -1,9 +1,9 @@
#include <scene/transition_fade_scene.h>
#include <app/application.h> #include <app/application.h>
#include <glm/gtc/matrix_transform.hpp>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <graphics/render_target.h> #include <graphics/render_target.h>
#include <scene/transition_fade_scene.h>
#include <utils/logger.h> #include <utils/logger.h>
#include <glm/gtc/matrix_transform.hpp>
namespace extra2d { namespace extra2d {
@ -25,14 +25,14 @@ void TransitionFadeScene::onTransitionStart() {
// 实际进度更新由 SceneManager 的 update 驱动 // 实际进度更新由 SceneManager 的 update 驱动
} }
void TransitionFadeScene::renderContent(RenderBackend &renderer) { void TransitionFadeScene::renderContent(Renderer &renderer) {
// 获取窗口大小 // 获取窗口大小
auto &app = Application::instance(); auto &app = Application::instance();
float windowWidth = static_cast<float>(app.window().getWidth()); float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().getHeight()); float windowHeight = static_cast<float>(app.window().height());
// 计算当前进度 // 计算当前进度
elapsed_ += 1.0f / 60.0f; // 假设 60fps实际应该由 update 传递 dt elapsed_ += 1.0f / 60.0f; // 假设 60fps实际应该由 update 传递 dt
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f; progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 检查是否需要切换场景(进度过半时) // 检查是否需要切换场景(进度过半时)
@ -54,10 +54,10 @@ void TransitionFadeScene::renderContent(RenderBackend &renderer) {
float maskAlpha; float maskAlpha;
if (progress_ < 0.5f) { if (progress_ < 0.5f) {
// 前半段:从透明到不透明 // 前半段:从透明到不透明
maskAlpha = progress_ * 2.0f; // 0 -> 1 maskAlpha = progress_ * 2.0f; // 0 -> 1
} else { } else {
// 后半段:从不透明到透明 // 后半段:从不透明到透明
maskAlpha = (1.0f - progress_) * 2.0f; // 1 -> 0 maskAlpha = (1.0f - progress_) * 2.0f; // 1 -> 0
} }
// 设置视口为整个窗口 // 设置视口为整个窗口

View File

@ -1,7 +1,8 @@
#include <scene/transition_flip_scene.h> #include <core/math_types.h>
#include <graphics/camera.h> #include <graphics/camera.h>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <core/math_types.h> #include <scene/transition_flip_scene.h>
namespace extra2d { namespace extra2d {
@ -9,9 +10,8 @@ TransitionFlipScene::TransitionFlipScene(float duration, Ptr<Scene> inScene,
Axis axis) Axis axis)
: TransitionScene(duration, inScene), axis_(axis) {} : TransitionScene(duration, inScene), axis_(axis) {}
Ptr<TransitionFlipScene> TransitionFlipScene::create(float duration, Ptr<TransitionFlipScene>
Ptr<Scene> inScene, TransitionFlipScene::create(float duration, Ptr<Scene> inScene, Axis axis) {
Axis axis) {
return makePtr<TransitionFlipScene>(duration, inScene, axis); return makePtr<TransitionFlipScene>(duration, inScene, axis);
} }
@ -19,16 +19,17 @@ void TransitionFlipScene::onTransitionStart() {
// 翻页过渡不需要特殊的初始化 // 翻页过渡不需要特殊的初始化
} }
void TransitionFlipScene::renderContent(RenderBackend &renderer) { void TransitionFlipScene::renderContent(Renderer &renderer) {
// 更新进度 // 更新进度
elapsed_ += 1.0f / 60.0f; elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f; progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数 // 缓动函数
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_ float easeProgress = progress_ < 0.5f
: -1.0f + (4.0f - 2.0f * progress_) * progress_; ? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
float angle = easeProgress * PI_F; // 180度翻转 float angle = easeProgress * PI_F; // 180度翻转
if (progress_ < 0.5f) { if (progress_ < 0.5f) {
// 前半段:翻转源场景 // 前半段:翻转源场景

View File

@ -1,7 +1,8 @@
#include <scene/transition_scale_scene.h> #include <algorithm>
#include <graphics/camera.h> #include <graphics/camera.h>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <algorithm> #include <scene/transition_scale_scene.h>
namespace extra2d { namespace extra2d {
@ -17,14 +18,15 @@ void TransitionScaleScene::onTransitionStart() {
// 缩放过渡不需要特殊的初始化 // 缩放过渡不需要特殊的初始化
} }
void TransitionScaleScene::renderContent(RenderBackend &renderer) { void TransitionScaleScene::renderContent(Renderer &renderer) {
// 更新进度 // 更新进度
elapsed_ += 1.0f / 60.0f; elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f; progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数 // 缓动函数
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_ float easeProgress = progress_ < 0.5f
: -1.0f + (4.0f - 2.0f * progress_) * progress_; ? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
// 源场景:缩小消失 // 源场景:缩小消失
if (outScene_) { if (outScene_) {

View File

@ -1,7 +1,8 @@
#include <scene/transition_scene.h>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <scene/transition_scene.h>
#include <utils/logger.h> #include <utils/logger.h>
namespace extra2d { namespace extra2d {
TransitionScene::TransitionScene(float duration, Ptr<Scene> inScene) TransitionScene::TransitionScene(float duration, Ptr<Scene> inScene)
@ -57,7 +58,7 @@ void TransitionScene::finish() {
} }
} }
void TransitionScene::renderContent(RenderBackend &renderer) { void TransitionScene::renderContent(Renderer &renderer) {
// 在 TransitionScene 上渲染新旧两个子场景 // 在 TransitionScene 上渲染新旧两个子场景
// 子类可以重写此方法来控制渲染顺序和效果 // 子类可以重写此方法来控制渲染顺序和效果
@ -66,13 +67,13 @@ void TransitionScene::renderContent(RenderBackend &renderer) {
drawInScene(renderer); drawInScene(renderer);
} }
void TransitionScene::drawOutScene(RenderBackend &renderer) { void TransitionScene::drawOutScene(Renderer &renderer) {
if (outScene_) { if (outScene_) {
outScene_->renderContent(renderer); outScene_->renderContent(renderer);
} }
} }
void TransitionScene::drawInScene(RenderBackend &renderer) { void TransitionScene::drawInScene(Renderer &renderer) {
if (inScene_) { if (inScene_) {
inScene_->renderContent(renderer); inScene_->renderContent(renderer);
} }

View File

@ -1,6 +1,7 @@
#include <scene/transition_slide_scene.h>
#include <graphics/camera.h> #include <graphics/camera.h>
#include <graphics/render_backend.h> #include <graphics/render_backend.h>
#include <scene/transition_slide_scene.h>
namespace extra2d { namespace extra2d {
@ -8,8 +9,9 @@ TransitionSlideScene::TransitionSlideScene(float duration, Ptr<Scene> inScene,
TransitionDirection direction) TransitionDirection direction)
: TransitionScene(duration, inScene), direction_(direction) {} : TransitionScene(duration, inScene), direction_(direction) {}
Ptr<TransitionSlideScene> TransitionSlideScene::create( Ptr<TransitionSlideScene>
float duration, Ptr<Scene> inScene, TransitionDirection direction) { TransitionSlideScene::create(float duration, Ptr<Scene> inScene,
TransitionDirection direction) {
return makePtr<TransitionSlideScene>(duration, inScene, direction); return makePtr<TransitionSlideScene>(duration, inScene, direction);
} }
@ -17,7 +19,7 @@ void TransitionSlideScene::onTransitionStart() {
// 滑动过渡不需要特殊的初始化 // 滑动过渡不需要特殊的初始化
} }
void TransitionSlideScene::renderContent(RenderBackend &renderer) { void TransitionSlideScene::renderContent(Renderer &renderer) {
// 获取视口尺寸 // 获取视口尺寸
float screenWidth = 800.0f; float screenWidth = 800.0f;
float screenHeight = 600.0f; float screenHeight = 600.0f;
@ -41,8 +43,9 @@ void TransitionSlideScene::renderContent(RenderBackend &renderer) {
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f; progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数 // 缓动函数
float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_ float easeProgress = progress_ < 0.5f
: -1.0f + (4.0f - 2.0f * progress_) * progress_; ? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
// 渲染退出场景(滑出) // 渲染退出场景(滑出)
if (outScene_) { if (outScene_) {

View File

@ -267,8 +267,8 @@ void Button::setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover,
useTextureRect_ = false; useTextureRect_ = false;
if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original && normal) { if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original && normal) {
setSize(static_cast<float>(normal->getWidth()), setSize(static_cast<float>(normal->width()),
static_cast<float>(normal->getHeight())); static_cast<float>(normal->height()));
} }
} }
@ -317,8 +317,8 @@ void Button::setStateBackgroundImage(
useTextureRect_ = false; useTextureRect_ = false;
if (useStateImages_ && scaleMode_ == ImageScaleMode::Original && offNormal) { if (useStateImages_ && scaleMode_ == ImageScaleMode::Original && offNormal) {
setSize(static_cast<float>(offNormal->getWidth()), setSize(static_cast<float>(offNormal->width()),
static_cast<float>(offNormal->getHeight())); static_cast<float>(offNormal->height()));
} }
} }
@ -330,8 +330,8 @@ void Button::setBackgroundImageScaleMode(ImageScaleMode mode) {
scaleMode_ = mode; scaleMode_ = mode;
if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original && if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original &&
imgNormal_) { imgNormal_) {
setSize(static_cast<float>(imgNormal_->getWidth()), setSize(static_cast<float>(imgNormal_->width()),
static_cast<float>(imgNormal_->getHeight())); static_cast<float>(imgNormal_->height()));
} }
} }
@ -408,7 +408,7 @@ Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
* @param renderer * @param renderer
* @param rect * @param rect
*/ */
void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) { void Button::drawBackgroundImage(Renderer &renderer, const Rect &rect) {
Texture *texture = nullptr; Texture *texture = nullptr;
Rect srcRect; Rect srcRect;
@ -431,28 +431,28 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
} }
} }
if (texture) { if (texture) {
srcRect = Rect(0, 0, static_cast<float>(texture->getWidth()), srcRect = Rect(0, 0, static_cast<float>(texture->width()),
static_cast<float>(texture->getHeight())); static_cast<float>(texture->height()));
} }
} else { } else {
if (pressed_ && imgPressed_) { if (pressed_ && imgPressed_) {
texture = imgPressed_.get(); texture = imgPressed_.get();
srcRect = useTextureRect_ srcRect = useTextureRect_
? imgPressedRect_ ? imgPressedRect_
: Rect(0, 0, static_cast<float>(imgPressed_->getWidth()), : Rect(0, 0, static_cast<float>(imgPressed_->width()),
static_cast<float>(imgPressed_->getHeight())); static_cast<float>(imgPressed_->height()));
} else if (hovered_ && imgHover_) { } else if (hovered_ && imgHover_) {
texture = imgHover_.get(); texture = imgHover_.get();
srcRect = useTextureRect_ srcRect = useTextureRect_
? imgHoverRect_ ? imgHoverRect_
: Rect(0, 0, static_cast<float>(imgHover_->getWidth()), : Rect(0, 0, static_cast<float>(imgHover_->width()),
static_cast<float>(imgHover_->getHeight())); static_cast<float>(imgHover_->height()));
} else if (imgNormal_) { } else if (imgNormal_) {
texture = imgNormal_.get(); texture = imgNormal_.get();
srcRect = useTextureRect_ srcRect = useTextureRect_
? imgNormalRect_ ? imgNormalRect_
: Rect(0, 0, static_cast<float>(imgNormal_->getWidth()), : Rect(0, 0, static_cast<float>(imgNormal_->width()),
static_cast<float>(imgNormal_->getHeight())); static_cast<float>(imgNormal_->height()));
} }
} }
@ -479,7 +479,7 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
* @param color * @param color
* @param radius * @param radius
*/ */
void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect, void Button::drawRoundedRect(Renderer &renderer, const Rect &rect,
const Color &color, float radius) { const Color &color, float radius) {
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f; float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
radius = std::min(radius, maxRadius); radius = std::min(radius, maxRadius);
@ -542,7 +542,7 @@ void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
* @param color * @param color
* @param radius * @param radius
*/ */
void Button::fillRoundedRect(RenderBackend &renderer, const Rect &rect, void Button::fillRoundedRect(Renderer &renderer, const Rect &rect,
const Color &color, float radius) { const Color &color, float radius) {
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f; float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
radius = std::min(radius, maxRadius); radius = std::min(radius, maxRadius);
@ -613,7 +613,7 @@ void Button::fillRoundedRect(RenderBackend &renderer, const Rect &rect,
* @brief * @brief
* @param renderer * @param renderer
*/ */
void Button::onDrawWidget(RenderBackend &renderer) { void Button::onDrawWidget(Renderer &renderer) {
Rect rect = boundingBox(); Rect rect = boundingBox();
if (rect.empty()) { if (rect.empty()) {
return; return;

View File

@ -127,7 +127,7 @@ Rect CheckBox::boundingBox() const {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void CheckBox::onDrawWidget(RenderBackend &renderer) { void CheckBox::onDrawWidget(Renderer &renderer) {
Vec2 position = pos(); Vec2 position = pos();
Rect boxRect(position.x, position.y + (size().height - boxSize_) * 0.5f, Rect boxRect(position.x, position.y + (size().height - boxSize_) * 0.5f,

View File

@ -323,7 +323,7 @@ Vec2 Label::calculateDrawPosition() const {
* @param position * @param position
* @param color * @param color
*/ */
void Label::drawText(RenderBackend &renderer, const Vec2 &position, void Label::drawText(Renderer &renderer, const Vec2 &position,
const Color &color) { const Color &color) {
if (!font_ || text_.empty()) { if (!font_ || text_.empty()) {
return; return;
@ -366,7 +366,7 @@ Rect Label::boundingBox() const {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void Label::onDrawWidget(RenderBackend &renderer) { void Label::onDrawWidget(Renderer &renderer) {
if (!font_ || text_.empty()) { if (!font_ || text_.empty()) {
return; return;
} }

View File

@ -340,7 +340,7 @@ void ProgressBar::onUpdate(float deltaTime) {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void ProgressBar::onDrawWidget(RenderBackend &renderer) { void ProgressBar::onDrawWidget(Renderer &renderer) {
Vec2 position = pos(); Vec2 position = pos();
Size widgetSize = size(); Size widgetSize = size();
@ -446,7 +446,7 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
* @param color * @param color
* @param radius * @param radius
*/ */
void ProgressBar::drawRoundedRect(RenderBackend &renderer, const Rect &rect, void ProgressBar::drawRoundedRect(Renderer &renderer, const Rect &rect,
const Color &color, float radius) { const Color &color, float radius) {
renderer.drawRect(rect, color, borderWidth_); renderer.drawRect(rect, color, borderWidth_);
} }
@ -458,7 +458,7 @@ void ProgressBar::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
* @param color * @param color
* @param radius * @param radius
*/ */
void ProgressBar::fillRoundedRect(RenderBackend &renderer, const Rect &rect, void ProgressBar::fillRoundedRect(Renderer &renderer, const Rect &rect,
const Color &color, float radius) { const Color &color, float radius) {
renderer.fillRect(rect, color); renderer.fillRect(rect, color);
} }
@ -468,7 +468,7 @@ void ProgressBar::fillRoundedRect(RenderBackend &renderer, const Rect &rect,
* @param renderer * @param renderer
* @param rect * @param rect
*/ */
void ProgressBar::drawStripes(RenderBackend &renderer, const Rect &rect) { void ProgressBar::drawStripes(Renderer &renderer, const Rect &rect) {
const float stripeWidth = 10.0f; const float stripeWidth = 10.0f;
const float spacing = 20.0f; const float spacing = 20.0f;
float rectRight = rect.origin.x + rect.size.width; float rectRight = rect.origin.x + rect.size.width;

View File

@ -128,7 +128,7 @@ Rect RadioButton::boundingBox() const {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void RadioButton::onDrawWidget(RenderBackend &renderer) { void RadioButton::onDrawWidget(Renderer &renderer) {
Vec2 position = pos(); Vec2 position = pos();
float centerX = position.x + circleSize_ * 0.5f; float centerX = position.x + circleSize_ * 0.5f;
float centerY = position.y + size().height * 0.5f; float centerY = position.y + size().height * 0.5f;

View File

@ -306,7 +306,7 @@ float Slider::snapToStep(float value) const {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void Slider::onDrawWidget(RenderBackend &renderer) { void Slider::onDrawWidget(Renderer &renderer) {
Rect trackRect = getTrackRect(); Rect trackRect = getTrackRect();
renderer.fillRect(trackRect, trackColor_); renderer.fillRect(trackRect, trackColor_);

View File

@ -234,7 +234,7 @@ Rect Text::boundingBox() const {
* @brief * @brief
* @param renderer * @param renderer
*/ */
void Text::onDrawWidget(RenderBackend &renderer) { void Text::onDrawWidget(Renderer &renderer) {
if (!font_ || text_.empty()) { if (!font_ || text_.empty()) {
return; return;
} }

View File

@ -38,6 +38,6 @@ Rect Widget::boundingBox() const {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// 重写 onDraw // 重写 onDraw
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void Widget::onDraw(RenderBackend &renderer) { onDrawWidget(renderer); } void Widget::onDraw(Renderer &renderer) { onDrawWidget(renderer); }
} // namespace extra2d } // namespace extra2d