refactor(core): 替换shared_ptr为侵入式引用计数IntrusivePtr
重构整个项目,将std::shared_ptr替换为自定义的IntrusivePtr实现: 1. 新增RefCounted基类,提供引用计数功能 2. 实现IntrusivePtr智能指针模板类 3. 修改所有资源管理类使用IntrusivePtr 4. 更新Node类继承自RefCounted 5. 移除types.h中的shared_ptr相关定义 6. 统一使用makeRef替代shared创建对象
This commit is contained in:
parent
4afd52cc82
commit
b4a55239aa
|
|
@ -85,7 +85,7 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 便捷方法
|
// 便捷方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void enterScene(Ptr<class Scene> scene);
|
void enterScene(IntrusivePtr<class Scene> scene);
|
||||||
|
|
||||||
float deltaTime() const { return deltaTime_; }
|
float deltaTime() const { return deltaTime_; }
|
||||||
float totalTime() const { return totalTime_; }
|
float totalTime() const { return totalTime_; }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/intrusive_ptr.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <core/types.h>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -21,10 +21,10 @@ public:
|
||||||
bool initialize();
|
bool initialize();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
std::shared_ptr<Sound> loadSound(const std::string& filePath);
|
IntrusivePtr<Sound> loadSound(const std::string& filePath);
|
||||||
std::shared_ptr<Sound> loadSound(const std::string& name, const std::string& filePath);
|
IntrusivePtr<Sound> loadSound(const std::string& name, const std::string& filePath);
|
||||||
|
|
||||||
std::shared_ptr<Sound> getSound(const std::string& name);
|
IntrusivePtr<Sound> getSound(const std::string& name);
|
||||||
void unloadSound(const std::string& name);
|
void unloadSound(const std::string& name);
|
||||||
void unloadAllSounds();
|
void unloadAllSounds();
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ private:
|
||||||
AudioEngine() = default;
|
AudioEngine() = default;
|
||||||
~AudioEngine();
|
~AudioEngine();
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Sound>> sounds_;
|
std::unordered_map<std::string, IntrusivePtr<Sound>> sounds_;
|
||||||
float masterVolume_ = 1.0f;
|
float masterVolume_ = 1.0f;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/ref_counted.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <core/types.h>
|
|
||||||
|
|
||||||
struct Mix_Chunk;
|
struct Mix_Chunk;
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace extra2d {
|
||||||
|
|
||||||
class AudioEngine;
|
class AudioEngine;
|
||||||
|
|
||||||
class Sound {
|
class Sound : public RefCounted {
|
||||||
public:
|
public:
|
||||||
~Sound();
|
~Sound();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/ref_counted.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 侵入式智能指针
|
||||||
|
// 参考 Cocos2d-x 的 IntrusivePtr 设计
|
||||||
|
// ============================================================================
|
||||||
|
template <class T>
|
||||||
|
class IntrusivePtr {
|
||||||
|
public:
|
||||||
|
using element_type = T;
|
||||||
|
|
||||||
|
// 默认构造函数
|
||||||
|
IntrusivePtr() : _ptr(nullptr) {}
|
||||||
|
|
||||||
|
// 从原始指针构造
|
||||||
|
IntrusivePtr(T* p) : _ptr(p) {
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->addRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拷贝构造函数
|
||||||
|
IntrusivePtr(const IntrusivePtr<T>& r) : _ptr(r._ptr) {
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->addRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从派生类拷贝构造
|
||||||
|
template <typename U>
|
||||||
|
IntrusivePtr(const IntrusivePtr<U>& r) : _ptr(r.get()) {
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->addRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动构造函数
|
||||||
|
IntrusivePtr(IntrusivePtr<T>&& r) noexcept : _ptr(r.release()) {}
|
||||||
|
|
||||||
|
// 从派生类移动构造
|
||||||
|
template <typename U>
|
||||||
|
IntrusivePtr(IntrusivePtr<U>&& r) noexcept : _ptr(r.release()) {}
|
||||||
|
|
||||||
|
// 析构函数
|
||||||
|
~IntrusivePtr() {
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取原始指针
|
||||||
|
T* get() const { return _ptr; }
|
||||||
|
|
||||||
|
// 解引用操作符
|
||||||
|
T& operator*() const { return *_ptr; }
|
||||||
|
|
||||||
|
// 箭头操作符
|
||||||
|
T* operator->() const { return _ptr; }
|
||||||
|
|
||||||
|
// 转换为原始指针(隐式转换)
|
||||||
|
operator T*() const { return _ptr; }
|
||||||
|
|
||||||
|
// 赋值操作符 - 原始指针
|
||||||
|
IntrusivePtr<T>& operator=(T* p) {
|
||||||
|
reset(p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 赋值操作符 - 同类型
|
||||||
|
IntrusivePtr<T>& operator=(const IntrusivePtr<T>& r) {
|
||||||
|
return *this = r._ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 赋值操作符 - 派生类
|
||||||
|
template <typename U>
|
||||||
|
IntrusivePtr<T>& operator=(const IntrusivePtr<U>& r) {
|
||||||
|
return *this = r.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动赋值
|
||||||
|
IntrusivePtr<T>& operator=(IntrusivePtr<T>&& r) noexcept {
|
||||||
|
IntrusivePtr<T>(std::move(r)).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从派生类移动赋值
|
||||||
|
template <typename U>
|
||||||
|
IntrusivePtr<T>& operator=(IntrusivePtr<U>&& r) noexcept {
|
||||||
|
IntrusivePtr<T>(std::move(r)).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 比较操作符
|
||||||
|
bool operator==(std::nullptr_t) const { return _ptr == nullptr; }
|
||||||
|
bool operator==(T* r) const { return _ptr == r; }
|
||||||
|
bool operator!=(std::nullptr_t) const { return _ptr != nullptr; }
|
||||||
|
bool operator!=(T* r) const { return _ptr != r; }
|
||||||
|
bool operator<(const IntrusivePtr<T>& r) const { return _ptr < r._ptr; }
|
||||||
|
|
||||||
|
// 重置指针
|
||||||
|
void reset() noexcept {
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->release();
|
||||||
|
}
|
||||||
|
_ptr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T* p) {
|
||||||
|
// 先增加新指针的引用计数,再释放旧指针
|
||||||
|
// 这样可以处理自赋值的情况
|
||||||
|
if (p) {
|
||||||
|
p->addRef();
|
||||||
|
}
|
||||||
|
if (_ptr) {
|
||||||
|
_ptr->release();
|
||||||
|
}
|
||||||
|
_ptr = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交换指针
|
||||||
|
void swap(T** pp) noexcept {
|
||||||
|
T* p = _ptr;
|
||||||
|
_ptr = *pp;
|
||||||
|
*pp = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(IntrusivePtr<T>& r) noexcept {
|
||||||
|
swap(&r._ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放指针所有权(不减少引用计数)
|
||||||
|
T* release() {
|
||||||
|
T* retVal = _ptr;
|
||||||
|
_ptr = nullptr;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* _ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 辅助函数
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// 创建 IntrusivePtr 的便捷函数
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
inline IntrusivePtr<T> makePtr(Args&&... args) {
|
||||||
|
return IntrusivePtr<T>(new T(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::hash 特化
|
||||||
|
// ============================================================================
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct hash<extra2d::IntrusivePtr<T>> {
|
||||||
|
size_t operator()(const extra2d::IntrusivePtr<T>& val) const noexcept {
|
||||||
|
return hash<T*>{}(val.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 侵入式引用计数基类
|
||||||
|
// 参考 Cocos2d-x 的 RefCounted 设计
|
||||||
|
// ============================================================================
|
||||||
|
class RefCounted {
|
||||||
|
public:
|
||||||
|
virtual ~RefCounted() = default;
|
||||||
|
|
||||||
|
// 增加引用计数
|
||||||
|
void addRef() {
|
||||||
|
++_referenceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 减少引用计数,当计数为0时删除对象
|
||||||
|
void release() {
|
||||||
|
if (--_referenceCount == 0) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前引用计数
|
||||||
|
uint32_t getRefCount() const {
|
||||||
|
return _referenceCount.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// 构造函数,初始引用计数为1
|
||||||
|
RefCounted() : _referenceCount(1) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<uint32_t> _referenceCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/intrusive_ptr.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -9,15 +10,12 @@ namespace extra2d {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 智能指针别名
|
// 智能指针别名
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <typename T> using Ptr = std::shared_ptr<T>;
|
|
||||||
|
|
||||||
template <typename T> using UniquePtr = std::unique_ptr<T>;
|
template <typename T> using UniquePtr = std::unique_ptr<T>;
|
||||||
|
|
||||||
template <typename T> using WeakPtr = std::weak_ptr<T>;
|
/// 创建 IntrusivePtr 的便捷函数
|
||||||
|
template <typename T, typename... Args>
|
||||||
/// 创建 shared_ptr 的便捷函数
|
inline IntrusivePtr<T> makeRef(Args &&...args) {
|
||||||
template <typename T, typename... Args> inline Ptr<T> shared(Args &&...args) {
|
return makePtr<T>(std::forward<Args>(args)...);
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 创建 unique_ptr 的便捷函数
|
/// 创建 unique_ptr 的便捷函数
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <core/color.h>
|
#include <core/color.h>
|
||||||
#include <core/rect.h>
|
#include <core/rect.h>
|
||||||
#include <core/types.h>
|
#include <core/ref_counted.h>
|
||||||
#include <core/vec2.h>
|
#include <core/vec2.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -23,7 +23,7 @@ struct Glyph {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 字体图集接口
|
// 字体图集接口
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class FontAtlas {
|
class FontAtlas : public RefCounted {
|
||||||
public:
|
public:
|
||||||
virtual ~FontAtlas() = default;
|
virtual ~FontAtlas() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ public:
|
||||||
void popTransform() override;
|
void popTransform() override;
|
||||||
glm::mat4 getCurrentTransform() const override;
|
glm::mat4 getCurrentTransform() const override;
|
||||||
|
|
||||||
Ptr<Texture> createTexture(int width, int height, const uint8_t *pixels,
|
IntrusivePtr<Texture> createTexture(int width, int height, const uint8_t *pixels,
|
||||||
int channels) override;
|
int channels) override;
|
||||||
Ptr<Texture> loadTexture(const std::string &filepath) override;
|
IntrusivePtr<Texture> loadTexture(const std::string &filepath) override;
|
||||||
|
|
||||||
void beginSpriteBatch() override;
|
void beginSpriteBatch() override;
|
||||||
void drawSprite(const Texture &texture, const Rect &destRect,
|
void drawSprite(const Texture &texture, const Rect &destRect,
|
||||||
|
|
@ -66,7 +66,7 @@ public:
|
||||||
void fillPolygon(const std::vector<Vec2> &points,
|
void fillPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color) override;
|
const Color &color) override;
|
||||||
|
|
||||||
Ptr<FontAtlas> createFontAtlas(const std::string &filepath, int fontSize,
|
IntrusivePtr<FontAtlas> createFontAtlas(const std::string &filepath, int fontSize,
|
||||||
bool useSDF = false) override;
|
bool useSDF = false) override;
|
||||||
void drawText(const FontAtlas &font, const std::string &text,
|
void drawText(const FontAtlas &font, const std::string &text,
|
||||||
const Vec2 &position, const Color &color) override;
|
const Vec2 &position, const Color &color) override;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void setWrap(bool repeat) override;
|
void setWrap(bool repeat) override;
|
||||||
|
|
||||||
// 从参数创建纹理的工厂方法
|
// 从参数创建纹理的工厂方法
|
||||||
static Ptr<Texture> create(int width, int height, PixelFormat format);
|
static IntrusivePtr<Texture> create(int width, int height, PixelFormat format);
|
||||||
|
|
||||||
// 加载压缩纹理(KTX/DDS 格式)
|
// 加载压缩纹理(KTX/DDS 格式)
|
||||||
bool loadCompressed(const std::string &filepath);
|
bool loadCompressed(const std::string &filepath);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/ref_counted.h>
|
||||||
#include <core/size.h>
|
#include <core/size.h>
|
||||||
#include <core/types.h>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -33,7 +33,7 @@ enum class PixelFormat {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 纹理接口
|
// 纹理接口
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class Texture {
|
class Texture : public RefCounted {
|
||||||
public:
|
public:
|
||||||
virtual ~Texture() = default;
|
virtual ~Texture() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public:
|
||||||
const uint8_t *pixels, Rect &outUvRect);
|
const uint8_t *pixels, Rect &outUvRect);
|
||||||
|
|
||||||
// 获取图集纹理
|
// 获取图集纹理
|
||||||
Ptr<Texture> getTexture() const { return texture_; }
|
IntrusivePtr<Texture> getTexture() const { return texture_; }
|
||||||
|
|
||||||
// 获取条目
|
// 获取条目
|
||||||
const AtlasEntry *getEntry(const std::string &name) const;
|
const AtlasEntry *getEntry(const std::string &name) const;
|
||||||
|
|
@ -66,7 +66,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int width_, height_;
|
int width_, height_;
|
||||||
Ptr<Texture> texture_;
|
IntrusivePtr<Texture> texture_;
|
||||||
std::unordered_map<std::string, AtlasEntry> entries_;
|
std::unordered_map<std::string, AtlasEntry> entries_;
|
||||||
|
|
||||||
// 矩形打包数据
|
// 矩形打包数据
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include <core/color.h>
|
#include <core/color.h>
|
||||||
#include <core/rect.h>
|
#include <core/rect.h>
|
||||||
|
#include <core/ref_counted.h>
|
||||||
#include <core/size.h>
|
#include <core/size.h>
|
||||||
#include <core/types.h>
|
|
||||||
#include <core/vec2.h>
|
#include <core/vec2.h>
|
||||||
#include <glm/mat4x4.hpp>
|
#include <glm/mat4x4.hpp>
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace extra2d {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 2D 正交相机
|
// 2D 正交相机
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class Camera {
|
class Camera : public RefCounted {
|
||||||
public:
|
public:
|
||||||
Camera();
|
Camera();
|
||||||
Camera(float left, float right, float bottom, float top);
|
Camera(float left, float right, float bottom, float top);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/color.h>
|
#include <core/color.h>
|
||||||
#include <core/types.h>
|
#include <core/ref_counted.h>
|
||||||
#include <graphics/opengl/gl_texture.h>
|
#include <graphics/opengl/gl_texture.h>
|
||||||
#include <graphics/texture.h>
|
#include <graphics/texture.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -25,7 +25,7 @@ struct RenderTargetConfig {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 渲染目标 - 基于FBO的离屏渲染
|
// 渲染目标 - 基于FBO的离屏渲染
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class RenderTarget {
|
class RenderTarget : public RefCounted {
|
||||||
public:
|
public:
|
||||||
RenderTarget();
|
RenderTarget();
|
||||||
~RenderTarget();
|
~RenderTarget();
|
||||||
|
|
@ -55,7 +55,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 从现有纹理创建渲染目标
|
* @brief 从现有纹理创建渲染目标
|
||||||
*/
|
*/
|
||||||
bool createFromTexture(Ptr<Texture> texture, bool hasDepth = false);
|
bool createFromTexture(IntrusivePtr<Texture> texture, bool hasDepth = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 销毁渲染目标
|
* @brief 销毁渲染目标
|
||||||
|
|
@ -109,12 +109,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取颜色纹理
|
* @brief 获取颜色纹理
|
||||||
*/
|
*/
|
||||||
Ptr<Texture> getColorTexture() const { return colorTexture_; }
|
IntrusivePtr<Texture> getColorTexture() const { return colorTexture_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取深度纹理(如果有)
|
* @brief 获取深度纹理(如果有)
|
||||||
*/
|
*/
|
||||||
Ptr<Texture> getDepthTexture() const { return depthTexture_; }
|
IntrusivePtr<Texture> getDepthTexture() const { return depthTexture_; }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 视口和裁剪
|
// 视口和裁剪
|
||||||
|
|
@ -169,7 +169,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建渲染目标的静态工厂方法
|
* @brief 创建渲染目标的静态工厂方法
|
||||||
*/
|
*/
|
||||||
static Ptr<RenderTarget> createFromConfig(const RenderTargetConfig &config);
|
static IntrusivePtr<RenderTarget> createFromConfig(const RenderTargetConfig &config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取当前绑定的渲染目标ID
|
* @brief 获取当前绑定的渲染目标ID
|
||||||
|
|
@ -190,8 +190,8 @@ protected:
|
||||||
GLuint fbo_ = 0; // 帧缓冲对象
|
GLuint fbo_ = 0; // 帧缓冲对象
|
||||||
GLuint rbo_ = 0; // 渲染缓冲对象(深度/模板)
|
GLuint rbo_ = 0; // 渲染缓冲对象(深度/模板)
|
||||||
|
|
||||||
Ptr<Texture> colorTexture_; // 颜色纹理
|
IntrusivePtr<Texture> colorTexture_; // 颜色纹理
|
||||||
Ptr<Texture> depthTexture_; // 深度纹理(可选)
|
IntrusivePtr<Texture> depthTexture_; // 深度纹理(可选)
|
||||||
|
|
||||||
int width_ = 0;
|
int width_ = 0;
|
||||||
int height_ = 0;
|
int height_ = 0;
|
||||||
|
|
@ -293,7 +293,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建新的渲染目标
|
* @brief 创建新的渲染目标
|
||||||
*/
|
*/
|
||||||
Ptr<RenderTarget> createRenderTarget(const RenderTargetConfig &config);
|
IntrusivePtr<RenderTarget> createRenderTarget(const RenderTargetConfig &config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取默认渲染目标
|
* @brief 获取默认渲染目标
|
||||||
|
|
@ -318,8 +318,8 @@ private:
|
||||||
RenderTargetManager(const RenderTargetManager &) = delete;
|
RenderTargetManager(const RenderTargetManager &) = delete;
|
||||||
RenderTargetManager &operator=(const RenderTargetManager &) = delete;
|
RenderTargetManager &operator=(const RenderTargetManager &) = delete;
|
||||||
|
|
||||||
Ptr<RenderTarget> defaultRenderTarget_;
|
IntrusivePtr<RenderTarget> defaultRenderTarget_;
|
||||||
std::vector<Ptr<RenderTarget>> renderTargets_;
|
std::vector<IntrusivePtr<RenderTarget>> renderTargets_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,9 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 纹理
|
// 纹理
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual Ptr<Texture> createTexture(int width, int height,
|
virtual IntrusivePtr<Texture> createTexture(int width, int height,
|
||||||
const uint8_t *pixels, int channels) = 0;
|
const uint8_t *pixels, int channels) = 0;
|
||||||
virtual Ptr<Texture> loadTexture(const std::string &filepath) = 0;
|
virtual IntrusivePtr<Texture> loadTexture(const std::string &filepath) = 0;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 精灵批渲染
|
// 精灵批渲染
|
||||||
|
|
@ -112,7 +112,7 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 文字渲染
|
// 文字渲染
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual Ptr<FontAtlas> createFontAtlas(const std::string &filepath,
|
virtual IntrusivePtr<FontAtlas> createFontAtlas(const std::string &filepath,
|
||||||
int fontSize, bool useSDF = false) = 0;
|
int fontSize, bool useSDF = false) = 0;
|
||||||
virtual void drawText(const FontAtlas &font, const std::string &text,
|
virtual void drawText(const FontAtlas &font, const std::string &text,
|
||||||
const Vec2 &position, const Color &color) = 0;
|
const Vec2 &position, const Color &color) = 0;
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,14 @@ enum class TextureFormat {
|
||||||
// 纹理LRU缓存项
|
// 纹理LRU缓存项
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct TextureCacheEntry {
|
struct TextureCacheEntry {
|
||||||
Ptr<Texture> texture;
|
IntrusivePtr<Texture> texture;
|
||||||
size_t size = 0; // 纹理大小(字节)
|
size_t size = 0; // 纹理大小(字节)
|
||||||
float lastAccessTime = 0.0f; // 最后访问时间
|
float lastAccessTime = 0.0f; // 最后访问时间
|
||||||
uint32_t accessCount = 0; // 访问次数
|
uint32_t accessCount = 0; // 访问次数
|
||||||
};
|
};
|
||||||
|
|
||||||
// 异步加载回调类型
|
// 异步加载回调类型
|
||||||
using TextureLoadCallback = std::function<void(Ptr<Texture>)>;
|
using TextureLoadCallback = std::function<void(IntrusivePtr<Texture>)>;
|
||||||
|
|
||||||
class ResourceManager {
|
class ResourceManager {
|
||||||
public:
|
public:
|
||||||
|
|
@ -60,13 +60,13 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// 加载纹理(带缓存)
|
/// 加载纹理(带缓存)
|
||||||
Ptr<Texture> loadTexture(const std::string &filepath);
|
IntrusivePtr<Texture> loadTexture(const std::string &filepath);
|
||||||
|
|
||||||
/// 加载纹理(指定是否异步)
|
/// 加载纹理(指定是否异步)
|
||||||
Ptr<Texture> loadTexture(const std::string &filepath, bool async);
|
IntrusivePtr<Texture> loadTexture(const std::string &filepath, bool async);
|
||||||
|
|
||||||
/// 加载纹理(完整参数:异步 + 压缩格式)
|
/// 加载纹理(完整参数:异步 + 压缩格式)
|
||||||
Ptr<Texture> loadTexture(const std::string &filepath, bool async,
|
IntrusivePtr<Texture> loadTexture(const std::string &filepath, bool async,
|
||||||
TextureFormat format);
|
TextureFormat format);
|
||||||
|
|
||||||
/// 异步加载纹理(带回调)
|
/// 异步加载纹理(带回调)
|
||||||
|
|
@ -78,10 +78,10 @@ public:
|
||||||
TextureLoadCallback callback);
|
TextureLoadCallback callback);
|
||||||
|
|
||||||
/// 加载纹理并生成Alpha遮罩(用于不规则形状图片)
|
/// 加载纹理并生成Alpha遮罩(用于不规则形状图片)
|
||||||
Ptr<Texture> loadTextureWithAlphaMask(const std::string &filepath);
|
IntrusivePtr<Texture> loadTextureWithAlphaMask(const std::string &filepath);
|
||||||
|
|
||||||
/// 通过key获取已缓存的纹理
|
/// 通过key获取已缓存的纹理
|
||||||
Ptr<Texture> getTexture(const std::string &key) const;
|
IntrusivePtr<Texture> getTexture(const std::string &key) const;
|
||||||
|
|
||||||
/// 检查纹理是否已缓存
|
/// 检查纹理是否已缓存
|
||||||
bool hasTexture(const std::string &key) const;
|
bool hasTexture(const std::string &key) const;
|
||||||
|
|
@ -107,11 +107,11 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// 加载字体图集(带缓存)
|
/// 加载字体图集(带缓存)
|
||||||
Ptr<FontAtlas> loadFont(const std::string &filepath, int fontSize,
|
IntrusivePtr<FontAtlas> loadFont(const std::string &filepath, int fontSize,
|
||||||
bool useSDF = false);
|
bool useSDF = false);
|
||||||
|
|
||||||
/// 通过key获取已缓存的字体图集
|
/// 通过key获取已缓存的字体图集
|
||||||
Ptr<FontAtlas> getFont(const std::string &key) const;
|
IntrusivePtr<FontAtlas> getFont(const std::string &key) const;
|
||||||
|
|
||||||
/// 检查字体是否已缓存
|
/// 检查字体是否已缓存
|
||||||
bool hasFont(const std::string &key) const;
|
bool hasFont(const std::string &key) const;
|
||||||
|
|
@ -124,11 +124,11 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// 加载音效(带缓存)
|
/// 加载音效(带缓存)
|
||||||
Ptr<Sound> loadSound(const std::string &filepath);
|
IntrusivePtr<Sound> loadSound(const std::string &filepath);
|
||||||
Ptr<Sound> loadSound(const std::string &name, const std::string &filepath);
|
IntrusivePtr<Sound> loadSound(const std::string &name, const std::string &filepath);
|
||||||
|
|
||||||
/// 通过key获取已缓存的音效
|
/// 通过key获取已缓存的音效
|
||||||
Ptr<Sound> getSound(const std::string &key) const;
|
IntrusivePtr<Sound> getSound(const std::string &key) const;
|
||||||
|
|
||||||
/// 检查音效是否已缓存
|
/// 检查音效是否已缓存
|
||||||
bool hasSound(const std::string &key) const;
|
bool hasSound(const std::string &key) const;
|
||||||
|
|
@ -255,7 +255,7 @@ private:
|
||||||
bool useSDF) const;
|
bool useSDF) const;
|
||||||
|
|
||||||
// 内部加载实现
|
// 内部加载实现
|
||||||
Ptr<Texture> loadTextureInternal(const std::string &filepath,
|
IntrusivePtr<Texture> loadTextureInternal(const std::string &filepath,
|
||||||
TextureFormat format);
|
TextureFormat format);
|
||||||
|
|
||||||
// 选择最佳纹理格式
|
// 选择最佳纹理格式
|
||||||
|
|
@ -273,9 +273,9 @@ private:
|
||||||
mutable std::mutex textFileMutex_;
|
mutable std::mutex textFileMutex_;
|
||||||
mutable std::mutex jsonFileMutex_;
|
mutable std::mutex jsonFileMutex_;
|
||||||
|
|
||||||
// 资源缓存 - 使用弱指针实现自动清理
|
// 资源缓存 - 使用 IntrusivePtr 强引用
|
||||||
std::unordered_map<std::string, WeakPtr<FontAtlas>> fontCache_;
|
std::unordered_map<std::string, IntrusivePtr<FontAtlas>> fontCache_;
|
||||||
std::unordered_map<std::string, WeakPtr<Sound>> soundCache_;
|
std::unordered_map<std::string, IntrusivePtr<Sound>> soundCache_;
|
||||||
|
|
||||||
// 文本文件缓存 - 使用强引用(字符串值类型)
|
// 文本文件缓存 - 使用强引用(字符串值类型)
|
||||||
std::unordered_map<std::string, std::string> textFileCache_;
|
std::unordered_map<std::string, std::string> textFileCache_;
|
||||||
|
|
@ -318,7 +318,7 @@ private:
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
TextureFormat format;
|
TextureFormat format;
|
||||||
TextureLoadCallback callback;
|
TextureLoadCallback callback;
|
||||||
std::promise<Ptr<Texture>> promise;
|
std::promise<IntrusivePtr<Texture>> promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::queue<AsyncLoadTask> asyncTaskQueue_;
|
std::queue<AsyncLoadTask> asyncTaskQueue_;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <core/color.h>
|
#include <core/color.h>
|
||||||
#include <core/rect.h>
|
#include <core/rect.h>
|
||||||
#include <core/types.h>
|
#include <core/types.h>
|
||||||
#include <core/vec2.h>
|
#include <core/vec2.h>
|
||||||
#include <event/event_dispatcher.h>
|
#include <event/event_dispatcher.h>
|
||||||
#include <functional>
|
|
||||||
#include <renderer/renderer.h>
|
#include <renderer/renderer.h>
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -22,7 +19,7 @@ struct RenderCommand;
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 节点基类 - 场景图的基础
|
// 节点基类 - 场景图的基础
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class Node : public std::enable_shared_from_this<Node> {
|
class Node : public RefCounted {
|
||||||
public:
|
public:
|
||||||
Node();
|
Node();
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
|
@ -30,23 +27,23 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 层级管理
|
// 层级管理
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void addChild(Ptr<Node> child);
|
void addChild(IntrusivePtr<Node> child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 批量添加子节点
|
* @brief 批量添加子节点
|
||||||
* @param children 子节点列表
|
* @param children 子节点列表
|
||||||
*/
|
*/
|
||||||
void addChildren(std::vector<Ptr<Node>> &&children);
|
void addChildren(std::vector<IntrusivePtr<Node>> &&children);
|
||||||
|
|
||||||
void removeChild(Ptr<Node> child);
|
void removeChild(IntrusivePtr<Node> child);
|
||||||
void removeChildByName(const std::string &name);
|
void removeChildByName(const std::string &name);
|
||||||
void removeFromParent();
|
void removeFromParent();
|
||||||
void removeAllChildren();
|
void removeAllChildren();
|
||||||
|
|
||||||
Ptr<Node> parent() const { return parent_.lock(); }
|
Node* parent() const { return parent_; }
|
||||||
const std::vector<Ptr<Node>> &children() const { return children_; }
|
const std::vector<IntrusivePtr<Node>> &children() const { return children_; }
|
||||||
Ptr<Node> childByName(const std::string &name) const;
|
IntrusivePtr<Node> childByName(const std::string &name) const;
|
||||||
Ptr<Node> childByTag(int tag) const;
|
IntrusivePtr<Node> childByTag(int tag) const;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 变换属性
|
// 变换属性
|
||||||
|
|
@ -195,17 +192,17 @@ private:
|
||||||
|
|
||||||
// 2. 字符串和容器(24-32字节)
|
// 2. 字符串和容器(24-32字节)
|
||||||
std::string name_; // 32 bytes
|
std::string name_; // 32 bytes
|
||||||
std::vector<Ptr<Node>> children_; // 24 bytes
|
std::vector<IntrusivePtr<Node>> children_; // 24 bytes
|
||||||
|
|
||||||
// 3. 子节点索引(加速查找)
|
// 3. 子节点索引(加速查找)
|
||||||
std::unordered_map<std::string, WeakPtr<Node>> nameIndex_; // 56 bytes
|
std::unordered_map<std::string, Node*> nameIndex_; // 56 bytes
|
||||||
std::unordered_map<int, WeakPtr<Node>> tagIndex_; // 56 bytes
|
std::unordered_map<int, Node*> tagIndex_; // 56 bytes
|
||||||
|
|
||||||
// 4. 事件分发器
|
// 4. 事件分发器
|
||||||
EventDispatcher eventDispatcher_; // 大小取决于实现
|
EventDispatcher eventDispatcher_; // 大小取决于实现
|
||||||
|
|
||||||
// 5. 父节点引用
|
// 5. 父节点引用
|
||||||
WeakPtr<Node> parent_; // 16 bytes
|
Node* parent_ = nullptr; // 8 bytes
|
||||||
|
|
||||||
// 7. 变换属性(按访问频率分组)
|
// 7. 变换属性(按访问频率分组)
|
||||||
Vec2 position_ = Vec2::Zero(); // 8 bytes
|
Vec2 position_ = Vec2::Zero(); // 8 bytes
|
||||||
|
|
@ -237,8 +234,6 @@ private:
|
||||||
bool childrenOrderDirty_ = false; // 1 byte
|
bool childrenOrderDirty_ = false; // 1 byte
|
||||||
bool visible_ = true; // 1 byte
|
bool visible_ = true; // 1 byte
|
||||||
bool running_ = false; // 1 byte
|
bool running_ = false; // 1 byte
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 摄像机
|
// 摄像机
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void setCamera(Ptr<Camera> camera);
|
void setCamera(IntrusivePtr<Camera> camera);
|
||||||
Ptr<Camera> getCamera() const { return camera_; }
|
IntrusivePtr<Camera> getCamera() const { return camera_; }
|
||||||
|
|
||||||
Camera *getActiveCamera() const {
|
Camera *getActiveCamera() const {
|
||||||
return camera_ ? camera_.get() : defaultCamera_.get();
|
return camera_ ? camera_.get() : defaultCamera_.get();
|
||||||
|
|
@ -63,7 +63,7 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 静态创建方法
|
// 静态创建方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static Ptr<Scene> create();
|
static IntrusivePtr<Scene> create();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
|
|
@ -75,8 +75,8 @@ private:
|
||||||
Color backgroundColor_ = Colors::Black;
|
Color backgroundColor_ = Colors::Black;
|
||||||
Size viewportSize_ = Size::Zero();
|
Size viewportSize_ = Size::Zero();
|
||||||
|
|
||||||
Ptr<Camera> camera_;
|
IntrusivePtr<Camera> camera_;
|
||||||
Ptr<Camera> defaultCamera_;
|
IntrusivePtr<Camera> defaultCamera_;
|
||||||
|
|
||||||
bool paused_ = false;
|
bool paused_ = false;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
// 运行第一个场景
|
// 运行第一个场景
|
||||||
void runWithScene(Ptr<Scene> scene);
|
void runWithScene(IntrusivePtr<Scene> scene);
|
||||||
|
|
||||||
// 替换当前场景
|
// 替换当前场景
|
||||||
void replaceScene(Ptr<Scene> scene);
|
void replaceScene(IntrusivePtr<Scene> scene);
|
||||||
|
|
||||||
// 压入新场景(当前场景暂停)
|
// 压入新场景(当前场景暂停)
|
||||||
void pushScene(Ptr<Scene> scene);
|
void pushScene(IntrusivePtr<Scene> scene);
|
||||||
|
|
||||||
// 弹出当前场景(恢复上一个场景)
|
// 弹出当前场景(恢复上一个场景)
|
||||||
void popScene();
|
void popScene();
|
||||||
|
|
@ -49,12 +49,12 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 获取场景
|
// 获取场景
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
Ptr<Scene> getCurrentScene() const;
|
IntrusivePtr<Scene> getCurrentScene() const;
|
||||||
Ptr<Scene> getPreviousScene() const;
|
IntrusivePtr<Scene> getPreviousScene() const;
|
||||||
Ptr<Scene> getRootScene() const;
|
IntrusivePtr<Scene> getRootScene() const;
|
||||||
|
|
||||||
// 通过名称获取场景
|
// 通过名称获取场景
|
||||||
Ptr<Scene> getSceneByName(const std::string &name) const;
|
IntrusivePtr<Scene> getSceneByName(const std::string &name) const;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 查询
|
// 查询
|
||||||
|
|
@ -83,17 +83,17 @@ public:
|
||||||
SceneManager &operator=(const SceneManager &) = delete;
|
SceneManager &operator=(const SceneManager &) = delete;
|
||||||
|
|
||||||
// 场景切换(供 Application 使用)
|
// 场景切换(供 Application 使用)
|
||||||
void enterScene(Ptr<Scene> scene);
|
void enterScene(IntrusivePtr<Scene> scene);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void doSceneSwitch();
|
void doSceneSwitch();
|
||||||
void dispatchPointerEvents(Scene &scene);
|
void dispatchPointerEvents(Scene &scene);
|
||||||
|
|
||||||
std::stack<Ptr<Scene>> sceneStack_;
|
std::stack<IntrusivePtr<Scene>> sceneStack_;
|
||||||
std::unordered_map<std::string, Ptr<Scene>> namedScenes_;
|
std::unordered_map<std::string, IntrusivePtr<Scene>> namedScenes_;
|
||||||
|
|
||||||
// Next scene to switch to (queued during transition)
|
// Next scene to switch to (queued during transition)
|
||||||
Ptr<Scene> nextScene_;
|
IntrusivePtr<Scene> nextScene_;
|
||||||
bool sendCleanupToScene_ = false;
|
bool sendCleanupToScene_ = false;
|
||||||
|
|
||||||
Node *hoverTarget_ = nullptr;
|
Node *hoverTarget_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -23,40 +23,40 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 静态创建方法
|
// 静态创建方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static Ptr<ShapeNode> create();
|
static IntrusivePtr<ShapeNode> create();
|
||||||
|
|
||||||
// 点
|
// 点
|
||||||
static Ptr<ShapeNode> createPoint(const Vec2 &pos, const Color &color);
|
static IntrusivePtr<ShapeNode> createPoint(const Vec2 &pos, const Color &color);
|
||||||
|
|
||||||
// 线
|
// 线
|
||||||
static Ptr<ShapeNode> createLine(const Vec2 &start, const Vec2 &end,
|
static IntrusivePtr<ShapeNode> createLine(const Vec2 &start, const Vec2 &end,
|
||||||
const Color &color, float width = 1.0f);
|
const Color &color, float width = 1.0f);
|
||||||
|
|
||||||
// 矩形
|
// 矩形
|
||||||
static Ptr<ShapeNode> createRect(const Rect &rect, const Color &color,
|
static IntrusivePtr<ShapeNode> createRect(const Rect &rect, const Color &color,
|
||||||
float width = 1.0f);
|
float width = 1.0f);
|
||||||
static Ptr<ShapeNode> createFilledRect(const Rect &rect, const Color &color);
|
static IntrusivePtr<ShapeNode> createFilledRect(const Rect &rect, const Color &color);
|
||||||
|
|
||||||
// 圆形
|
// 圆形
|
||||||
static Ptr<ShapeNode> createCircle(const Vec2 ¢er, float radius,
|
static IntrusivePtr<ShapeNode> createCircle(const Vec2 ¢er, float radius,
|
||||||
const Color &color, int segments = 32,
|
const Color &color, int segments = 32,
|
||||||
float width = 1.0f);
|
float width = 1.0f);
|
||||||
static Ptr<ShapeNode> createFilledCircle(const Vec2 ¢er, float radius,
|
static IntrusivePtr<ShapeNode> createFilledCircle(const Vec2 ¢er, float radius,
|
||||||
const Color &color,
|
const Color &color,
|
||||||
int segments = 32);
|
int segments = 32);
|
||||||
|
|
||||||
// 三角形
|
// 三角形
|
||||||
static Ptr<ShapeNode> createTriangle(const Vec2 &p1, const Vec2 &p2,
|
static IntrusivePtr<ShapeNode> createTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
const Vec2 &p3, const Color &color,
|
const Vec2 &p3, const Color &color,
|
||||||
float width = 1.0f);
|
float width = 1.0f);
|
||||||
static Ptr<ShapeNode> createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
|
static IntrusivePtr<ShapeNode> createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
const Vec2 &p3,
|
const Vec2 &p3,
|
||||||
const Color &color);
|
const Color &color);
|
||||||
|
|
||||||
// 多边形
|
// 多边形
|
||||||
static Ptr<ShapeNode> createPolygon(const std::vector<Vec2> &points,
|
static IntrusivePtr<ShapeNode> createPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color, float width = 1.0f);
|
const Color &color, float width = 1.0f);
|
||||||
static Ptr<ShapeNode> createFilledPolygon(const std::vector<Vec2> &points,
|
static IntrusivePtr<ShapeNode> createFilledPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color);
|
const Color &color);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ namespace extra2d {
|
||||||
class Sprite : public Node {
|
class Sprite : public Node {
|
||||||
public:
|
public:
|
||||||
Sprite();
|
Sprite();
|
||||||
explicit Sprite(Ptr<Texture> texture);
|
explicit Sprite(IntrusivePtr<Texture> texture);
|
||||||
~Sprite() override = default;
|
~Sprite() override = default;
|
||||||
|
|
||||||
// 纹理
|
// 纹理
|
||||||
void setTexture(Ptr<Texture> texture);
|
void setTexture(IntrusivePtr<Texture> texture);
|
||||||
Ptr<Texture> getTexture() const { return texture_; }
|
IntrusivePtr<Texture> getTexture() const { return texture_; }
|
||||||
|
|
||||||
// 纹理矩形 (用于图集)
|
// 纹理矩形 (用于图集)
|
||||||
void setTextureRect(const Rect &rect);
|
void setTextureRect(const Rect &rect);
|
||||||
|
|
@ -33,9 +33,9 @@ public:
|
||||||
bool flipY() const { return flipY_; }
|
bool flipY() const { return flipY_; }
|
||||||
|
|
||||||
// 静态创建方法
|
// 静态创建方法
|
||||||
static Ptr<Sprite> create();
|
static IntrusivePtr<Sprite> create();
|
||||||
static Ptr<Sprite> create(Ptr<Texture> texture);
|
static IntrusivePtr<Sprite> create(IntrusivePtr<Texture> texture);
|
||||||
static Ptr<Sprite> create(Ptr<Texture> texture, const Rect &rect);
|
static IntrusivePtr<Sprite> create(IntrusivePtr<Texture> texture, const Rect &rect);
|
||||||
|
|
||||||
Rect boundingBox() const override;
|
Rect boundingBox() const override;
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ protected:
|
||||||
int zOrder) override;
|
int zOrder) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ptr<Texture> texture_;
|
IntrusivePtr<Texture> texture_;
|
||||||
Rect textureRect_;
|
Rect textureRect_;
|
||||||
Color color_ = Colors::White;
|
Color color_ = Colors::White;
|
||||||
bool flipX_ = false;
|
bool flipX_ = false;
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ EventDispatcher &Application::eventDispatcher() { return *eventDispatcher_; }
|
||||||
|
|
||||||
Camera &Application::camera() { return *camera_; }
|
Camera &Application::camera() { return *camera_; }
|
||||||
|
|
||||||
void Application::enterScene(Ptr<Scene> scene) {
|
void Application::enterScene(IntrusivePtr<Scene> scene) {
|
||||||
if (sceneManager_ && scene) {
|
if (sceneManager_ && scene) {
|
||||||
scene->setViewportSize(static_cast<float>(window_->width()),
|
scene->setViewportSize(static_cast<float>(window_->width()),
|
||||||
static_cast<float>(window_->height()));
|
static_cast<float>(window_->height()));
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@ void AudioEngine::shutdown() {
|
||||||
E2D_LOG_INFO("AudioEngine shutdown");
|
E2D_LOG_INFO("AudioEngine shutdown");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Sound> AudioEngine::loadSound(const std::string &filePath) {
|
IntrusivePtr<Sound> AudioEngine::loadSound(const std::string &filePath) {
|
||||||
return loadSound(filePath, filePath);
|
return loadSound(filePath, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Sound> AudioEngine::loadSound(const std::string &name,
|
IntrusivePtr<Sound> AudioEngine::loadSound(const std::string &name,
|
||||||
const std::string &filePath) {
|
const std::string &filePath) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
E2D_LOG_ERROR("AudioEngine not initialized");
|
E2D_LOG_ERROR("AudioEngine not initialized");
|
||||||
|
|
@ -77,14 +77,14 @@ std::shared_ptr<Sound> AudioEngine::loadSound(const std::string &name,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sound = std::shared_ptr<Sound>(new Sound(name, filePath, chunk));
|
auto sound = IntrusivePtr<Sound>(new Sound(name, filePath, chunk));
|
||||||
sounds_[name] = sound;
|
sounds_[name] = sound;
|
||||||
|
|
||||||
E2D_LOG_DEBUG("Loaded sound: {}", filePath);
|
E2D_LOG_DEBUG("Loaded sound: {}", filePath);
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Sound> AudioEngine::getSound(const std::string &name) {
|
IntrusivePtr<Sound> AudioEngine::getSound(const std::string &name) {
|
||||||
auto it = sounds_.find(name);
|
auto it = sounds_.find(name);
|
||||||
if (it != sounds_.end()) {
|
if (it != sounds_.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
|
||||||
|
|
@ -256,13 +256,13 @@ glm::mat4 GLRenderer::getCurrentTransform() const {
|
||||||
return transformStack_.back();
|
return transformStack_.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Texture> GLRenderer::createTexture(int width, int height,
|
IntrusivePtr<Texture> GLRenderer::createTexture(int width, int height,
|
||||||
const uint8_t *pixels, int channels) {
|
const uint8_t *pixels, int channels) {
|
||||||
return shared<GLTexture>(width, height, pixels, channels);
|
return makeRef<GLTexture>(width, height, pixels, channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Texture> GLRenderer::loadTexture(const std::string &filepath) {
|
IntrusivePtr<Texture> GLRenderer::loadTexture(const std::string &filepath) {
|
||||||
return shared<GLTexture>(filepath);
|
return makeRef<GLTexture>(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRenderer::beginSpriteBatch() { spriteBatch_.begin(viewProjection_); }
|
void GLRenderer::beginSpriteBatch() { spriteBatch_.begin(viewProjection_); }
|
||||||
|
|
@ -476,9 +476,9 @@ void GLRenderer::fillPolygon(const std::vector<Vec2> &points,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath,
|
IntrusivePtr<FontAtlas> GLRenderer::createFontAtlas(const std::string &filepath,
|
||||||
int fontSize, bool useSDF) {
|
int fontSize, bool useSDF) {
|
||||||
return shared<GLFontAtlas>(filepath, fontSize, useSDF);
|
return makeRef<GLFontAtlas>(filepath, fontSize, useSDF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
void GLRenderer::drawText(const FontAtlas &font, const std::string &text,
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ void GLTexture::generateAlphaMask() {
|
||||||
|
|
||||||
PixelFormat GLTexture::getFormat() const { return format_; }
|
PixelFormat GLTexture::getFormat() const { return format_; }
|
||||||
|
|
||||||
Ptr<Texture> GLTexture::create(int width, int height, PixelFormat format) {
|
IntrusivePtr<Texture> GLTexture::create(int width, int height, PixelFormat format) {
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PixelFormat::R8:
|
case PixelFormat::R8:
|
||||||
|
|
@ -457,7 +457,7 @@ Ptr<Texture> GLTexture::create(int width, int height, PixelFormat format) {
|
||||||
channels = 4;
|
channels = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return shared<GLTexture>(width, height, nullptr, channels);
|
return makeRef<GLTexture>(width, height, nullptr, channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ TextureAtlasPage::TextureAtlasPage(int width, int height)
|
||||||
: width_(width), height_(height), isFull_(false), usedArea_(0) {
|
: width_(width), height_(height), isFull_(false), usedArea_(0) {
|
||||||
// 创建空白纹理
|
// 创建空白纹理
|
||||||
std::vector<uint8_t> emptyData(width * height * 4, 0);
|
std::vector<uint8_t> emptyData(width * height * 4, 0);
|
||||||
texture_ = shared<GLTexture>(width, height, emptyData.data(), 4);
|
texture_ = makeRef<GLTexture>(width, height, emptyData.data(), 4);
|
||||||
|
|
||||||
// 初始化矩形打包根节点
|
// 初始化矩形打包根节点
|
||||||
root_ = std::make_unique<PackNode>(0, 0, width, height);
|
root_ = std::make_unique<PackNode>(0, 0, width, height);
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ bool RenderTarget::create(const RenderTargetConfig &config) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderTarget::createFromTexture(Ptr<Texture> texture, bool hasDepth) {
|
bool RenderTarget::createFromTexture(IntrusivePtr<Texture> texture, bool hasDepth) {
|
||||||
if (!texture || !texture->isValid()) {
|
if (!texture || !texture->isValid()) {
|
||||||
E2D_ERROR("无效的颜色纹理");
|
E2D_ERROR("无效的颜色纹理");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -296,9 +296,9 @@ bool RenderTarget::saveToFile(const std::string &filepath) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<RenderTarget>
|
IntrusivePtr<RenderTarget>
|
||||||
RenderTarget::createFromConfig(const RenderTargetConfig &config) {
|
RenderTarget::createFromConfig(const RenderTargetConfig &config) {
|
||||||
auto rt = std::make_shared<RenderTarget>();
|
auto rt = makeRef<RenderTarget>();
|
||||||
if (rt->create(config)) {
|
if (rt->create(config)) {
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
@ -556,7 +556,7 @@ void RenderTargetManager::shutdown() {
|
||||||
E2D_INFO("渲染目标管理器已关闭");
|
E2D_INFO("渲染目标管理器已关闭");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<RenderTarget>
|
IntrusivePtr<RenderTarget>
|
||||||
RenderTargetManager::createRenderTarget(const RenderTargetConfig &config) {
|
RenderTargetManager::createRenderTarget(const RenderTargetConfig &config) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
E2D_ERROR("渲染目标管理器未初始化");
|
E2D_ERROR("渲染目标管理器未初始化");
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ static bool fileExists(const std::string &path) {
|
||||||
|
|
||||||
// 辅助函数:检查是否是 romfs 路径
|
// 辅助函数:检查是否是 romfs 路径
|
||||||
static bool isRomfsPath(const std::string &path) {
|
static bool isRomfsPath(const std::string &path) {
|
||||||
return path.find("romfs:/") == 0 || path.find("romfs:\\") == 0;
|
return path.find("romfs:/") == 0 || path.find("romfs:") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 辅助函数:获取可执行文件所在目录(Windows 平台)
|
// 辅助函数:获取可执行文件所在目录(Windows 平台)
|
||||||
|
|
@ -169,16 +169,16 @@ void ResourceManager::asyncLoadLoop() {
|
||||||
// 纹理资源 - 同步加载
|
// 纹理资源 - 同步加载
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath) {
|
IntrusivePtr<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,
|
IntrusivePtr<Texture> ResourceManager::loadTexture(const std::string &filepath,
|
||||||
bool async) {
|
bool async) {
|
||||||
return loadTexture(filepath, async, TextureFormat::Auto);
|
return loadTexture(filepath, async, TextureFormat::Auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Texture> ResourceManager::loadTexture(const std::string &filepath,
|
IntrusivePtr<Texture> ResourceManager::loadTexture(const std::string &filepath,
|
||||||
bool async, TextureFormat format) {
|
bool async, TextureFormat format) {
|
||||||
if (async) {
|
if (async) {
|
||||||
// 异步加载:返回空指针,实际纹理通过回调获取
|
// 异步加载:返回空指针,实际纹理通过回调获取
|
||||||
|
|
@ -235,7 +235,7 @@ void ResourceManager::loadTextureAsync(const std::string &filepath,
|
||||||
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,
|
IntrusivePtr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath,
|
||||||
TextureFormat format) {
|
TextureFormat format) {
|
||||||
std::lock_guard<std::mutex> lock(textureMutex_);
|
std::lock_guard<std::mutex> lock(textureMutex_);
|
||||||
|
|
||||||
|
|
@ -262,7 +262,7 @@ Ptr<Texture> ResourceManager::loadTextureInternal(const std::string &filepath,
|
||||||
|
|
||||||
// 创建新纹理
|
// 创建新纹理
|
||||||
try {
|
try {
|
||||||
auto texture = shared<GLTexture>(fullPath);
|
auto texture = makeRef<GLTexture>(fullPath);
|
||||||
if (!texture->isValid()) {
|
if (!texture->isValid()) {
|
||||||
E2D_LOG_ERROR("ResourceManager: failed to load texture: {}", filepath);
|
E2D_LOG_ERROR("ResourceManager: failed to load texture: {}", filepath);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -338,7 +338,7 @@ std::vector<uint8_t> ResourceManager::compressTexture(const uint8_t *data,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Texture>
|
IntrusivePtr<Texture>
|
||||||
ResourceManager::loadTextureWithAlphaMask(const std::string &filepath) {
|
ResourceManager::loadTextureWithAlphaMask(const std::string &filepath) {
|
||||||
// 先加载纹理
|
// 先加载纹理
|
||||||
auto texture = loadTexture(filepath);
|
auto texture = loadTexture(filepath);
|
||||||
|
|
@ -389,7 +389,7 @@ bool ResourceManager::hasAlphaMask(const std::string &textureKey) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Texture> ResourceManager::getTexture(const std::string &key) const {
|
IntrusivePtr<Texture> ResourceManager::getTexture(const std::string &key) const {
|
||||||
std::lock_guard<std::mutex> lock(textureMutex_);
|
std::lock_guard<std::mutex> lock(textureMutex_);
|
||||||
|
|
||||||
auto it = textureCache_.find(key);
|
auto it = textureCache_.find(key);
|
||||||
|
|
@ -439,7 +439,7 @@ std::string ResourceManager::makeFontKey(const std::string &filepath,
|
||||||
return filepath + "#" + std::to_string(fontSize) + (useSDF ? "#sdf" : "");
|
return filepath + "#" + std::to_string(fontSize) + (useSDF ? "#sdf" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
|
IntrusivePtr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
|
||||||
int fontSize, bool useSDF) {
|
int fontSize, bool useSDF) {
|
||||||
std::lock_guard<std::mutex> lock(fontMutex_);
|
std::lock_guard<std::mutex> lock(fontMutex_);
|
||||||
|
|
||||||
|
|
@ -448,12 +448,8 @@ Ptr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
auto it = fontCache_.find(key);
|
auto it = fontCache_.find(key);
|
||||||
if (it != fontCache_.end()) {
|
if (it != fontCache_.end()) {
|
||||||
if (auto font = it->second.lock()) {
|
|
||||||
E2D_LOG_TRACE("ResourceManager: font cache hit: {}", key);
|
E2D_LOG_TRACE("ResourceManager: font cache hit: {}", key);
|
||||||
return font;
|
return it->second;
|
||||||
}
|
|
||||||
// 弱引用已失效,移除
|
|
||||||
fontCache_.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析资源路径(优先尝试 romfs:/ 前缀)
|
// 解析资源路径(优先尝试 romfs:/ 前缀)
|
||||||
|
|
@ -465,7 +461,7 @@ Ptr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
|
||||||
|
|
||||||
// 创建新字体图集
|
// 创建新字体图集
|
||||||
try {
|
try {
|
||||||
auto font = shared<GLFontAtlas>(fullPath, fontSize, useSDF);
|
auto font = makeRef<GLFontAtlas>(fullPath, fontSize, useSDF);
|
||||||
if (!font->getTexture() || !font->getTexture()->isValid()) {
|
if (!font->getTexture() || !font->getTexture()->isValid()) {
|
||||||
E2D_LOG_ERROR("ResourceManager: failed to load font: {}", filepath);
|
E2D_LOG_ERROR("ResourceManager: failed to load font: {}", filepath);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -482,24 +478,19 @@ Ptr<FontAtlas> ResourceManager::loadFont(const std::string &filepath,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<FontAtlas> ResourceManager::getFont(const std::string &key) const {
|
IntrusivePtr<FontAtlas> ResourceManager::getFont(const std::string &key) const {
|
||||||
std::lock_guard<std::mutex> lock(fontMutex_);
|
std::lock_guard<std::mutex> lock(fontMutex_);
|
||||||
|
|
||||||
auto it = fontCache_.find(key);
|
auto it = fontCache_.find(key);
|
||||||
if (it != fontCache_.end()) {
|
if (it != fontCache_.end()) {
|
||||||
return it->second.lock();
|
return it->second;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::hasFont(const std::string &key) const {
|
bool ResourceManager::hasFont(const std::string &key) const {
|
||||||
std::lock_guard<std::mutex> lock(fontMutex_);
|
std::lock_guard<std::mutex> lock(fontMutex_);
|
||||||
|
return fontCache_.find(key) != fontCache_.end();
|
||||||
auto it = fontCache_.find(key);
|
|
||||||
if (it != fontCache_.end()) {
|
|
||||||
return !it->second.expired();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::unloadFont(const std::string &key) {
|
void ResourceManager::unloadFont(const std::string &key) {
|
||||||
|
|
@ -512,23 +503,19 @@ void ResourceManager::unloadFont(const std::string &key) {
|
||||||
// 音效资源
|
// 音效资源
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
Ptr<Sound> ResourceManager::loadSound(const std::string &filepath) {
|
IntrusivePtr<Sound> ResourceManager::loadSound(const std::string &filepath) {
|
||||||
return loadSound(filepath, filepath);
|
return loadSound(filepath, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Sound> ResourceManager::loadSound(const std::string &name,
|
IntrusivePtr<Sound> ResourceManager::loadSound(const std::string &name,
|
||||||
const std::string &filepath) {
|
const std::string &filepath) {
|
||||||
std::lock_guard<std::mutex> lock(soundMutex_);
|
std::lock_guard<std::mutex> lock(soundMutex_);
|
||||||
|
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
auto it = soundCache_.find(name);
|
auto it = soundCache_.find(name);
|
||||||
if (it != soundCache_.end()) {
|
if (it != soundCache_.end()) {
|
||||||
if (auto sound = it->second.lock()) {
|
|
||||||
E2D_LOG_TRACE("ResourceManager: sound cache hit: {}", name);
|
E2D_LOG_TRACE("ResourceManager: sound cache hit: {}", name);
|
||||||
return sound;
|
return it->second;
|
||||||
}
|
|
||||||
// 弱引用已失效,移除
|
|
||||||
soundCache_.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析资源路径(优先尝试 romfs:/ 前缀)
|
// 解析资源路径(优先尝试 romfs:/ 前缀)
|
||||||
|
|
@ -551,24 +538,19 @@ Ptr<Sound> ResourceManager::loadSound(const std::string &name,
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Sound> ResourceManager::getSound(const std::string &key) const {
|
IntrusivePtr<Sound> ResourceManager::getSound(const std::string &key) const {
|
||||||
std::lock_guard<std::mutex> lock(soundMutex_);
|
std::lock_guard<std::mutex> lock(soundMutex_);
|
||||||
|
|
||||||
auto it = soundCache_.find(key);
|
auto it = soundCache_.find(key);
|
||||||
if (it != soundCache_.end()) {
|
if (it != soundCache_.end()) {
|
||||||
return it->second.lock();
|
return it->second;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceManager::hasSound(const std::string &key) const {
|
bool ResourceManager::hasSound(const std::string &key) const {
|
||||||
std::lock_guard<std::mutex> lock(soundMutex_);
|
std::lock_guard<std::mutex> lock(soundMutex_);
|
||||||
|
return soundCache_.find(key) != soundCache_.end();
|
||||||
auto it = soundCache_.find(key);
|
|
||||||
if (it != soundCache_.end()) {
|
|
||||||
return !it->second.expired();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::unloadSound(const std::string &key) {
|
void ResourceManager::unloadSound(const std::string &key) {
|
||||||
|
|
@ -586,31 +568,8 @@ void ResourceManager::unloadSound(const std::string &key) {
|
||||||
|
|
||||||
void ResourceManager::purgeUnused() {
|
void ResourceManager::purgeUnused() {
|
||||||
// 纹理缓存使用LRU策略,不需要清理失效引用
|
// 纹理缓存使用LRU策略,不需要清理失效引用
|
||||||
// 字体缓存
|
// 字体和音效缓存使用 IntrusivePtr 强引用,不需要清理失效引用
|
||||||
{
|
// 当外部没有引用时,缓存会自动释放
|
||||||
std::lock_guard<std::mutex> lock(fontMutex_);
|
|
||||||
for (auto it = fontCache_.begin(); it != fontCache_.end();) {
|
|
||||||
if (it->second.expired()) {
|
|
||||||
E2D_LOG_TRACE("ResourceManager: purging unused font: {}", it->first);
|
|
||||||
it = fontCache_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 音效缓存
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(soundMutex_);
|
|
||||||
for (auto it = soundCache_.begin(); it != soundCache_.end();) {
|
|
||||||
if (it->second.expired()) {
|
|
||||||
E2D_LOG_TRACE("ResourceManager: purging unused sound: {}", it->first);
|
|
||||||
it = soundCache_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::clearTextureCache() {
|
void ResourceManager::clearTextureCache() {
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,22 @@ Node::Node() = default;
|
||||||
|
|
||||||
Node::~Node() { removeAllChildren(); }
|
Node::~Node() { removeAllChildren(); }
|
||||||
|
|
||||||
void Node::addChild(Ptr<Node> child) {
|
void Node::addChild(IntrusivePtr<Node> child) {
|
||||||
if (!child || child.get() == this) {
|
if (!child || child.get() == this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
child->removeFromParent();
|
child->removeFromParent();
|
||||||
child->parent_ = weak_from_this();
|
child->parent_ = this;
|
||||||
children_.push_back(child);
|
children_.push_back(child);
|
||||||
childrenOrderDirty_ = true;
|
childrenOrderDirty_ = true;
|
||||||
|
|
||||||
// 更新索引
|
// 更新索引
|
||||||
if (!child->name().empty()) {
|
if (!child->name().empty()) {
|
||||||
nameIndex_[child->name()] = child;
|
nameIndex_[child->name()] = child.get();
|
||||||
}
|
}
|
||||||
if (child->tag() != -1) {
|
if (child->tag() != -1) {
|
||||||
tagIndex_[child->tag()] = child;
|
tagIndex_[child->tag()] = child.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (running_) {
|
if (running_) {
|
||||||
|
|
@ -37,7 +37,7 @@ void Node::addChild(Ptr<Node> child) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::addChildren(std::vector<Ptr<Node>> &&children) {
|
void Node::addChildren(std::vector<IntrusivePtr<Node>> &&children) {
|
||||||
// 预留空间,避免多次扩容
|
// 预留空间,避免多次扩容
|
||||||
size_t newSize = children_.size() + children.size();
|
size_t newSize = children_.size() + children.size();
|
||||||
if (newSize > children_.capacity()) {
|
if (newSize > children_.capacity()) {
|
||||||
|
|
@ -50,15 +50,15 @@ void Node::addChildren(std::vector<Ptr<Node>> &&children) {
|
||||||
}
|
}
|
||||||
|
|
||||||
child->removeFromParent();
|
child->removeFromParent();
|
||||||
child->parent_ = weak_from_this();
|
child->parent_ = this;
|
||||||
children_.push_back(child);
|
children_.push_back(child);
|
||||||
|
|
||||||
// 更新索引
|
// 更新索引
|
||||||
if (!child->name().empty()) {
|
if (!child->name().empty()) {
|
||||||
nameIndex_[child->name()] = child;
|
nameIndex_[child->name()] = child.get();
|
||||||
}
|
}
|
||||||
if (child->tag() != -1) {
|
if (child->tag() != -1) {
|
||||||
tagIndex_[child->tag()] = child;
|
tagIndex_[child->tag()] = child.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (running_) {
|
if (running_) {
|
||||||
|
|
@ -74,7 +74,7 @@ void Node::addChildren(std::vector<Ptr<Node>> &&children) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::removeChild(Ptr<Node> child) {
|
void Node::removeChild(IntrusivePtr<Node> child) {
|
||||||
if (!child)
|
if (!child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ void Node::removeChild(Ptr<Node> child) {
|
||||||
if ((*it)->tag() != -1) {
|
if ((*it)->tag() != -1) {
|
||||||
tagIndex_.erase((*it)->tag());
|
tagIndex_.erase((*it)->tag());
|
||||||
}
|
}
|
||||||
(*it)->parent_.reset();
|
(*it)->parent_ = nullptr;
|
||||||
children_.erase(it);
|
children_.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,18 +107,9 @@ void Node::removeChildByName(const std::string &name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::removeFromParent() {
|
void Node::removeFromParent() {
|
||||||
auto p = parent_.lock();
|
auto p = parent_;
|
||||||
if (p) {
|
if (p) {
|
||||||
// 安全获取 shared_ptr,避免在对象未由 shared_ptr 管理时崩溃
|
p->removeChild(IntrusivePtr<Node>(this));
|
||||||
Ptr<Node> self;
|
|
||||||
try {
|
|
||||||
self = shared_from_this();
|
|
||||||
} catch (const std::bad_weak_ptr &) {
|
|
||||||
// 对象不是由 shared_ptr 管理的,直接重置父节点引用
|
|
||||||
parent_.reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p->removeChild(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,27 +119,27 @@ void Node::removeAllChildren() {
|
||||||
child->onDetachFromScene();
|
child->onDetachFromScene();
|
||||||
child->onExit();
|
child->onExit();
|
||||||
}
|
}
|
||||||
child->parent_.reset();
|
child->parent_ = nullptr;
|
||||||
}
|
}
|
||||||
children_.clear();
|
children_.clear();
|
||||||
nameIndex_.clear();
|
nameIndex_.clear();
|
||||||
tagIndex_.clear();
|
tagIndex_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Node> Node::childByName(const std::string &name) const {
|
IntrusivePtr<Node> Node::childByName(const std::string &name) const {
|
||||||
// 使用哈希索引,O(1) 查找
|
// 使用哈希索引,O(1) 查找
|
||||||
auto it = nameIndex_.find(name);
|
auto it = nameIndex_.find(name);
|
||||||
if (it != nameIndex_.end()) {
|
if (it != nameIndex_.end()) {
|
||||||
return it->second.lock();
|
return IntrusivePtr<Node>(it->second);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Node> Node::childByTag(int tag) const {
|
IntrusivePtr<Node> Node::childByTag(int tag) const {
|
||||||
// 使用哈希索引,O(1) 查找
|
// 使用哈希索引,O(1) 查找
|
||||||
auto it = tagIndex_.find(tag);
|
auto it = tagIndex_.find(tag);
|
||||||
if (it != tagIndex_.end()) {
|
if (it != tagIndex_.end()) {
|
||||||
return it->second.lock();
|
return IntrusivePtr<Node>(it->second);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -261,8 +252,7 @@ glm::mat4 Node::getWorldTransform() const {
|
||||||
const Node *current = this;
|
const Node *current = this;
|
||||||
while (current && chainCount < nodeChainCache.size()) {
|
while (current && chainCount < nodeChainCache.size()) {
|
||||||
nodeChainCache[chainCount++] = current;
|
nodeChainCache[chainCount++] = current;
|
||||||
auto p = current->parent_.lock();
|
current = current->parent_;
|
||||||
current = p.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从根节点开始计算
|
// 从根节点开始计算
|
||||||
|
|
@ -297,7 +287,7 @@ void Node::batchUpdateTransforms() {
|
||||||
|
|
||||||
// 如果世界变换脏了,需要重新计算
|
// 如果世界变换脏了,需要重新计算
|
||||||
if (worldTransformDirty_) {
|
if (worldTransformDirty_) {
|
||||||
auto parent = parent_.lock();
|
auto parent = parent_;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
// 使用父节点的世界变换(确保父节点已经更新)
|
// 使用父节点的世界变换(确保父节点已经更新)
|
||||||
worldTransform_ = parent->getWorldTransform() * localTransform_;
|
worldTransform_ = parent->getWorldTransform() * localTransform_;
|
||||||
|
|
@ -403,7 +393,7 @@ void Node::sortChildren() {
|
||||||
} else {
|
} else {
|
||||||
// 大数组使用标准排序
|
// 大数组使用标准排序
|
||||||
std::sort(children_.begin(), children_.end(),
|
std::sort(children_.begin(), children_.end(),
|
||||||
[](const Ptr<Node> &a, const Ptr<Node> &b) {
|
[](const IntrusivePtr<Node> &a, const IntrusivePtr<Node> &b) {
|
||||||
return a->zOrder() < b->zOrder();
|
return a->zOrder() < b->zOrder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
Scene::Scene() { defaultCamera_ = shared<Camera>(); }
|
Scene::Scene() { defaultCamera_ = makeRef<Camera>(); }
|
||||||
|
|
||||||
void Scene::setCamera(Ptr<Camera> camera) { camera_ = camera; }
|
void Scene::setCamera(IntrusivePtr<Camera> camera) { camera_ = camera; }
|
||||||
|
|
||||||
void Scene::setViewportSize(float width, float height) {
|
void Scene::setViewportSize(float width, float height) {
|
||||||
viewportSize_ = Size(width, height);
|
viewportSize_ = Size(width, height);
|
||||||
|
|
@ -68,6 +68,6 @@ void Scene::collectRenderCommands(std::vector<RenderCommand> &commands,
|
||||||
Node::collectRenderCommands(commands, parentZOrder);
|
Node::collectRenderCommands(commands, parentZOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Scene> Scene::create() { return shared<Scene>(); }
|
IntrusivePtr<Scene> Scene::create() { return makeRef<Scene>(); }
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ namespace extra2d {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Node *hitTestTopmost(const Ptr<Node> &node, const Vec2 &worldPos) {
|
Node *hitTestTopmost(const IntrusivePtr<Node> &node, const Vec2 &worldPos) {
|
||||||
if (!node || !node->visible()) {
|
if (!node || !node->visible()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Ptr<Node>> children = node->children();
|
std::vector<IntrusivePtr<Node>> children = node->children();
|
||||||
std::stable_sort(children.begin(), children.end(),
|
std::stable_sort(children.begin(), children.end(),
|
||||||
[](const Ptr<Node> &a, const Ptr<Node> &b) {
|
[](const IntrusivePtr<Node> &a, const IntrusivePtr<Node> &b) {
|
||||||
return a->zOrder() < b->zOrder();
|
return a->zOrder() < b->zOrder();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ SceneManager &SceneManager::getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::runWithScene(Ptr<Scene> scene) {
|
void SceneManager::runWithScene(IntrusivePtr<Scene> scene) {
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ void SceneManager::runWithScene(Ptr<Scene> scene) {
|
||||||
sceneStack_.push(scene);
|
sceneStack_.push(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::replaceScene(Ptr<Scene> scene) {
|
void SceneManager::replaceScene(IntrusivePtr<Scene> scene) {
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ void SceneManager::replaceScene(Ptr<Scene> scene) {
|
||||||
sceneStack_.push(scene);
|
sceneStack_.push(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::enterScene(Ptr<Scene> scene) {
|
void SceneManager::enterScene(IntrusivePtr<Scene> scene) {
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ void SceneManager::enterScene(Ptr<Scene> scene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::pushScene(Ptr<Scene> scene) {
|
void SceneManager::pushScene(IntrusivePtr<Scene> scene) {
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -154,8 +154,8 @@ void SceneManager::popToRootScene() {
|
||||||
|
|
||||||
void SceneManager::popToScene(const std::string &name) {
|
void SceneManager::popToScene(const std::string &name) {
|
||||||
// Find target scene in stack
|
// Find target scene in stack
|
||||||
std::stack<Ptr<Scene>> tempStack;
|
std::stack<IntrusivePtr<Scene>> tempStack;
|
||||||
Ptr<Scene> target = nullptr;
|
IntrusivePtr<Scene> target = nullptr;
|
||||||
|
|
||||||
while (!sceneStack_.empty()) {
|
while (!sceneStack_.empty()) {
|
||||||
auto scene = sceneStack_.top();
|
auto scene = sceneStack_.top();
|
||||||
|
|
@ -173,14 +173,14 @@ void SceneManager::popToScene(const std::string &name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Scene> SceneManager::getCurrentScene() const {
|
IntrusivePtr<Scene> SceneManager::getCurrentScene() const {
|
||||||
if (sceneStack_.empty()) {
|
if (sceneStack_.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return sceneStack_.top();
|
return sceneStack_.top();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Scene> SceneManager::getPreviousScene() const {
|
IntrusivePtr<Scene> SceneManager::getPreviousScene() const {
|
||||||
if (sceneStack_.size() < 2) {
|
if (sceneStack_.size() < 2) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -191,14 +191,14 @@ Ptr<Scene> SceneManager::getPreviousScene() const {
|
||||||
return tempStack.top();
|
return tempStack.top();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Scene> SceneManager::getRootScene() const {
|
IntrusivePtr<Scene> SceneManager::getRootScene() const {
|
||||||
if (sceneStack_.empty()) {
|
if (sceneStack_.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy stack to access bottom
|
// Copy stack to access bottom
|
||||||
auto tempStack = sceneStack_;
|
auto tempStack = sceneStack_;
|
||||||
Ptr<Scene> root;
|
IntrusivePtr<Scene> root;
|
||||||
while (!tempStack.empty()) {
|
while (!tempStack.empty()) {
|
||||||
root = tempStack.top();
|
root = tempStack.top();
|
||||||
tempStack.pop();
|
tempStack.pop();
|
||||||
|
|
@ -206,7 +206,7 @@ Ptr<Scene> SceneManager::getRootScene() const {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Scene> SceneManager::getSceneByName(const std::string &name) const {
|
IntrusivePtr<Scene> SceneManager::getSceneByName(const std::string &name) const {
|
||||||
auto it = namedScenes_.find(name);
|
auto it = namedScenes_.find(name);
|
||||||
if (it != namedScenes_.end()) {
|
if (it != namedScenes_.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
@ -285,7 +285,7 @@ void SceneManager::dispatchPointerEvents(Scene &scene) {
|
||||||
worldPos = camera->screenToWorld(screenPos);
|
worldPos = camera->screenToWorld(screenPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Node> root = scene.shared_from_this();
|
IntrusivePtr<Node> root = IntrusivePtr<Node>(&scene);
|
||||||
Node *newHover = hitTestTopmost(root, worldPos);
|
Node *newHover = hitTestTopmost(root, worldPos);
|
||||||
|
|
||||||
if (newHover != hoverTarget_) {
|
if (newHover != hoverTarget_) {
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,19 @@ namespace extra2d {
|
||||||
|
|
||||||
ShapeNode::ShapeNode() = default;
|
ShapeNode::ShapeNode() = default;
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::create() { return shared<ShapeNode>(); }
|
IntrusivePtr<ShapeNode> ShapeNode::create() { return makeRef<ShapeNode>(); }
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createPoint(const Vec2 &pos, const Color &color) {
|
IntrusivePtr<ShapeNode> ShapeNode::createPoint(const Vec2 &pos, const Color &color) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Point;
|
node->shapeType_ = ShapeType::Point;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->points_ = {pos};
|
node->points_ = {pos};
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end,
|
IntrusivePtr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end,
|
||||||
const Color &color, float width) {
|
const Color &color, float width) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Line;
|
node->shapeType_ = ShapeType::Line;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->lineWidth_ = width;
|
node->lineWidth_ = width;
|
||||||
|
|
@ -29,9 +29,9 @@ Ptr<ShapeNode> ShapeNode::createLine(const Vec2 &start, const Vec2 &end,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createRect(const Rect &rect, const Color &color,
|
IntrusivePtr<ShapeNode> ShapeNode::createRect(const Rect &rect, const Color &color,
|
||||||
float width) {
|
float width) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Rect;
|
node->shapeType_ = ShapeType::Rect;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->lineWidth_ = width;
|
node->lineWidth_ = width;
|
||||||
|
|
@ -42,17 +42,17 @@ Ptr<ShapeNode> ShapeNode::createRect(const Rect &rect, const Color &color,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createFilledRect(const Rect &rect,
|
IntrusivePtr<ShapeNode> ShapeNode::createFilledRect(const Rect &rect,
|
||||||
const Color &color) {
|
const Color &color) {
|
||||||
auto node = createRect(rect, color, 0);
|
auto node = createRect(rect, color, 0);
|
||||||
node->filled_ = true;
|
node->filled_ = true;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createCircle(const Vec2 ¢er, float radius,
|
IntrusivePtr<ShapeNode> ShapeNode::createCircle(const Vec2 ¢er, float radius,
|
||||||
const Color &color, int segments,
|
const Color &color, int segments,
|
||||||
float width) {
|
float width) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Circle;
|
node->shapeType_ = ShapeType::Circle;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->lineWidth_ = width;
|
node->lineWidth_ = width;
|
||||||
|
|
@ -64,17 +64,17 @@ Ptr<ShapeNode> ShapeNode::createCircle(const Vec2 ¢er, float radius,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createFilledCircle(const Vec2 ¢er, float radius,
|
IntrusivePtr<ShapeNode> ShapeNode::createFilledCircle(const Vec2 ¢er, float radius,
|
||||||
const Color &color, int segments) {
|
const Color &color, int segments) {
|
||||||
auto node = createCircle(center, radius, color, segments, 0);
|
auto node = createCircle(center, radius, color, segments, 0);
|
||||||
node->filled_ = true;
|
node->filled_ = true;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createTriangle(const Vec2 &p1, const Vec2 &p2,
|
IntrusivePtr<ShapeNode> ShapeNode::createTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
const Vec2 &p3, const Color &color,
|
const Vec2 &p3, const Color &color,
|
||||||
float width) {
|
float width) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Triangle;
|
node->shapeType_ = ShapeType::Triangle;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->lineWidth_ = width;
|
node->lineWidth_ = width;
|
||||||
|
|
@ -83,7 +83,7 @@ Ptr<ShapeNode> ShapeNode::createTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
|
IntrusivePtr<ShapeNode> ShapeNode::createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
const Vec2 &p3,
|
const Vec2 &p3,
|
||||||
const Color &color) {
|
const Color &color) {
|
||||||
auto node = createTriangle(p1, p2, p3, color, 0);
|
auto node = createTriangle(p1, p2, p3, color, 0);
|
||||||
|
|
@ -91,9 +91,9 @@ Ptr<ShapeNode> ShapeNode::createFilledTriangle(const Vec2 &p1, const Vec2 &p2,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createPolygon(const std::vector<Vec2> &points,
|
IntrusivePtr<ShapeNode> ShapeNode::createPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color, float width) {
|
const Color &color, float width) {
|
||||||
auto node = shared<ShapeNode>();
|
auto node = makeRef<ShapeNode>();
|
||||||
node->shapeType_ = ShapeType::Polygon;
|
node->shapeType_ = ShapeType::Polygon;
|
||||||
node->color_ = color;
|
node->color_ = color;
|
||||||
node->lineWidth_ = width;
|
node->lineWidth_ = width;
|
||||||
|
|
@ -102,7 +102,7 @@ Ptr<ShapeNode> ShapeNode::createPolygon(const std::vector<Vec2> &points,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<ShapeNode> ShapeNode::createFilledPolygon(const std::vector<Vec2> &points,
|
IntrusivePtr<ShapeNode> ShapeNode::createFilledPolygon(const std::vector<Vec2> &points,
|
||||||
const Color &color) {
|
const Color &color) {
|
||||||
auto node = createPolygon(points, color, 0);
|
auto node = createPolygon(points, color, 0);
|
||||||
node->filled_ = true;
|
node->filled_ = true;
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ namespace extra2d {
|
||||||
|
|
||||||
Sprite::Sprite() = default;
|
Sprite::Sprite() = default;
|
||||||
|
|
||||||
Sprite::Sprite(Ptr<Texture> texture) { setTexture(texture); }
|
Sprite::Sprite(IntrusivePtr<Texture> texture) { setTexture(texture); }
|
||||||
|
|
||||||
void Sprite::setTexture(Ptr<Texture> texture) {
|
void Sprite::setTexture(IntrusivePtr<Texture> texture) {
|
||||||
texture_ = texture;
|
texture_ = texture;
|
||||||
if (texture_) {
|
if (texture_) {
|
||||||
textureRect_ = Rect(0, 0, static_cast<float>(texture_->width()),
|
textureRect_ = Rect(0, 0, static_cast<float>(texture_->width()),
|
||||||
|
|
@ -27,14 +27,14 @@ void Sprite::setFlipX(bool flip) { flipX_ = flip; }
|
||||||
|
|
||||||
void Sprite::setFlipY(bool flip) { flipY_ = flip; }
|
void Sprite::setFlipY(bool flip) { flipY_ = flip; }
|
||||||
|
|
||||||
Ptr<Sprite> Sprite::create() { return shared<Sprite>(); }
|
IntrusivePtr<Sprite> Sprite::create() { return makeRef<Sprite>(); }
|
||||||
|
|
||||||
Ptr<Sprite> Sprite::create(Ptr<Texture> texture) {
|
IntrusivePtr<Sprite> Sprite::create(IntrusivePtr<Texture> texture) {
|
||||||
return shared<Sprite>(texture);
|
return makeRef<Sprite>(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Sprite> Sprite::create(Ptr<Texture> texture, const Rect &rect) {
|
IntrusivePtr<Sprite> Sprite::create(IntrusivePtr<Texture> texture, const Rect &rect) {
|
||||||
auto sprite = shared<Sprite>(texture);
|
auto sprite = makeRef<Sprite>(texture);
|
||||||
sprite->setTextureRect(rect);
|
sprite->setTextureRect(rect);
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue