refactor(renderer): 重构渲染器模块结构

将渲染器相关代码从graphics目录移动到renderer目录,包括Camera、Renderer等核心类
删除过渡动画相关代码,简化场景切换逻辑
移除Tween动画系统,减少代码复杂度
重命名ShapeNode为Shape,保持命名一致性
更新所有引用路径以反映新的目录结构
This commit is contained in:
ChestnutYueyue 2026-02-26 19:57:16 +08:00
parent f41600306e
commit e52c117830
52 changed files with 49 additions and 2768 deletions

View File

@ -1,73 +0,0 @@
#pragma once
#include <core/math_types.h>
#include <core/types.h>
#include <graphics/texture.h>
#include <string>
namespace extra2d {
// ============================================================================
// SpriteFrame - 精灵帧(纹理 + 区域 + 偏移的中间抽象)
// 借鉴 Cocos2d-x SpriteFrame解耦纹理物理存储与逻辑帧
// 一个纹理图集可包含多个 SpriteFrame减少纹理切换提升渲染性能
// ============================================================================
class SpriteFrame {
public:
SpriteFrame() = default;
SpriteFrame(Ptr<Texture> texture, const Rect &rect)
: texture_(std::move(texture)), rect_(rect), originalSize_(rect.size) {}
SpriteFrame(Ptr<Texture> texture, const Rect &rect, const Vec2 &offset,
const Size &originalSize)
: texture_(std::move(texture)), rect_(rect), offset_(offset),
originalSize_(originalSize) {}
// ------ 静态创建 ------
static Ptr<SpriteFrame> create(Ptr<Texture> texture, const Rect &rect) {
return makePtr<SpriteFrame>(std::move(texture), rect);
}
static Ptr<SpriteFrame> create(Ptr<Texture> texture, const Rect &rect,
const Vec2 &offset, const Size &originalSize) {
return makePtr<SpriteFrame>(std::move(texture), rect, offset, originalSize);
}
// ------ 纹理信息 ------
void setTexture(Ptr<Texture> texture) { texture_ = std::move(texture); }
Ptr<Texture> getTexture() const { return texture_; }
// ------ 矩形区域(在纹理图集中的位置)------
void setRect(const Rect &rect) { rect_ = rect; }
const Rect &getRect() const { return rect_; }
// ------ 偏移(图集打包时的裁剪偏移)------
void setOffset(const Vec2 &offset) { offset_ = offset; }
const Vec2 &getOffset() const { return offset_; }
// ------ 原始尺寸(裁剪前的完整尺寸)------
void setOriginalSize(const Size &size) { originalSize_ = size; }
const Size &getOriginalSize() const { return originalSize_; }
// ------ 旋转标志图集工具可能旋转90度------
void setRotated(bool rotated) { rotated_ = rotated; }
bool isRotated() const { return rotated_; }
// ------ 名称(用于缓存索引)------
void setName(const std::string &name) { name_ = name; }
const std::string &name() const { return name_; }
// ------ 有效性检查 ------
bool isValid() const { return texture_ != nullptr; }
private:
Ptr<Texture> texture_;
Rect rect_;
Vec2 offset_;
Size originalSize_;
bool rotated_ = false;
std::string name_;
};
} // namespace extra2d

View File

@ -1,201 +0,0 @@
#pragma once
#include <animation/sprite_frame.h>
#include <graphics/texture.h>
#include <mutex>
#include <resource/resource_manager.h>
#include <string>
#include <unordered_map>
#include <utils/logger.h>
namespace extra2d {
// ============================================================================
// SpriteFrameCache - 精灵帧全局缓存(借鉴 Cocos SpriteFrameCache
// 全局单例管理所有精灵帧,避免重复创建,支持图集自动切割
// ============================================================================
class SpriteFrameCache {
public:
static SpriteFrameCache &getInstance() {
static SpriteFrameCache instance;
return instance;
}
// ------ 添加帧 ------
/// 添加单个精灵帧
void addSpriteFrame(Ptr<SpriteFrame> frame, const std::string &name) {
std::lock_guard<std::mutex> lock(mutex_);
frames_[name] = std::move(frame);
}
/// 从纹理和矩形区域创建并添加帧
void addSpriteFrameFromTexture(Ptr<Texture> texture, const Rect &rect,
const std::string &name) {
auto frame = SpriteFrame::create(std::move(texture), rect);
frame->setName(name);
addSpriteFrame(std::move(frame), name);
}
/// 从纹理图集批量切割添加(等宽等高网格)
void addSpriteFramesFromGrid(const std::string &texturePath, int frameWidth,
int frameHeight, int frameCount = -1,
int spacing = 0, int margin = 0) {
auto texture = loadTextureFromFile(texturePath);
if (!texture)
return;
addSpriteFramesFromGrid(texture, texturePath, frameWidth, frameHeight,
frameCount, spacing, margin);
}
/// 从纹理对象批量切割添加(等宽等高网格,无需走 TexturePool
void addSpriteFramesFromGrid(Ptr<Texture> texture,
const std::string &keyPrefix, int frameWidth,
int frameHeight, int frameCount = -1,
int spacing = 0, int margin = 0) {
if (!texture)
return;
int texW = texture->width();
int texH = texture->height();
int usableW = texW - 2 * margin;
int usableH = texH - 2 * margin;
int cols = (usableW + spacing) / (frameWidth + spacing);
int rows = (usableH + spacing) / (frameHeight + spacing);
int total = (frameCount > 0) ? frameCount : cols * rows;
std::lock_guard<std::mutex> lock(mutex_);
for (int i = 0; i < total; ++i) {
int col = i % cols;
int row = i / cols;
if (row >= rows)
break;
Rect rect(static_cast<float>(margin + col * (frameWidth + spacing)),
static_cast<float>(margin + row * (frameHeight + spacing)),
static_cast<float>(frameWidth),
static_cast<float>(frameHeight));
std::string name = keyPrefix + "#" + std::to_string(i);
auto frame = SpriteFrame::create(texture, rect);
frame->setName(name);
frames_[name] = std::move(frame);
}
}
// ------ 获取帧 ------
/// 按名称获取
Ptr<SpriteFrame> getSpriteFrame(const std::string &name) const {
std::lock_guard<std::mutex> lock(mutex_);
auto it = frames_.find(name);
if (it != frames_.end())
return it->second;
return nullptr;
}
/// 通过路径+索引获取或创建ANI 格式的定位方式)
Ptr<SpriteFrame> getOrCreateFromFile(const std::string &texturePath,
int index = 0) {
std::string key = texturePath + "#" + std::to_string(index);
{
std::lock_guard<std::mutex> lock(mutex_);
auto it = frames_.find(key);
if (it != frames_.end())
return it->second;
}
// 缓存未命中,加载纹理并创建 SpriteFrame
auto texture = loadTextureFromFile(texturePath);
if (!texture)
return nullptr;
// 默认整张纹理作为一帧index=0或用整张纹理
Rect rect(0.0f, 0.0f, static_cast<float>(texture->width()),
static_cast<float>(texture->height()));
auto frame = SpriteFrame::create(texture, rect);
frame->setName(key);
std::lock_guard<std::mutex> lock(mutex_);
frames_[key] = frame;
return frame;
}
// ------ 缓存管理 ------
bool has(const std::string &name) const {
std::lock_guard<std::mutex> lock(mutex_);
return frames_.find(name) != frames_.end();
}
void removeSpriteFrame(const std::string &name) {
std::lock_guard<std::mutex> lock(mutex_);
frames_.erase(name);
}
/// 移除未被外部引用的精灵帧use_count == 1 表示仅缓存自身持有)
void removeUnusedSpriteFrames() {
std::lock_guard<std::mutex> lock(mutex_);
for (auto it = frames_.begin(); it != frames_.end();) {
if (it->second.use_count() == 1) {
it = frames_.erase(it);
} else {
++it;
}
}
}
void clear() {
std::lock_guard<std::mutex> lock(mutex_);
frames_.clear();
}
size_t count() const {
std::lock_guard<std::mutex> lock(mutex_);
return frames_.size();
}
private:
SpriteFrameCache() = default;
~SpriteFrameCache() = default;
SpriteFrameCache(const SpriteFrameCache &) = delete;
SpriteFrameCache &operator=(const SpriteFrameCache &) = delete;
/**
* @brief 使 ResourceManager LRU
* @param filepath
* @return nullptr
*/
Ptr<Texture> loadTextureFromFile(const std::string &filepath) {
// 使用 ResourceManager 的纹理缓存机制
// 这样可以享受 LRU 缓存、自动清理和缓存统计等功能
auto &resources = ResourceManager::getInstance();
// 先检查缓存中是否已有该纹理
auto texture = resources.getTexture(filepath);
if (texture) {
E2D_TRACE("SpriteFrameCache: 使用缓存纹理: {}", filepath);
return texture;
}
// 缓存未命中,通过 ResourceManager 加载
texture = resources.loadTexture(filepath);
if (!texture) {
E2D_ERROR("SpriteFrameCache: 加载纹理失败: {}", filepath);
return nullptr;
}
E2D_TRACE("SpriteFrameCache: 加载新纹理: {}", filepath);
return texture;
}
mutable std::mutex mutex_;
std::unordered_map<std::string, Ptr<SpriteFrame>> frames_;
};
// 便捷宏
#define E2D_SPRITE_FRAME_CACHE() ::extra2d::SpriteFrameCache::getInstance()
} // namespace extra2d

View File

@ -1,168 +0,0 @@
#pragma once
#include <animation/tween_easing.h>
#include <core/color.h>
#include <core/math_types.h>
#include <functional>
#include <initializer_list>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace extra2d {
class Node;
struct TweenOptions {
TweenEasing easing = TweenEasing::Linear;
std::function<void()> onStart = nullptr;
std::function<void(float progress)> onUpdate = nullptr;
std::function<void()> onComplete = nullptr;
};
struct TweenProperty {
std::optional<Vec2> position;
std::optional<Vec2> scale;
std::optional<float> rotation;
std::optional<float> opacity;
std::optional<Color> color;
};
class TweenAction {
public:
enum class Type : uint8_t {
Interval,
Delay,
Call,
Parallel,
};
virtual ~TweenAction() = default;
virtual void update(float dt) = 0;
virtual bool isFinished() const = 0;
virtual float getDuration() const = 0;
virtual float getElapsed() const = 0;
virtual void reset() = 0;
Type getType() const { return type_; }
protected:
TweenAction(Type type) : type_(type) {}
Type type_;
};
class Tween {
public:
using Ptr = std::shared_ptr<Tween>;
using Callback = std::function<void()>;
explicit Tween(Node *target);
Tween(Node *target, const std::string &name);
~Tween();
Tween(const Tween &) = delete;
Tween &operator=(const Tween &) = delete;
Tween(Tween &&) = default;
Tween &operator=(Tween &&) = default;
static Tween create(Node *target);
static Tween create(Node *target, const std::string &name);
Tween &to(float duration, const TweenProperty &props,
const TweenOptions &options = {});
Tween &by(float duration, const TweenProperty &props,
const TweenOptions &options = {});
Tween &set(const TweenProperty &props);
Tween &delay(float seconds);
Tween &call(Callback callback);
Tween &parallel();
Tween &endParallel();
Tween &union_();
Tween &repeat(int times);
Tween &repeatForever();
Tween &yoyo(bool enabled = true);
void start();
void stop();
void pause();
void resume();
void update(float dt);
bool isFinished() const;
bool isPlaying() const;
bool isPaused() const;
float getTotalDuration() const;
void setName(const std::string &name) { name_ = name; }
const std::string &name() const { return name_; }
private:
Node *target_ = nullptr;
std::string name_;
std::vector<std::unique_ptr<TweenAction>> actions_;
size_t currentActionIndex_ = 0;
bool playing_ = false;
bool paused_ = false;
bool finished_ = false;
int repeatCount_ = 1;
int currentRepeat_ = 0;
bool yoyo_ = false;
bool reverse_ = false;
bool repeatForever_ = false;
bool inParallel_ = false;
std::vector<std::unique_ptr<TweenAction>> parallelActions_;
void addAction(std::unique_ptr<TweenAction> action);
void advanceToNextAction();
void resetAllActions();
};
namespace tween {
inline TweenProperty pos(const Vec2 &p) {
TweenProperty props;
props.position = p;
return props;
}
inline TweenProperty pos(float x, float y) { return pos(Vec2(x, y)); }
inline TweenProperty scl(const Vec2 &s) {
TweenProperty props;
props.scale = s;
return props;
}
inline TweenProperty scl(float s) { return scl(Vec2(s, s)); }
inline TweenProperty rot(float degrees) {
TweenProperty props;
props.rotation = degrees;
return props;
}
inline TweenProperty opa(float opacity) {
TweenProperty props;
props.opacity = opacity;
return props;
}
inline TweenProperty col(const Color &c) {
TweenProperty props;
props.color = c;
return props;
}
TweenProperty combine(std::initializer_list<TweenProperty> props);
} // namespace tween
} // namespace extra2d

View File

@ -1,91 +0,0 @@
#pragma once
#include <cstdint>
namespace extra2d {
enum class TweenEasing : uint8_t {
Linear,
QuadIn,
QuadOut,
QuadInOut,
CubicIn,
CubicOut,
CubicInOut,
QuartIn,
QuartOut,
QuartInOut,
QuintIn,
QuintOut,
QuintInOut,
SineIn,
SineOut,
SineInOut,
ExpoIn,
ExpoOut,
ExpoInOut,
CircIn,
CircOut,
CircInOut,
ElasticIn,
ElasticOut,
ElasticInOut,
BackIn,
BackOut,
BackInOut,
BounceIn,
BounceOut,
BounceInOut,
Smooth,
Fade,
};
class EasingFunctions {
public:
using EasingFunc = float (*)(float);
static float apply(float t, TweenEasing easing);
static EasingFunc get(TweenEasing easing);
static float linear(float t);
static float quadIn(float t);
static float quadOut(float t);
static float quadInOut(float t);
static float cubicIn(float t);
static float cubicOut(float t);
static float cubicInOut(float t);
static float quartIn(float t);
static float quartOut(float t);
static float quartInOut(float t);
static float quintIn(float t);
static float quintOut(float t);
static float quintInOut(float t);
static float sineIn(float t);
static float sineOut(float t);
static float sineInOut(float t);
static float expoIn(float t);
static float expoOut(float t);
static float expoInOut(float t);
static float circIn(float t);
static float circOut(float t);
static float circInOut(float t);
static float elasticIn(float t);
static float elasticOut(float t);
static float elasticInOut(float t);
static float backIn(float t);
static float backOut(float t);
static float backInOut(float t);
static float bounceIn(float t);
static float bounceOut(float t);
static float bounceInOut(float t);
static float smooth(float t);
static float fade(float t);
private:
static constexpr float PI = 3.14159265358979323846f;
static constexpr float HALF_PI = 1.57079632679489661923f;
static constexpr float BACK_CONST = 1.70158f;
static constexpr float ELASTIC_CONST = 2.0f * PI / 3.0f;
};
} // namespace extra2d

View File

@ -2,7 +2,7 @@
#include <core/string.h>
#include <core/types.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <memory>
#include <platform/window.h>
@ -86,8 +86,6 @@ public:
// 便捷方法
// ------------------------------------------------------------------------
void enterScene(Ptr<class Scene> scene);
void enterScene(Ptr<class Scene> scene,
Ptr<class TransitionScene> transitionScene);
float deltaTime() const { return deltaTime_; }
float totalTime() const { return totalTime_; }

View File

@ -14,33 +14,23 @@
#include <platform/window.h>
// Graphics
#include <graphics/camera.h>
#include <graphics/font.h>
#include <graphics/renderer.h>
#include <graphics/shader_system.h>
#include <graphics/texture.h>
#include <graphics/render_target.h>
#include <graphics/vram_manager.h>
// Renderer
#include <renderer/camera.h>
#include <renderer/render_target.h>
#include <renderer/renderer.h>
#include <renderer/shader_system.h>
// Scene
#include <scene/node.h>
#include <scene/scene.h>
#include <scene/scene_manager.h>
#include <scene/shape_node.h>
#include <scene/shape.h>
#include <scene/sprite.h>
#include <scene/transition_box_scene.h>
#include <scene/transition_fade_scene.h>
#include <scene/transition_flip_scene.h>
#include <scene/transition_scale_scene.h>
#include <scene/transition_scene.h>
#include <scene/transition_slide_scene.h>
// Animation
#include <animation/sprite_frame.h>
#include <animation/sprite_frame_cache.h>
#include <animation/tween.h>
#include <animation/tween_easing.h>
// UI
#include <ui/button.h>

View File

@ -2,7 +2,7 @@
#include <graphics/opengl/gl_shader.h>
#include <graphics/opengl/gl_sprite_batch.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <array>
#include <glad/glad.h>

View File

@ -6,7 +6,7 @@
#include <core/types.h>
#include <event/event_dispatcher.h>
#include <functional>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <memory>
#include <string>
#include <vector>
@ -17,8 +17,6 @@ namespace extra2d {
class Scene;
class Renderer;
struct RenderCommand;
class Tween;
enum class TweenEasing : uint8_t;
// ============================================================================
// 节点基类 - 场景图的基础
@ -155,85 +153,6 @@ public:
// ------------------------------------------------------------------------
EventDispatcher &getEventDispatcher() { return eventDispatcher_; }
// ------------------------------------------------------------------------
// Tween 动画系统
// ------------------------------------------------------------------------
/**
* @brief Tween
* @return Tween
*/
Tween &tween();
/**
* @brief Tween
*/
Tween &tween(const std::string &name);
/**
* @brief
*/
Tween &moveTo(const Vec2 &pos, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &moveBy(const Vec2 &delta, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &scaleTo(float scale, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &scaleBy(float delta, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &rotateTo(float degrees, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &rotateBy(float degrees, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief 1
*/
Tween &fadeIn(float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief 0
*/
Tween &fadeOut(float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &fadeTo(float opacity, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief Tween
*/
void stopAllTweens();
/**
* @brief Tween
*/
void updateTweens(float dt);
// ------------------------------------------------------------------------
// 内部方法
// ------------------------------------------------------------------------
@ -318,8 +237,7 @@ private:
bool visible_ = true; // 1 byte
bool running_ = false; // 1 byte
// 10. Tween 动画列表
std::vector<std::shared_ptr<Tween>> tweens_;
};
} // namespace extra2d

View File

@ -1,7 +1,7 @@
#pragma once
#include <core/color.h>
#include <graphics/camera.h>
#include <renderer/camera.h>
#include <scene/node.h>
#include <vector>
@ -69,12 +69,7 @@ protected:
void onEnter() override;
void onExit() override;
// 过渡场景生命周期回调(供 TransitionScene 使用)
virtual void onExitTransitionDidStart() {}
virtual void onEnterTransitionDidFinish() {}
friend class SceneManager;
friend class TransitionScene;
private:
Color backgroundColor_ = Colors::Black;

View File

@ -3,7 +3,6 @@
#include <core/types.h>
#include <functional>
#include <scene/scene.h>
#include <scene/transition_scene.h>
#include <stack>
#include <string>
#include <unordered_map>
@ -14,15 +13,12 @@ namespace extra2d {
// 前向声明
struct RenderCommand;
class TransitionScene;
// ============================================================================
// 场景管理器 - 管理场景的生命周期和切换
// ============================================================================
class SceneManager {
public:
using TransitionCallback = std::function<void()>;
// ------------------------------------------------------------------------
// 单例访问
// ------------------------------------------------------------------------
@ -37,26 +33,18 @@ public:
// 替换当前场景
void replaceScene(Ptr<Scene> scene);
void replaceScene(Ptr<Scene> scene, TransitionType transition,
float duration = 0.5f);
// 压入新场景(当前场景暂停)
void pushScene(Ptr<Scene> scene);
void pushScene(Ptr<Scene> scene, TransitionType transition,
float duration = 0.5f);
// 弹出当前场景(恢复上一个场景)
void popScene();
void popScene(TransitionType transition, float duration = 0.5f);
// 弹出到根场景
void popToRootScene();
void popToRootScene(TransitionType transition, float duration = 0.5f);
// 弹出到指定场景
void popToScene(const std::string &name);
void popToScene(const std::string &name, TransitionType transition,
float duration = 0.5f);
// ------------------------------------------------------------------------
// 获取场景
@ -82,14 +70,6 @@ public:
void render(Renderer &renderer);
void collectRenderCommands(std::vector<RenderCommand> &commands);
// ------------------------------------------------------------------------
// 过渡控制
// ------------------------------------------------------------------------
bool isTransitioning() const { return isTransitioning_; }
void setTransitionCallback(TransitionCallback callback) {
transitionCallback_ = callback;
}
// ------------------------------------------------------------------------
// 清理
// ------------------------------------------------------------------------
@ -104,30 +84,14 @@ public:
// 场景切换(供 Application 使用)
void enterScene(Ptr<Scene> scene);
void enterScene(Ptr<Scene> scene, Ptr<TransitionScene> transitionScene);
private:
void doSceneSwitch();
void startTransition(Ptr<Scene> from, Ptr<Scene> to, TransitionType type,
float duration, Function<void()> stackAction);
void finishTransition();
void dispatchPointerEvents(Scene &scene);
// 创建过渡场景
Ptr<TransitionScene> createTransitionScene(TransitionType type,
float duration,
Ptr<Scene> inScene);
std::stack<Ptr<Scene>> sceneStack_;
std::unordered_map<std::string, Ptr<Scene>> namedScenes_;
// Transition state
bool isTransitioning_ = false;
TransitionType currentTransition_ = TransitionType::None;
Ptr<TransitionScene> activeTransitionScene_;
Function<void()> transitionStackAction_;
TransitionCallback transitionCallback_;
// Next scene to switch to (queued during transition)
Ptr<Scene> nextScene_;
bool sendCleanupToScene_ = false;

View File

@ -1,34 +0,0 @@
#pragma once
#include <scene/transition_scene.h>
namespace extra2d {
// ============================================================================
// 方块/马赛克过渡场景
// 实现原理:
// 1. 将屏幕分成多个方块
// 2. 方块逐个消失,显示新场景
// ============================================================================
class TransitionBoxScene : public TransitionScene {
public:
/**
* @brief
* @param duration
* @param inScene
* @param divisions 8 8x8
*/
TransitionBoxScene(float duration, Ptr<Scene> inScene, int divisions = 8);
static Ptr<TransitionBoxScene> create(float duration, Ptr<Scene> inScene,
int divisions = 8);
protected:
void onTransitionStart() override;
void renderContent(Renderer &renderer) override;
private:
int divisions_;
};
} // namespace extra2d

View File

@ -1,55 +0,0 @@
#pragma once
#include <core/color.h>
#include <scene/sprite.h>
#include <scene/transition_scene.h>
namespace extra2d {
// ============================================================================
// 淡入淡出过渡场景
// 实现原理:
// 1. 创建一个纯色精灵作为遮罩层
// 2. 第一阶段:遮罩从透明淡入到不透明(黑屏),同时显示旧场景
// 3. 切换显示新场景
// 4. 第二阶段:遮罩从不透明淡出到透明,显示新场景
// ============================================================================
class TransitionFadeScene : public TransitionScene {
public:
/**
* @brief
* @param duration
* @param inScene
* @param color
*/
TransitionFadeScene(float duration, Ptr<Scene> inScene,
const Color &color = Colors::Black);
static Ptr<TransitionFadeScene> create(float duration, Ptr<Scene> inScene,
const Color &color = Colors::Black);
protected:
/**
* @brief
*
*/
void onTransitionStart() override;
/**
* @brief
*
*/
void renderContent(Renderer &renderer) override;
private:
/**
* @brief 退
*/
void hideOutShowIn();
Color maskColor_; // 遮罩颜色
bool hasSwitched_ = false; // 是否已经切换场景
};
} // namespace extra2d

View File

@ -1,37 +0,0 @@
#pragma once
#include <scene/transition_scene.h>
namespace extra2d {
// ============================================================================
// 翻页过渡场景
// 实现原理:
// 1. 前半段:旧场景翻转消失
// 2. 后半段:新场景翻转出现
// ============================================================================
class TransitionFlipScene : public TransitionScene {
public:
enum class Axis { Horizontal, Vertical };
/**
* @brief
* @param duration
* @param inScene
* @param axis
*/
TransitionFlipScene(float duration, Ptr<Scene> inScene,
Axis axis = Axis::Horizontal);
static Ptr<TransitionFlipScene> create(float duration, Ptr<Scene> inScene,
Axis axis = Axis::Horizontal);
protected:
void onTransitionStart() override;
void renderContent(Renderer &renderer) override;
private:
Axis axis_;
};
} // namespace extra2d

View File

@ -1,29 +0,0 @@
#pragma once
#include <scene/transition_scene.h>
namespace extra2d {
// ============================================================================
// 缩放过渡场景
// 实现原理:
// 1. 旧场景缩小消失
// 2. 新场景放大出现
// ============================================================================
class TransitionScaleScene : public TransitionScene {
public:
/**
* @brief
* @param duration
* @param inScene
*/
TransitionScaleScene(float duration, Ptr<Scene> inScene);
static Ptr<TransitionScaleScene> create(float duration, Ptr<Scene> inScene);
protected:
void onTransitionStart() override;
void renderContent(Renderer &renderer) override;
};
} // namespace extra2d

View File

@ -1,130 +0,0 @@
#pragma once
#include <functional>
#include <scene/scene.h>
namespace extra2d {
// ============================================================================
// 过渡方向
// ============================================================================
enum class TransitionDirection { Left, Right, Up, Down };
// ============================================================================
// 过渡效果类型
// ============================================================================
enum class TransitionType {
None,
Fade,
SlideLeft,
SlideRight,
SlideUp,
SlideDown,
Scale,
Flip,
Box
};
// ============================================================================
// 过渡场景基类 - 继承自 Scene作为中介场景管理过渡效果
// 设计参考 Cocos2d-x 的 TransitionScene
// ============================================================================
class TransitionScene : public Scene {
public:
using FinishCallback = std::function<void()>;
/**
* @brief
* @param duration
* @param inScene
*/
TransitionScene(float duration, Ptr<Scene> inScene);
~TransitionScene() override = default;
// ------------------------------------------------------------------------
// 场景管理
// ------------------------------------------------------------------------
/**
* @brief
*/
Ptr<Scene> getInScene() const { return inScene_; }
/**
* @brief 退
*/
Ptr<Scene> getOutScene() const { return outScene_; }
/**
* @brief 退 SceneManager
*/
void setOutScene(Ptr<Scene> outScene) { outScene_ = outScene; }
/**
* @brief
*/
void setFinishCallback(FinishCallback callback) {
finishCallback_ = callback;
}
/**
* @brief
*/
float getDuration() const { return duration_; }
/**
* @brief [0, 1]
*/
float getProgress() const { return progress_; }
/**
* @brief
*/
bool isFinished() const { return isFinished_; }
/**
* @brief SceneManager
*/
void finish();
// ------------------------------------------------------------------------
// 渲染 - 在 TransitionScene 上渲染新旧两个子场景
// ------------------------------------------------------------------------
void renderContent(Renderer &renderer) override;
// ------------------------------------------------------------------------
// 生命周期
// ------------------------------------------------------------------------
void onEnter() override;
void onExit() override;
protected:
/**
* @brief
* onEnter finish()
*/
virtual void onTransitionStart() = 0;
/**
* @brief
*/
virtual void drawOutScene(Renderer &renderer);
/**
* @brief
*/
virtual void drawInScene(Renderer &renderer);
float duration_;
float elapsed_ = 0.0f;
float progress_ = 0.0f;
bool isFinished_ = false;
Ptr<Scene> inScene_; // 要进入的场景
Ptr<Scene> outScene_; // 要退出的场景
FinishCallback finishCallback_;
};
} // namespace extra2d

View File

@ -1,35 +0,0 @@
#pragma once
#include <scene/transition_scene.h>
namespace extra2d {
// ============================================================================
// 滑动过渡场景
// 实现原理:
// 1. 旧场景向指定方向滑出
// 2. 新场景从相反方向滑入
// ============================================================================
class TransitionSlideScene : public TransitionScene {
public:
/**
* @brief
* @param duration
* @param inScene
* @param direction
*/
TransitionSlideScene(float duration, Ptr<Scene> inScene,
TransitionDirection direction);
static Ptr<TransitionSlideScene> create(float duration, Ptr<Scene> inScene,
TransitionDirection direction);
protected:
void onTransitionStart() override;
void renderContent(Renderer &renderer) override;
private:
TransitionDirection direction_;
};
} // namespace extra2d

View File

@ -1,8 +0,0 @@
#include <animation/sprite_frame.h>
namespace extra2d {
// SpriteFrame 的实现全部在头文件中以内联方式完成
// 此文件保留用于未来可能需要的非内联实现
} // namespace extra2d

View File

@ -1,8 +0,0 @@
#include <animation/sprite_frame_cache.h>
namespace extra2d {
// SpriteFrameCache 的实现全部在头文件中以内联方式完成
// 此文件保留用于未来可能需要的非内联实现
} // namespace extra2d

View File

@ -1,451 +0,0 @@
#include <animation/tween.h>
#include <scene/node.h>
#include <algorithm>
#include <cmath>
namespace extra2d {
class IntervalAction : public TweenAction {
public:
IntervalAction(Node *target, float duration, const TweenProperty &props,
const TweenOptions &options, bool isRelative)
: TweenAction(Type::Interval), target_(target), duration_(duration),
props_(props), options_(options), isRelative_(isRelative) {}
void update(float dt) override {
if (finished_)
return;
elapsed_ += dt;
float t = std::min(elapsed_ / duration_, 1.0f);
float easedT = EasingFunctions::apply(t, options_.easing);
applyProperties(easedT);
if (options_.onUpdate) {
options_.onUpdate(t);
}
if (t >= 1.0f) {
finished_ = true;
if (options_.onComplete) {
options_.onComplete();
}
}
}
bool isFinished() const override { return finished_; }
float getDuration() const override { return duration_; }
float getElapsed() const override { return elapsed_; }
void reset() override {
elapsed_ = 0.0f;
finished_ = false;
started_ = false;
}
void captureStartValues() {
if (started_)
return;
started_ = true;
if (target_) {
startPos_ = target_->pos();
startScale_ = target_->scale();
startRotation_ = target_->rot();
startOpacity_ = target_->opacity();
}
}
private:
Node *target_;
float duration_;
TweenProperty props_;
TweenOptions options_;
bool isRelative_;
bool started_ = false;
float elapsed_ = 0.0f;
bool finished_ = false;
Vec2 startPos_;
Vec2 startScale_;
float startRotation_ = 0.0f;
float startOpacity_ = 1.0f;
void applyProperties(float t) {
if (!target_)
return;
if (props_.position.has_value()) {
Vec2 targetPos = isRelative_ ? startPos_ + props_.position.value()
: props_.position.value();
Vec2 newPos = Vec2::lerp(startPos_, targetPos, t);
target_->setPosition(newPos);
}
if (props_.scale.has_value()) {
Vec2 targetScale =
isRelative_ ? startScale_ + props_.scale.value()
: props_.scale.value();
Vec2 newScale = Vec2::lerp(startScale_, targetScale, t);
target_->setScale(newScale);
}
if (props_.rotation.has_value()) {
float targetRot = isRelative_ ? startRotation_ + props_.rotation.value()
: props_.rotation.value();
float newRot = startRotation_ + (targetRot - startRotation_) * t;
target_->setRotation(newRot);
}
if (props_.opacity.has_value()) {
float targetOpa = isRelative_ ? startOpacity_ + props_.opacity.value()
: props_.opacity.value();
float newOpa = startOpacity_ + (targetOpa - startOpacity_) * t;
target_->setOpacity(newOpa);
}
}
};
class DelayAction : public TweenAction {
public:
DelayAction(float duration)
: TweenAction(Type::Delay), duration_(duration) {}
void update(float dt) override {
elapsed_ += dt;
finished_ = elapsed_ >= duration_;
}
bool isFinished() const override { return finished_; }
float getDuration() const override { return duration_; }
float getElapsed() const override { return elapsed_; }
void reset() override {
elapsed_ = 0.0f;
finished_ = false;
}
private:
float duration_;
float elapsed_ = 0.0f;
bool finished_ = false;
};
class CallAction : public TweenAction {
public:
CallAction(std::function<void()> callback)
: TweenAction(Type::Call), callback_(std::move(callback)) {}
void update(float) override {
if (!called_) {
if (callback_) {
callback_();
}
called_ = true;
}
finished_ = true;
}
bool isFinished() const override { return finished_; }
float getDuration() const override { return 0.0f; }
float getElapsed() const override { return 0.0f; }
void reset() override {
called_ = false;
finished_ = false;
}
private:
std::function<void()> callback_;
bool called_ = false;
bool finished_ = false;
};
class SetAction : public TweenAction {
public:
SetAction(Node *target, const TweenProperty &props)
: TweenAction(Type::Call), target_(target), props_(props) {}
void update(float) override {
if (!applied_ && target_) {
if (props_.position.has_value())
target_->setPosition(props_.position.value());
if (props_.scale.has_value())
target_->setScale(props_.scale.value());
if (props_.rotation.has_value())
target_->setRotation(props_.rotation.value());
if (props_.opacity.has_value())
target_->setOpacity(props_.opacity.value());
applied_ = true;
}
finished_ = true;
}
bool isFinished() const override { return finished_; }
float getDuration() const override { return 0.0f; }
float getElapsed() const override { return 0.0f; }
void reset() override {
applied_ = false;
finished_ = false;
}
private:
Node *target_;
TweenProperty props_;
bool applied_ = false;
bool finished_ = false;
};
class ParallelAction : public TweenAction {
public:
ParallelAction() : TweenAction(Type::Parallel) {}
void addAction(std::unique_ptr<TweenAction> action) {
actions_.push_back(std::move(action));
}
void update(float dt) override {
if (finished_)
return;
bool allFinished = true;
for (auto &action : actions_) {
if (!action->isFinished()) {
action->update(dt);
allFinished = false;
}
}
finished_ = allFinished;
}
bool isFinished() const override { return finished_; }
float getDuration() const override {
float maxDur = 0.0f;
for (const auto &action : actions_) {
maxDur = std::max(maxDur, action->getDuration());
}
return maxDur;
}
float getElapsed() const override {
float maxElapsed = 0.0f;
for (const auto &action : actions_) {
maxElapsed = std::max(maxElapsed, action->getElapsed());
}
return maxElapsed;
}
void reset() override {
for (auto &action : actions_) {
action->reset();
}
finished_ = false;
}
private:
std::vector<std::unique_ptr<TweenAction>> actions_;
bool finished_ = false;
};
Tween::Tween(Node *target) : target_(target) {}
Tween::Tween(Node *target, const std::string &name)
: target_(target), name_(name) {}
Tween::~Tween() = default;
Tween Tween::create(Node *target) { return Tween(target); }
Tween Tween::create(Node *target, const std::string &name) {
return Tween(target, name);
}
Tween &Tween::to(float duration, const TweenProperty &props,
const TweenOptions &options) {
auto action =
std::make_unique<IntervalAction>(target_, duration, props, options, false);
addAction(std::move(action));
return *this;
}
Tween &Tween::by(float duration, const TweenProperty &props,
const TweenOptions &options) {
auto action =
std::make_unique<IntervalAction>(target_, duration, props, options, true);
addAction(std::move(action));
return *this;
}
Tween &Tween::set(const TweenProperty &props) {
auto action = std::make_unique<SetAction>(target_, props);
addAction(std::move(action));
return *this;
}
Tween &Tween::delay(float seconds) {
auto action = std::make_unique<DelayAction>(seconds);
addAction(std::move(action));
return *this;
}
Tween &Tween::call(Callback callback) {
auto action = std::make_unique<CallAction>(std::move(callback));
addAction(std::move(action));
return *this;
}
Tween &Tween::parallel() {
inParallel_ = true;
parallelActions_.clear();
return *this;
}
Tween &Tween::endParallel() {
if (inParallel_ && !parallelActions_.empty()) {
auto parallel = std::make_unique<ParallelAction>();
for (auto &action : parallelActions_) {
parallel->addAction(std::move(action));
}
actions_.push_back(std::move(parallel));
parallelActions_.clear();
}
inParallel_ = false;
return *this;
}
Tween &Tween::union_() { return *this; }
Tween &Tween::repeat(int times) {
repeatCount_ = times;
return *this;
}
Tween &Tween::repeatForever() {
repeatForever_ = true;
return *this;
}
Tween &Tween::yoyo(bool enabled) {
yoyo_ = enabled;
return *this;
}
void Tween::start() {
if (actions_.empty())
return;
playing_ = true;
paused_ = false;
finished_ = false;
currentActionIndex_ = 0;
currentRepeat_ = 0;
for (auto &action : actions_) {
action->reset();
}
if (auto *interval =
dynamic_cast<IntervalAction *>(actions_[0].get())) {
interval->captureStartValues();
}
}
void Tween::stop() {
playing_ = false;
finished_ = true;
}
void Tween::pause() { paused_ = true; }
void Tween::resume() { paused_ = false; }
void Tween::update(float dt) {
if (!playing_ || paused_ || finished_)
return;
if (currentActionIndex_ >= actions_.size()) {
if (repeatForever_ || currentRepeat_ < repeatCount_ - 1) {
currentRepeat_++;
resetAllActions();
currentActionIndex_ = 0;
if (yoyo_) {
reverse_ = !reverse_;
}
} else {
finished_ = true;
playing_ = false;
return;
}
}
auto &action = actions_[currentActionIndex_];
action->update(dt);
if (action->isFinished()) {
currentActionIndex_++;
if (currentActionIndex_ < actions_.size()) {
actions_[currentActionIndex_]->reset();
if (auto *interval = dynamic_cast<IntervalAction *>(
actions_[currentActionIndex_].get())) {
interval->captureStartValues();
}
}
}
}
bool Tween::isFinished() const { return finished_; }
bool Tween::isPlaying() const { return playing_; }
bool Tween::isPaused() const { return paused_; }
float Tween::getTotalDuration() const {
float total = 0.0f;
for (const auto &action : actions_) {
total += action->getDuration();
}
return total;
}
void Tween::addAction(std::unique_ptr<TweenAction> action) {
if (inParallel_) {
parallelActions_.push_back(std::move(action));
} else {
actions_.push_back(std::move(action));
}
}
void Tween::advanceToNextAction() {
currentActionIndex_++;
if (currentActionIndex_ < actions_.size()) {
actions_[currentActionIndex_]->reset();
}
}
void Tween::resetAllActions() {
for (auto &action : actions_) {
action->reset();
}
}
namespace tween {
TweenProperty combine(std::initializer_list<TweenProperty> props) {
TweenProperty result;
for (const auto &p : props) {
if (p.position.has_value())
result.position = p.position;
if (p.scale.has_value())
result.scale = p.scale;
if (p.rotation.has_value())
result.rotation = p.rotation;
if (p.opacity.has_value())
result.opacity = p.opacity;
if (p.color.has_value())
result.color = p.color;
}
return result;
}
} // namespace tween
} // namespace extra2d

View File

@ -1,236 +0,0 @@
#include <animation/tween_easing.h>
#include <cmath>
namespace extra2d {
float EasingFunctions::apply(float t, TweenEasing easing) {
return get(easing)(t);
}
EasingFunctions::EasingFunc EasingFunctions::get(TweenEasing easing) {
switch (easing) {
case TweenEasing::Linear: return linear;
case TweenEasing::QuadIn: return quadIn;
case TweenEasing::QuadOut: return quadOut;
case TweenEasing::QuadInOut: return quadInOut;
case TweenEasing::CubicIn: return cubicIn;
case TweenEasing::CubicOut: return cubicOut;
case TweenEasing::CubicInOut: return cubicInOut;
case TweenEasing::QuartIn: return quartIn;
case TweenEasing::QuartOut: return quartOut;
case TweenEasing::QuartInOut: return quartInOut;
case TweenEasing::QuintIn: return quintIn;
case TweenEasing::QuintOut: return quintOut;
case TweenEasing::QuintInOut: return quintInOut;
case TweenEasing::SineIn: return sineIn;
case TweenEasing::SineOut: return sineOut;
case TweenEasing::SineInOut: return sineInOut;
case TweenEasing::ExpoIn: return expoIn;
case TweenEasing::ExpoOut: return expoOut;
case TweenEasing::ExpoInOut: return expoInOut;
case TweenEasing::CircIn: return circIn;
case TweenEasing::CircOut: return circOut;
case TweenEasing::CircInOut: return circInOut;
case TweenEasing::ElasticIn: return elasticIn;
case TweenEasing::ElasticOut: return elasticOut;
case TweenEasing::ElasticInOut: return elasticInOut;
case TweenEasing::BackIn: return backIn;
case TweenEasing::BackOut: return backOut;
case TweenEasing::BackInOut: return backInOut;
case TweenEasing::BounceIn: return bounceIn;
case TweenEasing::BounceOut: return bounceOut;
case TweenEasing::BounceInOut: return bounceInOut;
case TweenEasing::Smooth: return smooth;
case TweenEasing::Fade: return fade;
default: return linear;
}
}
float EasingFunctions::linear(float t) {
return t;
}
float EasingFunctions::quadIn(float t) {
return t * t;
}
float EasingFunctions::quadOut(float t) {
return t * (2.0f - t);
}
float EasingFunctions::quadInOut(float t) {
if (t < 0.5f) {
return 2.0f * t * t;
}
return -1.0f + (4.0f - 2.0f * t) * t;
}
float EasingFunctions::cubicIn(float t) {
return t * t * t;
}
float EasingFunctions::cubicOut(float t) {
float t1 = t - 1.0f;
return t1 * t1 * t1 + 1.0f;
}
float EasingFunctions::cubicInOut(float t) {
if (t < 0.5f) {
return 4.0f * t * t * t;
}
float t1 = 2.0f * t - 2.0f;
return 0.5f * t1 * t1 * t1 + 1.0f;
}
float EasingFunctions::quartIn(float t) {
return t * t * t * t;
}
float EasingFunctions::quartOut(float t) {
float t1 = t - 1.0f;
return 1.0f - t1 * t1 * t1 * t1;
}
float EasingFunctions::quartInOut(float t) {
if (t < 0.5f) {
return 8.0f * t * t * t * t;
}
float t1 = t - 1.0f;
return 1.0f - 8.0f * t1 * t1 * t1 * t1;
}
float EasingFunctions::quintIn(float t) {
return t * t * t * t * t;
}
float EasingFunctions::quintOut(float t) {
float t1 = t - 1.0f;
return t1 * t1 * t1 * t1 * t1 + 1.0f;
}
float EasingFunctions::quintInOut(float t) {
if (t < 0.5f) {
return 16.0f * t * t * t * t * t;
}
float t1 = 2.0f * t - 2.0f;
return 0.5f * t1 * t1 * t1 * t1 * t1 + 1.0f;
}
float EasingFunctions::sineIn(float t) {
return 1.0f - std::cos(t * HALF_PI);
}
float EasingFunctions::sineOut(float t) {
return std::sin(t * HALF_PI);
}
float EasingFunctions::sineInOut(float t) {
return -0.5f * (std::cos(PI * t) - 1.0f);
}
float EasingFunctions::expoIn(float t) {
return t == 0.0f ? 0.0f : std::pow(2.0f, 10.0f * (t - 1.0f));
}
float EasingFunctions::expoOut(float t) {
return t == 1.0f ? 1.0f : 1.0f - std::pow(2.0f, -10.0f * t);
}
float EasingFunctions::expoInOut(float t) {
if (t == 0.0f) return 0.0f;
if (t == 1.0f) return 1.0f;
if (t < 0.5f) {
return 0.5f * std::pow(2.0f, 20.0f * t - 10.0f);
}
return 1.0f - 0.5f * std::pow(2.0f, -20.0f * t + 10.0f);
}
float EasingFunctions::circIn(float t) {
return 1.0f - std::sqrt(1.0f - t * t);
}
float EasingFunctions::circOut(float t) {
return std::sqrt(2.0f * t - t * t);
}
float EasingFunctions::circInOut(float t) {
if (t < 0.5f) {
return 0.5f * (1.0f - std::sqrt(1.0f - 4.0f * t * t));
}
return 0.5f * (std::sqrt(4.0f * t - 4.0f * t * t - 3.0f) + 1.0f);
}
float EasingFunctions::elasticIn(float t) {
if (t == 0.0f) return 0.0f;
if (t == 1.0f) return 1.0f;
return -std::pow(2.0f, 10.0f * (t - 1.0f)) * std::sin((t - 1.1f) * ELASTIC_CONST);
}
float EasingFunctions::elasticOut(float t) {
if (t == 0.0f) return 0.0f;
if (t == 1.0f) return 1.0f;
return std::pow(2.0f, -10.0f * t) * std::sin((t - 0.1f) * ELASTIC_CONST) + 1.0f;
}
float EasingFunctions::elasticInOut(float t) {
if (t == 0.0f) return 0.0f;
if (t == 1.0f) return 1.0f;
if (t < 0.5f) {
return -0.5f * std::pow(2.0f, 20.0f * t - 10.0f) * std::sin((20.0f * t - 11.125f) * PI / 4.5f);
}
return std::pow(2.0f, -20.0f * t + 10.0f) * std::sin((20.0f * t - 11.125f) * PI / 4.5f) * 0.5f + 1.0f;
}
float EasingFunctions::backIn(float t) {
return t * t * ((BACK_CONST + 1.0f) * t - BACK_CONST);
}
float EasingFunctions::backOut(float t) {
float t1 = t - 1.0f;
return t1 * t1 * ((BACK_CONST + 1.0f) * t1 + BACK_CONST) + 1.0f;
}
float EasingFunctions::backInOut(float t) {
float s = BACK_CONST * 1.525f;
if (t < 0.5f) {
return 0.5f * (t * 2.0f) * (t * 2.0f) * ((s + 1.0f) * 2.0f * t - s);
}
float t1 = 2.0f * t - 2.0f;
return 0.5f * (t1 * t1 * ((s + 1.0f) * t1 + s) + 2.0f);
}
float EasingFunctions::bounceIn(float t) {
return 1.0f - bounceOut(1.0f - t);
}
float EasingFunctions::bounceOut(float t) {
if (t < 1.0f / 2.75f) {
return 7.5625f * t * t;
} else if (t < 2.0f / 2.75f) {
float t1 = t - 1.5f / 2.75f;
return 7.5625f * t1 * t1 + 0.75f;
} else if (t < 2.5f / 2.75f) {
float t1 = t - 2.25f / 2.75f;
return 7.5625f * t1 * t1 + 0.9375f;
} else {
float t1 = t - 2.625f / 2.75f;
return 7.5625f * t1 * t1 + 0.984375f;
}
}
float EasingFunctions::bounceInOut(float t) {
if (t < 0.5f) {
return 0.5f * bounceIn(t * 2.0f);
}
return 0.5f * bounceOut(t * 2.0f - 1.0f) + 0.5f;
}
float EasingFunctions::smooth(float t) {
return t * t * (3.0f - 2.0f * t);
}
float EasingFunctions::fade(float t) {
return t * t * t * (t * (6.0f * t - 15.0f) + 10.0f);
}
} // namespace extra2d

View File

@ -2,8 +2,8 @@
#include <audio/audio_engine.h>
#include <event/event_dispatcher.h>
#include <event/event_queue.h>
#include <graphics/camera.h>
#include <graphics/renderer.h>
#include <renderer/camera.h>
#include <renderer/renderer.h>
#include <graphics/vram_manager.h>
#include <platform/input.h>
#include <platform/window.h>
@ -382,14 +382,11 @@ EventDispatcher &Application::eventDispatcher() { return *eventDispatcher_; }
Camera &Application::camera() { return *camera_; }
void Application::enterScene(Ptr<Scene> scene) { enterScene(scene, nullptr); }
void Application::enterScene(Ptr<Scene> scene,
Ptr<class TransitionScene> transitionScene) {
void Application::enterScene(Ptr<Scene> scene) {
if (sceneManager_ && scene) {
scene->setViewportSize(static_cast<float>(window_->width()),
static_cast<float>(window_->height()));
sceneManager_->enterScene(scene, transitionScene);
sceneManager_->enterScene(scene);
}
}

View File

@ -1,5 +1,5 @@
#include <algorithm>
#include <graphics/camera.h>
#include <renderer/camera.h>
#include <glm/gtc/matrix_transform.hpp>
namespace extra2d {

View File

@ -1,5 +1,5 @@
#include <graphics/opengl/gl_renderer.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
namespace extra2d {

View File

@ -1,4 +1,4 @@
#include <graphics/render_command.h>
#include <renderer/render_command.h>
#include <algorithm>
namespace extra2d {

View File

@ -1,6 +1,6 @@
#include <glad/glad.h>
#include <graphics/opengl/gl_texture.h>
#include <graphics/render_target.h>
#include <renderer/render_target.h>
#include <utils/logger.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION

View File

@ -1,4 +1,4 @@
#include <graphics/shader_preset.h>
#include <renderer/shader_preset.h>
#include <utils/logger.h>
namespace extra2d {

View File

@ -1,5 +1,5 @@
#include <core/color.h>
#include <graphics/shader_system.h>
#include <renderer/shader_system.h>
#include <utils/logger.h>
#include <fstream>
#include <sstream>

View File

@ -1,7 +1,6 @@
#include <algorithm>
#include <animation/tween.h>
#include <cmath>
#include <graphics/render_command.h>
#include <renderer/render_command.h>
#include <scene/node.h>
#include <scene/scene.h>
#include <utils/logger.h>
@ -330,7 +329,6 @@ void Node::onExit() {
}
void Node::onUpdate(float dt) {
updateTweens(dt);
onUpdateNode(dt);
// Update children
@ -431,142 +429,4 @@ void Node::collectRenderCommands(std::vector<RenderCommand> &commands,
}
}
Tween &Node::tween() {
auto tw = std::make_shared<Tween>(this);
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::tween(const std::string &name) {
auto tw = std::make_shared<Tween>(this, name);
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::moveTo(const Vec2 &pos, float duration, TweenEasing easing) {
TweenProperty props;
props.position = pos;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::moveBy(const Vec2 &delta, float duration, TweenEasing easing) {
TweenProperty props;
props.position = delta;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->by(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::scaleTo(float scale, float duration, TweenEasing easing) {
TweenProperty props;
props.scale = Vec2(scale, scale);
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::scaleBy(float delta, float duration, TweenEasing easing) {
TweenProperty props;
props.scale = Vec2(delta, delta);
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->by(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::rotateTo(float degrees, float duration, TweenEasing easing) {
TweenProperty props;
props.rotation = degrees;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::rotateBy(float degrees, float duration, TweenEasing easing) {
TweenProperty props;
props.rotation = degrees;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->by(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::fadeIn(float duration, TweenEasing easing) {
TweenProperty props;
props.opacity = 1.0f;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::fadeOut(float duration, TweenEasing easing) {
TweenProperty props;
props.opacity = 0.0f;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
Tween &Node::fadeTo(float opacity, float duration, TweenEasing easing) {
TweenProperty props;
props.opacity = opacity;
TweenOptions options;
options.easing = easing;
auto tw = std::make_shared<Tween>(this);
tw->to(duration, props, options);
tw->start();
tweens_.push_back(tw);
return *tweens_.back();
}
void Node::stopAllTweens() {
for (auto &tw : tweens_) {
tw->stop();
}
tweens_.clear();
}
void Node::updateTweens(float dt) {
for (auto it = tweens_.begin(); it != tweens_.end();) {
(*it)->update(dt);
if ((*it)->isFinished()) {
it = tweens_.erase(it);
} else {
++it;
}
}
}
} // namespace extra2d

View File

@ -1,5 +1,5 @@
#include <graphics/render_command.h>
#include <graphics/renderer.h>
#include <renderer/render_command.h>
#include <renderer/renderer.h>
#include <scene/scene.h>
#include <utils/logger.h>

View File

@ -1,15 +1,9 @@
#include <algorithm>
#include <app/application.h>
#include <graphics/render_command.h>
#include <graphics/renderer.h>
#include <renderer/render_command.h>
#include <renderer/renderer.h>
#include <platform/input.h>
#include <scene/scene_manager.h>
#include <scene/transition_box_scene.h>
#include <scene/transition_fade_scene.h>
#include <scene/transition_flip_scene.h>
#include <scene/transition_scale_scene.h>
#include <scene/transition_scene.h>
#include <scene/transition_slide_scene.h>
#include <utils/logger.h>
@ -76,7 +70,7 @@ void SceneManager::runWithScene(Ptr<Scene> scene) {
}
void SceneManager::replaceScene(Ptr<Scene> scene) {
if (!scene || isTransitioning_) {
if (!scene) {
return;
}
@ -98,7 +92,7 @@ void SceneManager::replaceScene(Ptr<Scene> scene) {
}
void SceneManager::enterScene(Ptr<Scene> scene) {
if (!scene || isTransitioning_) {
if (!scene) {
return;
}
@ -109,112 +103,8 @@ void SceneManager::enterScene(Ptr<Scene> scene) {
}
}
void SceneManager::enterScene(Ptr<Scene> scene,
Ptr<TransitionScene> transitionScene) {
if (!scene || isTransitioning_) {
return;
}
// 如果没有过渡场景,使用无过渡切换
if (!transitionScene) {
enterScene(scene);
return;
}
auto current = getCurrentScene();
if (!current) {
enterScene(scene);
return;
}
// 在过渡开始前,发送 UIHoverExit 给当前悬停的节点,重置按钮状态
if (hoverTarget_) {
Event evt;
evt.type = EventType::UIHoverExit;
evt.data = CustomEvent{0, hoverTarget_};
dispatchToNode(hoverTarget_, evt);
hoverTarget_ = nullptr;
}
captureTarget_ = nullptr;
hasLastPointerWorld_ = false;
// 设置过渡场景
transitionScene->setOutScene(current);
transitionScene->setFinishCallback([this]() { finishTransition(); });
// 暂停当前场景
current->pause();
// 推入过渡场景(作为中介场景)
transitionScene->onEnter();
transitionScene->onAttachToScene(transitionScene.get());
sceneStack_.push(transitionScene);
isTransitioning_ = true;
activeTransitionScene_ = transitionScene;
transitionStackAction_ = [this, transitionScene]() {
// 退出旧场景
auto outScene = transitionScene->getOutScene();
if (!sceneStack_.empty() && outScene) {
// 过渡场景已经在栈顶,弹出它
if (sceneStack_.top().get() == transitionScene.get()) {
sceneStack_.pop();
}
outScene->onExit();
outScene->onDetachFromScene();
}
// 推入新场景
auto inScene = transitionScene->getInScene();
if (inScene) {
inScene->onAttachToScene(inScene.get());
sceneStack_.push(inScene);
}
};
}
void SceneManager::replaceScene(Ptr<Scene> scene, TransitionType transition,
float duration) {
if (!scene || isTransitioning_) {
return;
}
if (sceneStack_.empty()) {
runWithScene(scene);
return;
}
auto oldScene = sceneStack_.top();
startTransition(oldScene, scene, transition, duration, [this]() {
// 过渡完成后,退出旧场景并从堆栈中移除
if (!sceneStack_.empty() && activeTransitionScene_) {
// 弹出过渡场景
if (sceneStack_.top().get() == activeTransitionScene_.get()) {
sceneStack_.pop();
}
// 退出旧场景
auto outScene = activeTransitionScene_->getOutScene();
if (outScene) {
outScene->onExit();
outScene->onDetachFromScene();
}
}
// 将新场景推入堆栈
if (activeTransitionScene_) {
auto inScene = activeTransitionScene_->getInScene();
if (inScene) {
inScene->onAttachToScene(inScene.get());
sceneStack_.push(inScene);
}
}
});
}
void SceneManager::pushScene(Ptr<Scene> scene) {
if (!scene || isTransitioning_) {
if (!scene) {
return;
}
@ -229,43 +119,8 @@ void SceneManager::pushScene(Ptr<Scene> scene) {
sceneStack_.push(scene);
}
void SceneManager::pushScene(Ptr<Scene> scene, TransitionType transition,
float duration) {
if (!scene || isTransitioning_) {
return;
}
if (sceneStack_.empty()) {
runWithScene(scene);
return;
}
// 暂停当前场景
sceneStack_.top()->pause();
auto currentScene = sceneStack_.top();
startTransition(currentScene, scene, transition, duration, [this]() {
// 过渡完成后,将新场景推入堆栈
if (!sceneStack_.empty() && activeTransitionScene_) {
// 弹出过渡场景
if (sceneStack_.top().get() == activeTransitionScene_.get()) {
sceneStack_.pop();
}
}
if (activeTransitionScene_) {
auto inScene = activeTransitionScene_->getInScene();
if (inScene) {
inScene->onAttachToScene(inScene.get());
sceneStack_.push(inScene);
}
}
});
}
void SceneManager::popScene() {
if (sceneStack_.size() <= 1 || isTransitioning_) {
if (sceneStack_.size() <= 1) {
return;
}
@ -280,42 +135,8 @@ void SceneManager::popScene() {
}
}
void SceneManager::popScene(TransitionType transition, float duration) {
if (sceneStack_.size() <= 1 || isTransitioning_) {
return;
}
auto current = sceneStack_.top();
auto previous = getPreviousScene();
startTransition(current, previous, transition, duration, [this]() {
// 过渡完成后,退出当前场景并从堆栈中移除
if (!sceneStack_.empty() && activeTransitionScene_) {
// 弹出过渡场景
if (sceneStack_.top().get() == activeTransitionScene_.get()) {
sceneStack_.pop();
}
// 退出当前场景
auto outScene = activeTransitionScene_->getOutScene();
if (outScene) {
outScene->onExit();
outScene->onDetachFromScene();
}
}
// 恢复前一个场景
if (activeTransitionScene_) {
auto inScene = activeTransitionScene_->getInScene();
if (inScene && !sceneStack_.empty() && sceneStack_.top() == inScene) {
inScene->resume();
}
}
});
}
void SceneManager::popToRootScene() {
if (sceneStack_.size() <= 1 || isTransitioning_) {
if (sceneStack_.size() <= 1) {
return;
}
@ -331,35 +152,7 @@ void SceneManager::popToRootScene() {
sceneStack_.top()->resume();
}
void SceneManager::popToRootScene(TransitionType transition, float duration) {
if (sceneStack_.size() <= 1 || isTransitioning_) {
return;
}
auto root = getRootScene();
auto current = sceneStack_.top();
startTransition(current, root, transition, duration, [this, root]() {
// 退出所有场景直到根场景
while (!sceneStack_.empty() && sceneStack_.top().get() != root.get()) {
auto scene = sceneStack_.top();
scene->onExit();
scene->onDetachFromScene();
sceneStack_.pop();
}
// 恢复根场景
if (!sceneStack_.empty() && sceneStack_.top().get() == root.get()) {
root->resume();
}
});
}
void SceneManager::popToScene(const std::string &name) {
if (isTransitioning_) {
return;
}
// Find target scene in stack
std::stack<Ptr<Scene>> tempStack;
Ptr<Scene> target = nullptr;
@ -380,33 +173,6 @@ void SceneManager::popToScene(const std::string &name) {
}
}
void SceneManager::popToScene(const std::string &name,
TransitionType transition, float duration) {
if (isTransitioning_) {
return;
}
auto target = getSceneByName(name);
if (target && target != sceneStack_.top()) {
auto current = sceneStack_.top();
startTransition(current, target, transition, duration, [this, target]() {
// 退出所有场景直到目标场景
while (!sceneStack_.empty() && sceneStack_.top() != target) {
auto scene = sceneStack_.top();
scene->onExit();
scene->onDetachFromScene();
sceneStack_.pop();
}
// 恢复目标场景
if (!sceneStack_.empty() && sceneStack_.top() == target) {
target->resume();
}
});
}
}
Ptr<Scene> SceneManager::getCurrentScene() const {
if (sceneStack_.empty()) {
return nullptr;
@ -464,21 +230,12 @@ bool SceneManager::hasScene(const std::string &name) const {
}
void SceneManager::update(float dt) {
if (isTransitioning_) {
// 过渡场景在栈顶,正常更新即可
hoverTarget_ = nullptr;
captureTarget_ = nullptr;
hasLastPointerWorld_ = false;
}
if (!sceneStack_.empty()) {
auto &scene = *sceneStack_.top();
scene.updateScene(dt);
if (!isTransitioning_) {
dispatchPointerEvents(scene);
}
}
}
void SceneManager::render(Renderer &renderer) {
Color clearColor = Colors::Black;
@ -519,114 +276,6 @@ void SceneManager::end() {
void SceneManager::purgeCachedScenes() { namedScenes_.clear(); }
void SceneManager::startTransition(Ptr<Scene> from, Ptr<Scene> to,
TransitionType type, float duration,
Function<void()> stackAction) {
if (!from || !to) {
return;
}
// 创建过渡场景
auto transitionScene = createTransitionScene(type, duration, to);
if (!transitionScene) {
// 回退到无过渡切换
replaceScene(to);
return;
}
// 在过渡开始前,发送 UIHoverExit 给当前悬停的节点,重置按钮状态
if (hoverTarget_) {
Event evt;
evt.type = EventType::UIHoverExit;
evt.data = CustomEvent{0, hoverTarget_};
dispatchToNode(hoverTarget_, evt);
hoverTarget_ = nullptr;
}
captureTarget_ = nullptr;
hasLastPointerWorld_ = false;
// 设置过渡场景
transitionScene->setOutScene(from);
transitionScene->setFinishCallback([this]() { finishTransition(); });
// 暂停当前场景
from->pause();
// 推入过渡场景(作为中介场景)
transitionScene->onEnter();
transitionScene->onAttachToScene(transitionScene.get());
sceneStack_.push(transitionScene);
isTransitioning_ = true;
currentTransition_ = type;
activeTransitionScene_ = transitionScene;
transitionStackAction_ = std::move(stackAction);
}
Ptr<TransitionScene> SceneManager::createTransitionScene(TransitionType type,
float duration,
Ptr<Scene> inScene) {
if (!inScene) {
return nullptr;
}
switch (type) {
case TransitionType::Fade:
return TransitionFadeScene::create(duration, inScene);
case TransitionType::SlideLeft:
return TransitionSlideScene::create(duration, inScene,
TransitionDirection::Left);
case TransitionType::SlideRight:
return TransitionSlideScene::create(duration, inScene,
TransitionDirection::Right);
case TransitionType::SlideUp:
return TransitionSlideScene::create(duration, inScene,
TransitionDirection::Up);
case TransitionType::SlideDown:
return TransitionSlideScene::create(duration, inScene,
TransitionDirection::Down);
case TransitionType::Scale:
return TransitionScaleScene::create(duration, inScene);
case TransitionType::Flip:
return TransitionFlipScene::create(duration, inScene);
case TransitionType::Box:
return TransitionBoxScene::create(duration, inScene);
default:
// 默认使用淡入淡出
return TransitionFadeScene::create(duration, inScene);
}
}
void SceneManager::finishTransition() {
// 先保存当前悬停的节点,然后在 transitionStackAction_ 之后发送 UIHoverExit
Node *lastHoverTarget = hoverTarget_;
isTransitioning_ = false;
hoverTarget_ = nullptr;
captureTarget_ = nullptr;
hasLastPointerWorld_ = false;
if (transitionStackAction_) {
transitionStackAction_();
}
// 在 transitionStackAction_ 之后发送 UIHoverExit确保旧场景仍然有效
if (lastHoverTarget) {
Event evt;
evt.type = EventType::UIHoverExit;
evt.data = CustomEvent{0, lastHoverTarget};
dispatchToNode(lastHoverTarget, evt);
}
activeTransitionScene_.reset();
transitionStackAction_ = nullptr;
if (transitionCallback_) {
transitionCallback_();
transitionCallback_ = nullptr;
}
}
void SceneManager::dispatchPointerEvents(Scene &scene) {
auto &input = Application::instance().input();
Vec2 screenPos = input.getMousePosition();

View File

@ -1,10 +1,9 @@
#include <algorithm>
#include <cmath>
#include <graphics/render_command.h>
#include <graphics/renderer.h>
#include <limits>
#include <scene/shape_node.h>
#include <renderer/render_command.h>
#include <renderer/renderer.h>
#include <scene/shape.h>
namespace extra2d {
@ -110,17 +109,11 @@ Ptr<ShapeNode> ShapeNode::createFilledPolygon(const std::vector<Vec2> &points,
return node;
}
void ShapeNode::setPoints(const std::vector<Vec2> &points) {
points_ = points;
}
void ShapeNode::setPoints(const std::vector<Vec2> &points) { points_ = points; }
void ShapeNode::addPoint(const Vec2 &point) {
points_.push_back(point);
}
void ShapeNode::addPoint(const Vec2 &point) { points_.push_back(point); }
void ShapeNode::clearPoints() {
points_.clear();
}
void ShapeNode::clearPoints() { points_.clear(); }
Rect ShapeNode::boundingBox() const {
if (points_.empty()) {

View File

@ -1,7 +1,7 @@
#include <algorithm>
#include <cmath>
#include <graphics/render_command.h>
#include <graphics/renderer.h>
#include <renderer/render_command.h>
#include <renderer/renderer.h>
#include <graphics/texture.h>
#include <scene/sprite.h>

View File

@ -1,71 +0,0 @@
#include <algorithm>
#include <app/application.h>
#include <core/color.h>
#include <glm/gtc/matrix_transform.hpp>
#include <graphics/renderer.h>
#include <scene/transition_box_scene.h>
namespace extra2d {
TransitionBoxScene::TransitionBoxScene(float duration, Ptr<Scene> inScene,
int divisions)
: TransitionScene(duration, inScene), divisions_(divisions) {}
Ptr<TransitionBoxScene>
TransitionBoxScene::create(float duration, Ptr<Scene> inScene, int divisions) {
return makePtr<TransitionBoxScene>(duration, inScene, divisions);
}
void TransitionBoxScene::onTransitionStart() {
// 方块过渡不需要特殊的初始化
}
void TransitionBoxScene::renderContent(Renderer &renderer) {
// 获取窗口大小
auto &app = Application::instance();
float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().height());
// 更新进度
elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 先渲染新场景
if (inScene_) {
inScene_->renderContent(renderer);
} else if (outScene_) {
outScene_->renderContent(renderer);
}
// 设置视口为整个窗口
renderer.setViewport(0, 0, static_cast<int>(windowWidth),
static_cast<int>(windowHeight));
// 计算要显示的方块数量
int div = std::max(1, divisions_);
int total = div * div;
int visible = std::clamp(static_cast<int>(total * progress_), 0, total);
float cellW = windowWidth / static_cast<float>(div);
float cellH = windowHeight / static_cast<float>(div);
// 设置正交投影
glm::mat4 overlayVP =
glm::ortho(0.0f, windowWidth, windowHeight, 0.0f, -1.0f, 1.0f);
renderer.setViewProjection(overlayVP);
// 绘制剩余的方块(作为遮罩)
for (int idx = visible; idx < total; ++idx) {
int x = idx % div;
int y = idx / div;
renderer.fillRect(Rect(x * cellW, y * cellH, cellW + 1.0f, cellH + 1.0f),
Colors::Black);
}
// 检查是否完成
if (progress_ >= 1.0f && !isFinished_) {
finish();
}
}
} // namespace extra2d

View File

@ -1,89 +0,0 @@
#include <app/application.h>
#include <glm/gtc/matrix_transform.hpp>
#include <graphics/render_target.h>
#include <graphics/renderer.h>
#include <scene/transition_fade_scene.h>
#include <utils/logger.h>
namespace extra2d {
TransitionFadeScene::TransitionFadeScene(float duration, Ptr<Scene> inScene,
const Color &color)
: TransitionScene(duration, inScene), maskColor_(color) {}
Ptr<TransitionFadeScene> TransitionFadeScene::create(float duration,
Ptr<Scene> inScene,
const Color &color) {
return makePtr<TransitionFadeScene>(duration, inScene, color);
}
void TransitionFadeScene::onTransitionStart() {
E2D_LOG_DEBUG("TransitionFadeScene::onTransitionStart - 启动淡入淡出过渡");
// 使用一个定时器来更新进度
// 由于我们没有直接的动作系统集成到 Scene使用简单的 update 逻辑
// 实际进度更新由 SceneManager 的 update 驱动
}
void TransitionFadeScene::renderContent(Renderer &renderer) {
// 获取窗口大小
auto &app = Application::instance();
float windowWidth = static_cast<float>(app.window().width());
float windowHeight = static_cast<float>(app.window().height());
// 计算当前进度
elapsed_ += 1.0f / 60.0f; // 假设 60fps实际应该由 update 传递 dt
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 检查是否需要切换场景(进度过半时)
if (!hasSwitched_ && progress_ >= 0.5f) {
hideOutShowIn();
}
// 根据进度渲染
if (progress_ < 0.5f) {
// 第一阶段:显示旧场景
drawOutScene(renderer);
} else {
// 第二阶段:显示新场景
drawInScene(renderer);
}
// 绘制遮罩层
// 计算遮罩透明度
float maskAlpha;
if (progress_ < 0.5f) {
// 前半段:从透明到不透明
maskAlpha = progress_ * 2.0f; // 0 -> 1
} else {
// 后半段:从不透明到透明
maskAlpha = (1.0f - progress_) * 2.0f; // 1 -> 0
}
// 设置视口为整个窗口
renderer.setViewport(0, 0, static_cast<int>(windowWidth),
static_cast<int>(windowHeight));
// 设置正交投影
glm::mat4 overlayVP =
glm::ortho(0.0f, windowWidth, windowHeight, 0.0f, -1.0f, 1.0f);
renderer.setViewProjection(overlayVP);
// 绘制遮罩
Color maskColor = maskColor_;
maskColor.a = maskAlpha;
renderer.fillRect(Rect(0.0f, 0.0f, windowWidth, windowHeight), maskColor);
// 检查是否完成
if (progress_ >= 1.0f && !isFinished_) {
finish();
}
}
void TransitionFadeScene::hideOutShowIn() {
hasSwitched_ = true;
E2D_LOG_DEBUG("TransitionFadeScene::hideOutShowIn - 切换场景显示");
}
} // namespace extra2d

View File

@ -1,91 +0,0 @@
#include <core/math_types.h>
#include <graphics/camera.h>
#include <graphics/renderer.h>
#include <scene/transition_flip_scene.h>
namespace extra2d {
TransitionFlipScene::TransitionFlipScene(float duration, Ptr<Scene> inScene,
Axis axis)
: TransitionScene(duration, inScene), axis_(axis) {}
Ptr<TransitionFlipScene>
TransitionFlipScene::create(float duration, Ptr<Scene> inScene, Axis axis) {
return makePtr<TransitionFlipScene>(duration, inScene, axis);
}
void TransitionFlipScene::onTransitionStart() {
// 翻页过渡不需要特殊的初始化
}
void TransitionFlipScene::renderContent(Renderer &renderer) {
// 更新进度
elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数
float easeProgress = progress_ < 0.5f
? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
float angle = easeProgress * PI_F; // 180度翻转
if (progress_ < 0.5f) {
// 前半段:翻转源场景
if (outScene_) {
float currentAngle = angle;
Camera *camera = outScene_->getActiveCamera();
float originalRotation = camera ? camera->rot() : 0.0f;
if (axis_ == Axis::Horizontal) {
// 水平轴翻转 - 模拟绕X轴旋转
if (camera) {
camera->setRotation(originalRotation + currentAngle * RAD_TO_DEG);
}
} else {
// 垂直轴翻转 - 模拟绕Y轴旋转
if (camera) {
camera->setRotation(originalRotation - currentAngle * RAD_TO_DEG);
}
}
outScene_->renderContent(renderer);
if (camera) {
camera->setRotation(originalRotation);
}
}
} else {
// 后半段:翻转目标场景
if (inScene_) {
float currentAngle = angle - PI_F;
Camera *camera = inScene_->getActiveCamera();
float originalRotation = camera ? camera->rot() : 0.0f;
if (axis_ == Axis::Horizontal) {
if (camera) {
camera->setRotation(originalRotation + currentAngle * RAD_TO_DEG);
}
} else {
if (camera) {
camera->setRotation(originalRotation - currentAngle * RAD_TO_DEG);
}
}
inScene_->renderContent(renderer);
if (camera) {
camera->setRotation(originalRotation);
}
}
}
// 检查是否完成
if (progress_ >= 1.0f && !isFinished_) {
finish();
}
}
} // namespace extra2d

View File

@ -1,72 +0,0 @@
#include <algorithm>
#include <graphics/camera.h>
#include <graphics/renderer.h>
#include <scene/transition_scale_scene.h>
namespace extra2d {
TransitionScaleScene::TransitionScaleScene(float duration, Ptr<Scene> inScene)
: TransitionScene(duration, inScene) {}
Ptr<TransitionScaleScene> TransitionScaleScene::create(float duration,
Ptr<Scene> inScene) {
return makePtr<TransitionScaleScene>(duration, inScene);
}
void TransitionScaleScene::onTransitionStart() {
// 缩放过渡不需要特殊的初始化
}
void TransitionScaleScene::renderContent(Renderer &renderer) {
// 更新进度
elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数
float easeProgress = progress_ < 0.5f
? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
// 源场景:缩小消失
if (outScene_) {
float scale = std::max(0.01f, 1.0f - easeProgress);
Camera *camera = outScene_->getActiveCamera();
float originalZoom = camera ? camera->getZoom() : 1.0f;
if (camera) {
camera->setZoom(originalZoom * scale);
}
outScene_->renderContent(renderer);
if (camera) {
camera->setZoom(originalZoom);
}
}
// 目标场景:放大出现
if (inScene_) {
float scale = std::max(0.01f, easeProgress);
Camera *camera = inScene_->getActiveCamera();
float originalZoom = camera ? camera->getZoom() : 1.0f;
if (camera) {
camera->setZoom(originalZoom * scale);
}
inScene_->renderContent(renderer);
if (camera) {
camera->setZoom(originalZoom);
}
}
// 检查是否完成
if (progress_ >= 1.0f && !isFinished_) {
finish();
}
}
} // namespace extra2d

View File

@ -1,81 +0,0 @@
#include <graphics/renderer.h>
#include <scene/transition_scene.h>
#include <utils/logger.h>
namespace extra2d {
TransitionScene::TransitionScene(float duration, Ptr<Scene> inScene)
: duration_(duration), inScene_(inScene) {}
void TransitionScene::onEnter() {
// 调用基类的 onEnter
Scene::onEnter();
// 调用退出场景的 onExitTransitionDidStart
if (outScene_) {
outScene_->onExitTransitionDidStart();
}
// 调用进入场景的 onEnter
if (inScene_) {
inScene_->onEnter();
inScene_->onAttachToScene(inScene_.get());
}
// 启动过渡
onTransitionStart();
}
void TransitionScene::onExit() {
// 调用退出场景的 onExit
if (outScene_) {
outScene_->onExit();
outScene_->onDetachFromScene();
}
// 调用进入场景的 onEnterTransitionDidFinish
if (inScene_) {
inScene_->onEnterTransitionDidFinish();
}
// 调用基类的 onExit
Scene::onExit();
}
void TransitionScene::finish() {
if (isFinished_) {
return;
}
isFinished_ = true;
E2D_LOG_DEBUG("TransitionScene::finish - 过渡完成,切换到目标场景");
// 调用完成回调,通知 SceneManager 进行场景切换
if (finishCallback_) {
finishCallback_();
}
}
void TransitionScene::renderContent(Renderer &renderer) {
// 在 TransitionScene 上渲染新旧两个子场景
// 子类可以重写此方法来控制渲染顺序和效果
// 默认先渲染退出场景,再渲染进入场景(在上方)
drawOutScene(renderer);
drawInScene(renderer);
}
void TransitionScene::drawOutScene(Renderer &renderer) {
if (outScene_) {
outScene_->renderContent(renderer);
}
}
void TransitionScene::drawInScene(Renderer &renderer) {
if (inScene_) {
inScene_->renderContent(renderer);
}
}
} // namespace extra2d

View File

@ -1,123 +0,0 @@
#include <graphics/camera.h>
#include <graphics/renderer.h>
#include <scene/transition_slide_scene.h>
namespace extra2d {
TransitionSlideScene::TransitionSlideScene(float duration, Ptr<Scene> inScene,
TransitionDirection direction)
: TransitionScene(duration, inScene), direction_(direction) {}
Ptr<TransitionSlideScene>
TransitionSlideScene::create(float duration, Ptr<Scene> inScene,
TransitionDirection direction) {
return makePtr<TransitionSlideScene>(duration, inScene, direction);
}
void TransitionSlideScene::onTransitionStart() {
// 滑动过渡不需要特殊的初始化
}
void TransitionSlideScene::renderContent(Renderer &renderer) {
// 获取视口尺寸
float screenWidth = 800.0f;
float screenHeight = 600.0f;
if (outScene_) {
Size viewportSize = outScene_->getViewportSize();
if (viewportSize.width > 0 && viewportSize.height > 0) {
screenWidth = viewportSize.width;
screenHeight = viewportSize.height;
}
} else if (inScene_) {
Size viewportSize = inScene_->getViewportSize();
if (viewportSize.width > 0 && viewportSize.height > 0) {
screenWidth = viewportSize.width;
screenHeight = viewportSize.height;
}
}
// 更新进度
elapsed_ += 1.0f / 60.0f;
progress_ = duration_ > 0.0f ? std::min(1.0f, elapsed_ / duration_) : 1.0f;
// 缓动函数
float easeProgress = progress_ < 0.5f
? 2.0f * progress_ * progress_
: -1.0f + (4.0f - 2.0f * progress_) * progress_;
// 渲染退出场景(滑出)
if (outScene_) {
float offsetX = 0.0f;
float offsetY = 0.0f;
switch (direction_) {
case TransitionDirection::Left:
offsetX = -screenWidth * easeProgress;
break;
case TransitionDirection::Right:
offsetX = screenWidth * easeProgress;
break;
case TransitionDirection::Up:
offsetY = -screenHeight * easeProgress;
break;
case TransitionDirection::Down:
offsetY = screenHeight * easeProgress;
break;
}
Camera *camera = outScene_->getActiveCamera();
Vec2 originalPos = camera ? camera->pos() : Vec2::Zero();
if (camera) {
camera->setPosition(originalPos.x + offsetX, originalPos.y + offsetY);
}
outScene_->renderContent(renderer);
if (camera) {
camera->setPosition(originalPos);
}
}
// 渲染进入场景(滑入)
if (inScene_) {
float offsetX = 0.0f;
float offsetY = 0.0f;
switch (direction_) {
case TransitionDirection::Left:
offsetX = screenWidth * (1.0f - easeProgress);
break;
case TransitionDirection::Right:
offsetX = -screenWidth * (1.0f - easeProgress);
break;
case TransitionDirection::Up:
offsetY = screenHeight * (1.0f - easeProgress);
break;
case TransitionDirection::Down:
offsetY = -screenHeight * (1.0f - easeProgress);
break;
}
Camera *camera = inScene_->getActiveCamera();
Vec2 originalPos = camera ? camera->pos() : Vec2::Zero();
if (camera) {
camera->setPosition(originalPos.x + offsetX, originalPos.y + offsetY);
}
inScene_->renderContent(renderer);
if (camera) {
camera->setPosition(originalPos);
}
}
// 检查是否完成
if (progress_ >= 1.0f && !isFinished_) {
finish();
}
}
} // namespace extra2d

View File

@ -2,7 +2,7 @@
#include <app/application.h>
#include <cmath>
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/button.h>
namespace extra2d {

View File

@ -1,5 +1,5 @@
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/check_box.h>
namespace extra2d {

View File

@ -1,5 +1,5 @@
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/label.h>
namespace extra2d {

View File

@ -1,6 +1,6 @@
#include <cmath>
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/progress_bar.h>
namespace extra2d {

View File

@ -1,5 +1,5 @@
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/radio_button.h>
namespace extra2d {

View File

@ -1,6 +1,6 @@
#include <cmath>
#include <core/string.h>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/slider.h>
namespace extra2d {

View File

@ -1,7 +1,7 @@
#include <core/string.h>
#include <cstdarg>
#include <cstdio>
#include <graphics/renderer.h>
#include <renderer/renderer.h>
#include <ui/text.h>
namespace extra2d {