refactor(core): 统一命名规范并优化核心模块结构
重构智能指针、基础类型和核心组件的命名,使用更简洁一致的命名风格: - 将 UniquePtr/SharedPtr 简化为 Unique/Ref - 基础类型使用 i32/u32/f32 等更短名称 - 方法名统一为小写驼峰,如 getServiceInfo() 改为 info() - 模块初始化方法 parallel() 替代 allowParallelInit() 新增核心组件: - 添加 ObjectPool 对象池模板类 - 添加 RingBuffer 环形缓冲区模板类 - 添加编译期类型ID生成机制 优化现有组件: - 事件队列改用 RingBuffer 实现 - 服务注册表改用数组存储提高缓存友好性 - 模块依赖管理算法优化 - 统一时间相关参数为 f32/f64 类型 移除冗余代码,简化接口设计,提升整体代码一致性和性能
This commit is contained in:
parent
f9e244299f
commit
b41e96d870
|
|
@ -0,0 +1,199 @@
|
||||||
|
# Extra2D 资源服务设计计划
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
设计一个现代化的资源服务,支持高效的资源管理、存储和访问功能。采用设计模式确保代码的可扩展性、可维护性和性能。
|
||||||
|
|
||||||
|
## 2. 设计目标
|
||||||
|
|
||||||
|
- **高效缓存**: 避免重复加载相同资源
|
||||||
|
- **类型安全**: 使用模板和强类型ID
|
||||||
|
- **异步加载**: 支持后台加载大资源
|
||||||
|
- **内存管理**: 自动释放未使用资源
|
||||||
|
- **扩展性**: 易于添加新资源类型
|
||||||
|
|
||||||
|
## 3. 核心组件设计
|
||||||
|
|
||||||
|
### 3.1 资源类型枚举
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
enum class AssetType {
|
||||||
|
Texture, // 纹理/图片
|
||||||
|
Font, // 字体
|
||||||
|
Shader, // 着色器
|
||||||
|
Audio, // 音频
|
||||||
|
Data, // 通用数据
|
||||||
|
Custom // 自定义类型
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 资源句柄 (Resource Handle)
|
||||||
|
|
||||||
|
使用强类型句柄替代裸指针,提供类型安全和生命周期管理:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename T>
|
||||||
|
class AssetHandle {
|
||||||
|
AssetID id_;
|
||||||
|
Weak<T> cacheRef_;
|
||||||
|
public:
|
||||||
|
bool valid() const;
|
||||||
|
Ref<T> get() const;
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 资源基类
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Asset {
|
||||||
|
public:
|
||||||
|
virtual ~Asset() = default;
|
||||||
|
virtual AssetType type() const = 0;
|
||||||
|
virtual bool loaded() const = 0;
|
||||||
|
virtual size_t memorySize() const = 0;
|
||||||
|
|
||||||
|
const AssetID& id() const { return id_; }
|
||||||
|
const std::string& path() const { return path_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AssetID id_;
|
||||||
|
std::string path_;
|
||||||
|
std::atomic<bool> loaded_{false};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 具体资源类型
|
||||||
|
|
||||||
|
#### 纹理资源
|
||||||
|
```cpp
|
||||||
|
class TextureAsset : public Asset {
|
||||||
|
public:
|
||||||
|
AssetType type() const override { return AssetType::Texture; }
|
||||||
|
|
||||||
|
int width() const { return width_; }
|
||||||
|
int height() const { return height_; }
|
||||||
|
int channels() const { return channels_; }
|
||||||
|
const u8* data() const { return data_.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int width_ = 0;
|
||||||
|
int height_ = 0;
|
||||||
|
int channels_ = 0;
|
||||||
|
Unique<u8[]> data_;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 字体资源
|
||||||
|
```cpp
|
||||||
|
class FontAsset : public Asset {
|
||||||
|
public:
|
||||||
|
AssetType type() const override { return AssetType::Font; }
|
||||||
|
|
||||||
|
const stbtt_fontinfo& info() const { return info_; }
|
||||||
|
float scaleForPixelHeight(float pixels) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<u8> data_;
|
||||||
|
stbtt_fontinfo info_;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 着色器资源
|
||||||
|
```cpp
|
||||||
|
class ShaderAsset : public Asset {
|
||||||
|
public:
|
||||||
|
AssetType type() const override { return AssetType::Shader; }
|
||||||
|
|
||||||
|
const std::string& vertexSource() const { return vertexSrc_; }
|
||||||
|
const std::string& fragmentSource() const { return fragmentSrc_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string vertexSrc_;
|
||||||
|
std::string fragmentSrc_;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 服务接口设计
|
||||||
|
|
||||||
|
### 4.1 资源服务接口
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class IAssetService : public IService {
|
||||||
|
public:
|
||||||
|
virtual ~IAssetService() = default;
|
||||||
|
|
||||||
|
// 同步加载
|
||||||
|
template<typename T>
|
||||||
|
AssetHandle<T> load(const std::string& path);
|
||||||
|
|
||||||
|
// 异步加载
|
||||||
|
template<typename T>
|
||||||
|
void loadAsync(const std::string& path, AssetLoadCallback<T> callback);
|
||||||
|
|
||||||
|
// 获取已缓存资源
|
||||||
|
template<typename T>
|
||||||
|
AssetHandle<T> get(const std::string& path);
|
||||||
|
|
||||||
|
// 卸载资源
|
||||||
|
virtual void unload(const AssetID& id) = 0;
|
||||||
|
virtual void unloadAll() = 0;
|
||||||
|
|
||||||
|
// 缓存管理
|
||||||
|
virtual void setCacheLimit(size_t maxBytes) = 0;
|
||||||
|
virtual size_t cacheSize() const = 0;
|
||||||
|
virtual void gc() = 0; // 垃圾回收
|
||||||
|
|
||||||
|
// 注册加载器
|
||||||
|
template<typename T>
|
||||||
|
void registerLoader(Unique<AssetLoader<T>> loader);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 资源加载器接口
|
||||||
|
|
||||||
|
使用**策略模式**支持不同资源类型的加载:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename T>
|
||||||
|
class AssetLoader {
|
||||||
|
public:
|
||||||
|
virtual ~AssetLoader() = default;
|
||||||
|
virtual Unique<T> load(const std::string& path) = 0;
|
||||||
|
virtual bool canLoad(const std::string& path) const = 0;
|
||||||
|
virtual AssetType type() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 纹理加载器
|
||||||
|
class TextureLoader : public AssetLoader<TextureAsset> {
|
||||||
|
public:
|
||||||
|
Unique<TextureAsset> load(const std::string& path) override;
|
||||||
|
bool canLoad(const std::string& path) const override;
|
||||||
|
AssetType type() const override { return AssetType::Texture; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 字体加载器
|
||||||
|
class FontLoader : public AssetLoader<FontAsset> {
|
||||||
|
public:
|
||||||
|
Unique<FontAsset> load(const std::string& path) override;
|
||||||
|
bool canLoad(const std::string& path) const override;
|
||||||
|
AssetType type() const override { return AssetType::Font; }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 实现架构
|
||||||
|
|
||||||
|
### 5.1 类图
|
||||||
|
|
||||||
|
```
|
||||||
|
IService
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
IAssetService (接口)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
AssetService (实现)
|
||||||
|
│
|
||||||
|
┌──────────────┼──────────────┐
|
||||||
|
│ │ │
|
||||||
|
▼ ▼ ▼
|
||||||
|
|
@ -76,8 +76,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
bool isPaused() const { return paused_; }
|
bool paused() const { return paused_; }
|
||||||
bool isRunning() const { return running_; }
|
bool running() const { return running_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口
|
* @brief 获取窗口
|
||||||
|
|
@ -85,9 +85,9 @@ public:
|
||||||
*/
|
*/
|
||||||
GLFWWindow *window();
|
GLFWWindow *window();
|
||||||
|
|
||||||
float deltaTime() const { return deltaTime_; }
|
f32 dt() const { return dt_; }
|
||||||
float totalTime() const { return totalTime_; }
|
f32 totalTime() const { return totalTime_; }
|
||||||
int fps() const { return currentFps_; }
|
int fps() const { return fps_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Application();
|
Application();
|
||||||
|
|
@ -102,12 +102,12 @@ private:
|
||||||
bool paused_ = false;
|
bool paused_ = false;
|
||||||
bool shouldQuit_ = false;
|
bool shouldQuit_ = false;
|
||||||
|
|
||||||
float deltaTime_ = 0.0f;
|
f32 dt_ = 0.0f;
|
||||||
float totalTime_ = 0.0f;
|
f32 totalTime_ = 0.0f;
|
||||||
double lastFrameTime_ = 0.0;
|
f64 lastFrameTime_ = 0.0;
|
||||||
int frameCount_ = 0;
|
int frameCount_ = 0;
|
||||||
float fpsTimer_ = 0.0f;
|
f32 fpsTimer_ = 0.0f;
|
||||||
int currentFps_ = 0;
|
int fps_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public:
|
||||||
* @brief 检查模块是否支持并行初始化
|
* @brief 检查模块是否支持并行初始化
|
||||||
* @return 支持并行初始化返回 true
|
* @return 支持并行初始化返回 true
|
||||||
*/
|
*/
|
||||||
virtual bool allowParallelInit() const { return true; }
|
virtual bool parallel() const { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置所属Application
|
* @brief 设置所属Application
|
||||||
|
|
@ -77,6 +77,6 @@ protected:
|
||||||
/**
|
/**
|
||||||
* @brief 模块工厂函数类型
|
* @brief 模块工厂函数类型
|
||||||
*/
|
*/
|
||||||
using ModuleFactory = std::function<UniquePtr<Module>()>;
|
using ModuleFactory = std::function<Unique<Module>()>;
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <extra2d/core/types.h>
|
||||||
|
#include <array>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 固定大小对象池
|
||||||
|
* @tparam T 对象类型
|
||||||
|
* @tparam Size 池大小
|
||||||
|
*/
|
||||||
|
template <typename T, size_t Size>
|
||||||
|
class ObjectPool {
|
||||||
|
public:
|
||||||
|
ObjectPool() {
|
||||||
|
for (size_t i = 0; i < Size; ++i) {
|
||||||
|
available_.push(&pool_[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取对象
|
||||||
|
* @return 对象指针,池耗尽返回nullptr
|
||||||
|
*/
|
||||||
|
T* acquire() {
|
||||||
|
if (available_.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
T* obj = available_.front();
|
||||||
|
available_.pop();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放对象回池
|
||||||
|
* @param obj 对象指针
|
||||||
|
*/
|
||||||
|
void release(T* obj) {
|
||||||
|
if (obj >= pool_.data() && obj < pool_.data() + Size) {
|
||||||
|
obj->~T();
|
||||||
|
new (obj) T();
|
||||||
|
available_.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取可用对象数量
|
||||||
|
*/
|
||||||
|
size_t available() const { return available_.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取池总大小
|
||||||
|
*/
|
||||||
|
static constexpr size_t capacity() { return Size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
alignas(alignof(T)) std::array<u8, sizeof(T) * Size> storage_;
|
||||||
|
T* pool_ = reinterpret_cast<T*>(storage_.data());
|
||||||
|
std::queue<T*> available_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <extra2d/core/module.h>
|
#include <extra2d/core/module.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <unordered_map>
|
#include <array>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -12,12 +12,32 @@ namespace extra2d {
|
||||||
|
|
||||||
class Application;
|
class Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 编译期类型ID生成器
|
||||||
|
*/
|
||||||
|
using TypeId = size_t;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
inline TypeId nextTypeId() {
|
||||||
|
static TypeId id = 0;
|
||||||
|
return ++id;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline TypeId getTypeId() {
|
||||||
|
static TypeId id = nextTypeId();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 模块注册表
|
* @brief 模块注册表
|
||||||
* 管理模块的注册、拓扑排序和生命周期
|
* 管理模块的注册、拓扑排序和生命周期
|
||||||
*/
|
*/
|
||||||
class Registry {
|
class Registry {
|
||||||
public:
|
public:
|
||||||
|
static constexpr size_t MAX_MODULES = 64;
|
||||||
|
|
||||||
static Registry& instance();
|
static Registry& instance();
|
||||||
|
|
||||||
Registry(const Registry&) = delete;
|
Registry(const Registry&) = delete;
|
||||||
|
|
@ -33,16 +53,30 @@ public:
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
T* use(Args&&... args) {
|
T* use(Args&&... args) {
|
||||||
static_assert(std::is_base_of_v<Module, T>, "T must derive from Module");
|
static_assert(std::is_base_of_v<Module, T>, "T must derive from Module");
|
||||||
|
|
||||||
auto typeIdx = std::type_index(typeid(T));
|
TypeId typeId = detail::getTypeId<T>();
|
||||||
if (modules_.count(typeIdx)) {
|
|
||||||
return static_cast<T*>(modules_[typeIdx].get());
|
// 数组查找,O(n) 但 n 很小,缓存友好
|
||||||
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
|
if (modules_[i].id == typeId) {
|
||||||
|
return static_cast<T*>(modules_[i].module.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto module = makeUnique<T>(std::forward<Args>(args)...);
|
// 添加新模块
|
||||||
|
if (moduleCount_ >= MAX_MODULES) {
|
||||||
|
return nullptr; // 模块数量超过上限
|
||||||
|
}
|
||||||
|
|
||||||
|
auto module = ptr::makeUnique<T>(std::forward<Args>(args)...);
|
||||||
T* ptr = module.get();
|
T* ptr = module.get();
|
||||||
module->setApp(app_);
|
module->setApp(app_);
|
||||||
modules_[typeIdx] = std::move(module);
|
|
||||||
|
modules_[moduleCount_].id = typeId;
|
||||||
|
modules_[moduleCount_].module = std::move(module);
|
||||||
|
modules_[moduleCount_].valid = true;
|
||||||
|
++moduleCount_;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,10 +87,12 @@ public:
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* get() const {
|
T* get() const {
|
||||||
auto typeIdx = std::type_index(typeid(T));
|
TypeId typeId = detail::getTypeId<T>();
|
||||||
auto it = modules_.find(typeIdx);
|
|
||||||
if (it != modules_.end()) {
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
return static_cast<T*>(it->second.get());
|
if (modules_[i].id == typeId && modules_[i].valid) {
|
||||||
|
return static_cast<T*>(modules_[i].module.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -67,9 +103,12 @@ public:
|
||||||
* @return 模块指针
|
* @return 模块指针
|
||||||
*/
|
*/
|
||||||
Module* get(std::type_index typeIdx) const {
|
Module* get(std::type_index typeIdx) const {
|
||||||
auto it = modules_.find(typeIdx);
|
// 这里仍然使用type_index作为后备方案
|
||||||
if (it != modules_.end()) {
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
return it->second.get();
|
if (modules_[i].valid &&
|
||||||
|
std::type_index(typeid(*modules_[i].module)) == typeIdx) {
|
||||||
|
return modules_[i].module.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -98,26 +137,33 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取模块数量
|
* @brief 获取模块数量
|
||||||
*/
|
*/
|
||||||
size_t size() const { return modules_.size(); }
|
size_t size() const { return moduleCount_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registry() = default;
|
Registry() = default;
|
||||||
~Registry() = default;
|
~Registry() = default;
|
||||||
|
|
||||||
|
struct ModuleEntry {
|
||||||
|
TypeId id = 0;
|
||||||
|
Unique<Module> module;
|
||||||
|
bool valid = false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 拓扑排序模块
|
* @brief 拓扑排序模块
|
||||||
* @return 排序后的模块列表
|
* @return 排序后的模块列表
|
||||||
*/
|
*/
|
||||||
std::vector<Module*> topologicalSort();
|
std::vector<Module*> sort();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 按层级对模块进行分组
|
* @brief 按层级对模块进行分组
|
||||||
* 同一层级的模块没有相互依赖,可以并行初始化
|
* 同一层级的模块没有相互依赖,可以并行初始化
|
||||||
* @return 按层级分组的模块列表
|
* @return 按层级分组的模块列表
|
||||||
*/
|
*/
|
||||||
std::vector<std::vector<Module*>> groupByLevel();
|
std::vector<std::vector<Module*>> group();
|
||||||
|
|
||||||
std::unordered_map<std::type_index, UniquePtr<Module>> modules_;
|
std::array<ModuleEntry, MAX_MODULES> modules_;
|
||||||
|
size_t moduleCount_ = 0;
|
||||||
Application* app_ = nullptr;
|
Application* app_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,398 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <extra2d/core/types.h>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 错误码枚举
|
||||||
|
*/
|
||||||
|
enum class ErrorCode {
|
||||||
|
None = 0,
|
||||||
|
Unknown = 1,
|
||||||
|
InvalidArgument = 2,
|
||||||
|
OutOfMemory = 3,
|
||||||
|
FileNotFound = 4,
|
||||||
|
PermissionDenied = 5,
|
||||||
|
NotImplemented = 6,
|
||||||
|
AlreadyExists = 7,
|
||||||
|
NotInitialized = 8,
|
||||||
|
AlreadyInitialized = 9,
|
||||||
|
OperationFailed = 10,
|
||||||
|
Timeout = 11,
|
||||||
|
Cancelled = 12,
|
||||||
|
InvalidState = 13,
|
||||||
|
ResourceExhausted = 14,
|
||||||
|
Unavailable = 15,
|
||||||
|
DataLoss = 16,
|
||||||
|
Unauthenticated = 17,
|
||||||
|
PermissionDenied2 = 18,
|
||||||
|
ResourceNotFound = 19,
|
||||||
|
Aborted = 20,
|
||||||
|
OutOfRange = 21,
|
||||||
|
Unimplemented = 22,
|
||||||
|
Internal = 23,
|
||||||
|
DataCorrupted = 24,
|
||||||
|
RequestTooLarge = 25,
|
||||||
|
ResourceBusy = 26,
|
||||||
|
QuotaExceeded = 27,
|
||||||
|
DeadlineExceeded = 28,
|
||||||
|
LoadBalancing = 29,
|
||||||
|
NetworkError = 30,
|
||||||
|
ProtocolError = 31,
|
||||||
|
ServiceUnavailable = 32,
|
||||||
|
GatewayError = 33,
|
||||||
|
RateLimited = 34,
|
||||||
|
BadRequest = 35,
|
||||||
|
Unauthorized = 36,
|
||||||
|
Forbidden = 37,
|
||||||
|
NotFound = 38,
|
||||||
|
MethodNotAllowed = 39,
|
||||||
|
Conflict = 40,
|
||||||
|
Gone = 41,
|
||||||
|
LengthRequired = 42,
|
||||||
|
PreconditionFailed = 43,
|
||||||
|
PayloadTooLarge = 44,
|
||||||
|
UriTooLong = 45,
|
||||||
|
UnsupportedMediaType = 46,
|
||||||
|
RangeNotSatisfiable = 47,
|
||||||
|
ExpectationFailed = 48,
|
||||||
|
ImATeapot = 49,
|
||||||
|
MisdirectedRequest = 50,
|
||||||
|
UnprocessableEntity = 51,
|
||||||
|
Locked = 52,
|
||||||
|
FailedDependency = 53,
|
||||||
|
TooEarly = 54,
|
||||||
|
UpgradeRequired = 55,
|
||||||
|
PreconditionRequired = 56,
|
||||||
|
TooManyRequests = 57,
|
||||||
|
RequestHeaderFieldsTooLarge = 58,
|
||||||
|
UnavailableForLegalReasons = 59
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 错误信息结构
|
||||||
|
*/
|
||||||
|
struct Error {
|
||||||
|
ErrorCode code = ErrorCode::None;
|
||||||
|
std::string message;
|
||||||
|
std::string file;
|
||||||
|
int line = 0;
|
||||||
|
|
||||||
|
Error() = default;
|
||||||
|
Error(ErrorCode c, const std::string& msg) : code(c), message(msg) {}
|
||||||
|
Error(ErrorCode c, const std::string& msg, const std::string& f, int l)
|
||||||
|
: code(c), message(msg), file(f), line(l) {}
|
||||||
|
|
||||||
|
bool ok() const { return code == ErrorCode::None; }
|
||||||
|
|
||||||
|
static Error none() { return Error(); }
|
||||||
|
static Error unknown(const std::string& msg) { return Error(ErrorCode::Unknown, msg); }
|
||||||
|
static Error invalidArgument(const std::string& msg) { return Error(ErrorCode::InvalidArgument, msg); }
|
||||||
|
static Error outOfMemory(const std::string& msg) { return Error(ErrorCode::OutOfMemory, msg); }
|
||||||
|
static Error fileNotFound(const std::string& msg) { return Error(ErrorCode::FileNotFound, msg); }
|
||||||
|
static Error permissionDenied(const std::string& msg) { return Error(ErrorCode::PermissionDenied, msg); }
|
||||||
|
static Error notImplemented(const std::string& msg) { return Error(ErrorCode::NotImplemented, msg); }
|
||||||
|
static Error alreadyExists(const std::string& msg) { return Error(ErrorCode::AlreadyExists, msg); }
|
||||||
|
static Error notInitialized(const std::string& msg) { return Error(ErrorCode::NotInitialized, msg); }
|
||||||
|
static Error alreadyInitialized(const std::string& msg) { return Error(ErrorCode::AlreadyInitialized, msg); }
|
||||||
|
static Error operationFailed(const std::string& msg) { return Error(ErrorCode::OperationFailed, msg); }
|
||||||
|
static Error timeout(const std::string& msg) { return Error(ErrorCode::Timeout, msg); }
|
||||||
|
static Error cancelled(const std::string& msg) { return Error(ErrorCode::Cancelled, msg); }
|
||||||
|
static Error invalidState(const std::string& msg) { return Error(ErrorCode::InvalidState, msg); }
|
||||||
|
static Error resourceExhausted(const std::string& msg) { return Error(ErrorCode::ResourceExhausted, msg); }
|
||||||
|
static Error unavailable(const std::string& msg) { return Error(ErrorCode::Unavailable, msg); }
|
||||||
|
static Error dataLoss(const std::string& msg) { return Error(ErrorCode::DataLoss, msg); }
|
||||||
|
static Error unauthenticated(const std::string& msg) { return Error(ErrorCode::Unauthenticated, msg); }
|
||||||
|
static Error permissionDenied2(const std::string& msg) { return Error(ErrorCode::PermissionDenied2, msg); }
|
||||||
|
static Error resourceNotFound(const std::string& msg) { return Error(ErrorCode::ResourceNotFound, msg); }
|
||||||
|
static Error aborted(const std::string& msg) { return Error(ErrorCode::Aborted, msg); }
|
||||||
|
static Error outOfRange(const std::string& msg) { return Error(ErrorCode::OutOfRange, msg); }
|
||||||
|
static Error unimplemented(const std::string& msg) { return Error(ErrorCode::Unimplemented, msg); }
|
||||||
|
static Error internal(const std::string& msg) { return Error(ErrorCode::Internal, msg); }
|
||||||
|
static Error dataCorrupted(const std::string& msg) { return Error(ErrorCode::DataCorrupted, msg); }
|
||||||
|
static Error requestTooLarge(const std::string& msg) { return Error(ErrorCode::RequestTooLarge, msg); }
|
||||||
|
static Error resourceBusy(const std::string& msg) { return Error(ErrorCode::ResourceBusy, msg); }
|
||||||
|
static Error quotaExceeded(const std::string& msg) { return Error(ErrorCode::QuotaExceeded, msg); }
|
||||||
|
static Error deadlineExceeded(const std::string& msg) { return Error(ErrorCode::DeadlineExceeded, msg); }
|
||||||
|
static Error loadBalancing(const std::string& msg) { return Error(ErrorCode::LoadBalancing, msg); }
|
||||||
|
static Error networkError(const std::string& msg) { return Error(ErrorCode::NetworkError, msg); }
|
||||||
|
static Error protocolError(const std::string& msg) { return Error(ErrorCode::ProtocolError, msg); }
|
||||||
|
static Error serviceUnavailable(const std::string& msg) { return Error(ErrorCode::ServiceUnavailable, msg); }
|
||||||
|
static Error gatewayError(const std::string& msg) { return Error(ErrorCode::GatewayError, msg); }
|
||||||
|
static Error rateLimited(const std::string& msg) { return Error(ErrorCode::RateLimited, msg); }
|
||||||
|
static Error badRequest(const std::string& msg) { return Error(ErrorCode::BadRequest, msg); }
|
||||||
|
static Error unauthorized(const std::string& msg) { return Error(ErrorCode::Unauthorized, msg); }
|
||||||
|
static Error forbidden(const std::string& msg) { return Error(ErrorCode::Forbidden, msg); }
|
||||||
|
static Error notFound(const std::string& msg) { return Error(ErrorCode::NotFound, msg); }
|
||||||
|
static Error methodNotAllowed(const std::string& msg) { return Error(ErrorCode::MethodNotAllowed, msg); }
|
||||||
|
static Error conflict(const std::string& msg) { return Error(ErrorCode::Conflict, msg); }
|
||||||
|
static Error gone(const std::string& msg) { return Error(ErrorCode::Gone, msg); }
|
||||||
|
static Error lengthRequired(const std::string& msg) { return Error(ErrorCode::LengthRequired, msg); }
|
||||||
|
static Error preconditionFailed(const std::string& msg) { return Error(ErrorCode::PreconditionFailed, msg); }
|
||||||
|
static Error payloadTooLarge(const std::string& msg) { return Error(ErrorCode::PayloadTooLarge, msg); }
|
||||||
|
static Error uriTooLong(const std::string& msg) { return Error(ErrorCode::UriTooLong, msg); }
|
||||||
|
static Error unsupportedMediaType(const std::string& msg) { return Error(ErrorCode::UnsupportedMediaType, msg); }
|
||||||
|
static Error rangeNotSatisfiable(const std::string& msg) { return Error(ErrorCode::RangeNotSatisfiable, msg); }
|
||||||
|
static Error expectationFailed(const std::string& msg) { return Error(ErrorCode::ExpectationFailed, msg); }
|
||||||
|
static Error imATeapot(const std::string& msg) { return Error(ErrorCode::ImATeapot, msg); }
|
||||||
|
static Error misdirectedRequest(const std::string& msg) { return Error(ErrorCode::MisdirectedRequest, msg); }
|
||||||
|
static Error unprocessableEntity(const std::string& msg) { return Error(ErrorCode::UnprocessableEntity, msg); }
|
||||||
|
static Error locked(const std::string& msg) { return Error(ErrorCode::Locked, msg); }
|
||||||
|
static Error failedDependency(const std::string& msg) { return Error(ErrorCode::FailedDependency, msg); }
|
||||||
|
static Error tooEarly(const std::string& msg) { return Error(ErrorCode::TooEarly, msg); }
|
||||||
|
static Error upgradeRequired(const std::string& msg) { return Error(ErrorCode::UpgradeRequired, msg); }
|
||||||
|
static Error preconditionRequired(const std::string& msg) { return Error(ErrorCode::PreconditionRequired, msg); }
|
||||||
|
static Error tooManyRequests(const std::string& msg) { return Error(ErrorCode::TooManyRequests, msg); }
|
||||||
|
static Error requestHeaderFieldsTooLarge(const std::string& msg) { return Error(ErrorCode::RequestHeaderFieldsTooLarge, msg); }
|
||||||
|
static Error unavailableForLegalReasons(const std::string& msg) { return Error(ErrorCode::UnavailableForLegalReasons, msg); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Result类型,用于错误处理
|
||||||
|
* @tparam T 成功时的值类型
|
||||||
|
* @tparam E 错误类型,默认为Error
|
||||||
|
*/
|
||||||
|
template<typename T, typename E = Error>
|
||||||
|
class Result {
|
||||||
|
public:
|
||||||
|
Result() : hasValue_(false) {
|
||||||
|
new (&storage_.error) E();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Result() {
|
||||||
|
if (hasValue_) {
|
||||||
|
storage_.value.~T();
|
||||||
|
} else {
|
||||||
|
storage_.error.~E();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(const Result& other) : hasValue_(other.hasValue_) {
|
||||||
|
if (hasValue_) {
|
||||||
|
new (&storage_.value) T(other.storage_.value);
|
||||||
|
} else {
|
||||||
|
new (&storage_.error) E(other.storage_.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(Result&& other) noexcept : hasValue_(other.hasValue_) {
|
||||||
|
if (hasValue_) {
|
||||||
|
new (&storage_.value) T(std::move(other.storage_.value));
|
||||||
|
} else {
|
||||||
|
new (&storage_.error) E(std::move(other.storage_.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result& operator=(const Result& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~Result();
|
||||||
|
hasValue_ = other.hasValue_;
|
||||||
|
if (hasValue_) {
|
||||||
|
new (&storage_.value) T(other.storage_.value);
|
||||||
|
} else {
|
||||||
|
new (&storage_.error) E(other.storage_.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result& operator=(Result&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~Result();
|
||||||
|
hasValue_ = other.hasValue_;
|
||||||
|
if (hasValue_) {
|
||||||
|
new (&storage_.value) T(std::move(other.storage_.value));
|
||||||
|
} else {
|
||||||
|
new (&storage_.error) E(std::move(other.storage_.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<T, E> ok(T value) {
|
||||||
|
Result<T, E> result;
|
||||||
|
result.hasValue_ = true;
|
||||||
|
new (&result.storage_.value) T(std::move(value));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<T, E> err(E error) {
|
||||||
|
Result<T, E> result;
|
||||||
|
result.hasValue_ = false;
|
||||||
|
new (&result.storage_.error) E(std::move(error));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok() const { return hasValue_; }
|
||||||
|
bool isOk() const { return hasValue_; }
|
||||||
|
bool isErr() const { return !hasValue_; }
|
||||||
|
|
||||||
|
T& value() & {
|
||||||
|
return storage_.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& value() const & {
|
||||||
|
return storage_.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
T&& value() && {
|
||||||
|
return std::move(storage_.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
E& error() & {
|
||||||
|
return storage_.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const E& error() const & {
|
||||||
|
return storage_.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
E&& error() && {
|
||||||
|
return std::move(storage_.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
T valueOr(T defaultValue) const {
|
||||||
|
return hasValue_ ? storage_.value : std::move(defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
Result<T, E> map(F&& f) {
|
||||||
|
if (hasValue_) {
|
||||||
|
return Result<T, E>::ok(f(storage_.value));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
Result<T, E> mapErr(F&& f) {
|
||||||
|
if (!hasValue_) {
|
||||||
|
return Result<T, E>::err(f(storage_.error));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
auto andThen(F&& f) -> decltype(f(std::declval<T>())) {
|
||||||
|
if (hasValue_) {
|
||||||
|
return f(storage_.value);
|
||||||
|
}
|
||||||
|
return Result<typename decltype(f(std::declval<T>()))::ValueType, E>::err(storage_.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
Result<T, E> orElse(F&& f) {
|
||||||
|
if (!hasValue_) {
|
||||||
|
return f(storage_.error);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union Storage {
|
||||||
|
T value;
|
||||||
|
E error;
|
||||||
|
|
||||||
|
Storage() {}
|
||||||
|
~Storage() {}
|
||||||
|
} storage_;
|
||||||
|
|
||||||
|
bool hasValue_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 特化void类型
|
||||||
|
template<typename E>
|
||||||
|
class Result<void, E> {
|
||||||
|
public:
|
||||||
|
Result() : hasValue_(true) {}
|
||||||
|
|
||||||
|
~Result() {
|
||||||
|
if (!hasValue_) {
|
||||||
|
storage_.error.~E();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(const Result& other) : hasValue_(other.hasValue_) {
|
||||||
|
if (!hasValue_) {
|
||||||
|
new (&storage_.error) E(other.storage_.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(Result&& other) noexcept : hasValue_(other.hasValue_) {
|
||||||
|
if (!hasValue_) {
|
||||||
|
new (&storage_.error) E(std::move(other.storage_.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result& operator=(const Result& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~Result();
|
||||||
|
hasValue_ = other.hasValue_;
|
||||||
|
if (!hasValue_) {
|
||||||
|
new (&storage_.error) E(other.storage_.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result& operator=(Result&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~Result();
|
||||||
|
hasValue_ = other.hasValue_;
|
||||||
|
if (!hasValue_) {
|
||||||
|
new (&storage_.error) E(std::move(other.storage_.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<void, E> ok() {
|
||||||
|
return Result<void, E>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<void, E> err(E error) {
|
||||||
|
Result<void, E> result;
|
||||||
|
result.hasValue_ = false;
|
||||||
|
new (&result.storage_.error) E(std::move(error));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok() const { return hasValue_; }
|
||||||
|
bool isOk() const { return hasValue_; }
|
||||||
|
bool isErr() const { return !hasValue_; }
|
||||||
|
|
||||||
|
E& error() & {
|
||||||
|
return storage_.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const E& error() const & {
|
||||||
|
return storage_.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
E&& error() && {
|
||||||
|
return std::move(storage_.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union Storage {
|
||||||
|
E error;
|
||||||
|
|
||||||
|
Storage() {}
|
||||||
|
~Storage() {}
|
||||||
|
} storage_;
|
||||||
|
|
||||||
|
bool hasValue_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 便捷宏
|
||||||
|
#define E2D_TRY(result) \
|
||||||
|
do { \
|
||||||
|
auto _res = (result); \
|
||||||
|
if (!_res.ok()) { \
|
||||||
|
return Result<decltype(_res)::ValueType, decltype(_res)::ErrorType>::err(_res.error()); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <extra2d/core/types.h>
|
||||||
|
#include <atomic>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 无锁环形缓冲区(单生产者单消费者)
|
||||||
|
* @tparam T 元素类型
|
||||||
|
* @tparam Size 缓冲区大小(必须是2的幂)
|
||||||
|
*/
|
||||||
|
template <typename T, size_t Size>
|
||||||
|
class RingBuffer {
|
||||||
|
static_assert((Size & (Size - 1)) == 0, "Size must be a power of 2");
|
||||||
|
|
||||||
|
public:
|
||||||
|
RingBuffer() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 入队
|
||||||
|
* @param item 元素
|
||||||
|
* @return 成功返回true,缓冲区满返回false
|
||||||
|
*/
|
||||||
|
bool push(const T& item) {
|
||||||
|
const size_t currentHead = head_.load(std::memory_order_relaxed);
|
||||||
|
const size_t currentTail = tail_.load(std::memory_order_acquire);
|
||||||
|
|
||||||
|
if ((currentHead - currentTail) >= Size) {
|
||||||
|
return false; // 缓冲区满
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_[currentHead & mask_] = item;
|
||||||
|
head_.store(currentHead + 1, std::memory_order_release);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 入队(移动语义)
|
||||||
|
* @param item 元素
|
||||||
|
* @return 成功返回true,缓冲区满返回false
|
||||||
|
*/
|
||||||
|
bool push(T&& item) {
|
||||||
|
const size_t currentHead = head_.load(std::memory_order_relaxed);
|
||||||
|
const size_t currentTail = tail_.load(std::memory_order_acquire);
|
||||||
|
|
||||||
|
if ((currentHead - currentTail) >= Size) {
|
||||||
|
return false; // 缓冲区满
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_[currentHead & mask_] = std::move(item);
|
||||||
|
head_.store(currentHead + 1, std::memory_order_release);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 出队
|
||||||
|
* @param item 输出元素
|
||||||
|
* @return 成功返回true,缓冲区空返回false
|
||||||
|
*/
|
||||||
|
bool pop(T& item) {
|
||||||
|
const size_t currentTail = tail_.load(std::memory_order_relaxed);
|
||||||
|
const size_t currentHead = head_.load(std::memory_order_acquire);
|
||||||
|
|
||||||
|
if (currentTail == currentHead) {
|
||||||
|
return false; // 缓冲区空
|
||||||
|
}
|
||||||
|
|
||||||
|
item = std::move(buffer_[currentTail & mask_]);
|
||||||
|
tail_.store(currentTail + 1, std::memory_order_release);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 检查是否为空
|
||||||
|
*/
|
||||||
|
bool empty() const {
|
||||||
|
return head_.load(std::memory_order_acquire) ==
|
||||||
|
tail_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前大小
|
||||||
|
*/
|
||||||
|
size_t size() const {
|
||||||
|
return head_.load(std::memory_order_acquire) -
|
||||||
|
tail_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取容量
|
||||||
|
*/
|
||||||
|
static constexpr size_t capacity() { return Size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t mask_ = Size - 1;
|
||||||
|
alignas(64) std::array<T, Size> buffer_;
|
||||||
|
alignas(64) std::atomic<size_t> head_{0};
|
||||||
|
alignas(64) std::atomic<size_t> tail_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -9,7 +9,7 @@ namespace extra2d {
|
||||||
* @brief 服务优先级枚举
|
* @brief 服务优先级枚举
|
||||||
* 定义服务的初始化顺序,数值越小越先初始化
|
* 定义服务的初始化顺序,数值越小越先初始化
|
||||||
*/
|
*/
|
||||||
enum class ServicePriority : int {
|
enum class ServicePriority : i32 {
|
||||||
Core = 0,
|
Core = 0,
|
||||||
Event = 100,
|
Event = 100,
|
||||||
Timer = 200,
|
Timer = 200,
|
||||||
|
|
@ -56,13 +56,13 @@ public:
|
||||||
* @brief 获取服务信息
|
* @brief 获取服务信息
|
||||||
* @return 服务信息结构体
|
* @return 服务信息结构体
|
||||||
*/
|
*/
|
||||||
virtual ServiceInfo getServiceInfo() const = 0;
|
virtual ServiceInfo info() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化服务
|
* @brief 初始化服务
|
||||||
* @return 初始化成功返回 true
|
* @return 初始化成功返回 true
|
||||||
*/
|
*/
|
||||||
virtual bool initialize() = 0;
|
virtual bool init() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 关闭服务
|
* @brief 关闭服务
|
||||||
|
|
@ -87,15 +87,15 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新服务
|
* @brief 更新服务
|
||||||
* @param deltaTime 帧间隔时间
|
* @param dt 帧间隔时间
|
||||||
*/
|
*/
|
||||||
virtual void update(float deltaTime) { }
|
virtual void update(f32 dt) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 检查服务是否已初始化
|
* @brief 检查服务是否已初始化
|
||||||
* @return 已初始化返回 true
|
* @return 已初始化返回 true
|
||||||
*/
|
*/
|
||||||
virtual bool isInitialized() const {
|
virtual bool initialized() const {
|
||||||
return info_.state == ServiceState::Running ||
|
return info_.state == ServiceState::Running ||
|
||||||
info_.state == ServiceState::Paused;
|
info_.state == ServiceState::Paused;
|
||||||
}
|
}
|
||||||
|
|
@ -104,13 +104,13 @@ public:
|
||||||
* @brief 获取服务状态
|
* @brief 获取服务状态
|
||||||
* @return 当前服务状态
|
* @return 当前服务状态
|
||||||
*/
|
*/
|
||||||
ServiceState getState() const { return info_.state; }
|
ServiceState state() const { return info_.state; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取服务名称
|
* @brief 获取服务名称
|
||||||
* @return 服务名称
|
* @return 服务名称
|
||||||
*/
|
*/
|
||||||
const std::string& getName() const { return info_.name; }
|
const std::string& name() const { return info_.name; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ServiceInfo info_;
|
ServiceInfo info_;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <shared_mutex>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -15,7 +16,7 @@ namespace extra2d {
|
||||||
/**
|
/**
|
||||||
* @brief 服务工厂函数类型
|
* @brief 服务工厂函数类型
|
||||||
*/
|
*/
|
||||||
template <typename T> using ServiceFactory = std::function<SharedPtr<T>()>;
|
template <typename T> using ServiceFactory = Fn<Ref<T>()>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 服务定位器
|
* @brief 服务定位器
|
||||||
|
|
@ -25,7 +26,7 @@ template <typename T> using ServiceFactory = std::function<SharedPtr<T>()>;
|
||||||
* - 类型安全的服务注册和获取
|
* - 类型安全的服务注册和获取
|
||||||
* - 支持服务工厂延迟创建
|
* - 支持服务工厂延迟创建
|
||||||
* - 支持服务依赖声明
|
* - 支持服务依赖声明
|
||||||
* - 线程安全
|
* - 线程安全(读写锁)
|
||||||
* - 支持 Mock 测试
|
* - 支持 Mock 测试
|
||||||
*/
|
*/
|
||||||
class ServiceLocator {
|
class ServiceLocator {
|
||||||
|
|
@ -42,39 +43,39 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 注册服务实例
|
* @brief 注册服务实例
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
* @param service 服务实例
|
* @param svc 服务实例
|
||||||
*/
|
*/
|
||||||
template <typename T> void registerService(SharedPtr<T> service) {
|
template <typename T> void add(Ref<T> svc) {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
services_[typeId] = std::static_pointer_cast<IService>(service);
|
services_[typeId] = std::static_pointer_cast<IService>(svc);
|
||||||
orderedServices_.push_back(service);
|
orderedServices_.push_back(svc);
|
||||||
sortServices();
|
sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 注册服务工厂
|
* @brief 注册服务工厂
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
* @param factory 服务工厂函数
|
* @param fn 服务工厂函数
|
||||||
*/
|
*/
|
||||||
template <typename T> void registerFactory(ServiceFactory<T> factory) {
|
template <typename T> void setFactory(ServiceFactory<T> fn) {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
factories_[typeId] = [factory]() -> SharedPtr<IService> {
|
factories_[typeId] = [fn]() -> Ref<IService> {
|
||||||
return std::static_pointer_cast<IService>(factory());
|
return std::static_pointer_cast<IService>(fn());
|
||||||
};
|
};
|
||||||
|
|
||||||
// 立即创建服务实例并添加到有序列表
|
// 立即创建服务实例并添加到有序列表
|
||||||
auto service = factories_[typeId]();
|
auto svc = factories_[typeId]();
|
||||||
services_[typeId] = service;
|
services_[typeId] = svc;
|
||||||
orderedServices_.push_back(service);
|
orderedServices_.push_back(svc);
|
||||||
sortServices();
|
sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -82,13 +83,15 @@ public:
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
* @return 服务实例,不存在返回 nullptr
|
* @return 服务实例,不存在返回 nullptr
|
||||||
*/
|
*/
|
||||||
template <typename T> SharedPtr<T> getService() const {
|
template <typename T> Ref<T> get() const {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
|
|
||||||
|
// 读锁查询
|
||||||
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
auto it = services_.find(typeId);
|
auto it = services_.find(typeId);
|
||||||
if (it != services_.end()) {
|
if (it != services_.end()) {
|
||||||
return std::static_pointer_cast<T>(it->second);
|
return std::static_pointer_cast<T>(it->second);
|
||||||
|
|
@ -96,9 +99,9 @@ public:
|
||||||
|
|
||||||
auto factoryIt = factories_.find(typeId);
|
auto factoryIt = factories_.find(typeId);
|
||||||
if (factoryIt != factories_.end()) {
|
if (factoryIt != factories_.end()) {
|
||||||
auto service = factoryIt->second();
|
auto svc = factoryIt->second();
|
||||||
services_[typeId] = service;
|
services_[typeId] = svc;
|
||||||
return std::static_pointer_cast<T>(service);
|
return std::static_pointer_cast<T>(svc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -109,12 +112,14 @@ public:
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
* @return 服务实例,不存在返回 nullptr
|
* @return 服务实例,不存在返回 nullptr
|
||||||
*/
|
*/
|
||||||
template <typename T> SharedPtr<T> tryGetService() const {
|
template <typename T> Ref<T> tryGet() const {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
|
|
||||||
|
// 读锁查询
|
||||||
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
auto it = services_.find(typeId);
|
auto it = services_.find(typeId);
|
||||||
if (it != services_.end()) {
|
if (it != services_.end()) {
|
||||||
return std::static_pointer_cast<T>(it->second);
|
return std::static_pointer_cast<T>(it->second);
|
||||||
|
|
@ -127,8 +132,8 @@ public:
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
* @return 已注册返回 true
|
* @return 已注册返回 true
|
||||||
*/
|
*/
|
||||||
template <typename T> bool hasService() const {
|
template <typename T> bool has() const {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
return services_.find(typeId) != services_.end() ||
|
return services_.find(typeId) != services_.end() ||
|
||||||
factories_.find(typeId) != factories_.end();
|
factories_.find(typeId) != factories_.end();
|
||||||
|
|
@ -138,17 +143,17 @@ public:
|
||||||
* @brief 注销服务
|
* @brief 注销服务
|
||||||
* @tparam T 服务接口类型
|
* @tparam T 服务接口类型
|
||||||
*/
|
*/
|
||||||
template <typename T> void unregisterService() {
|
template <typename T> void remove() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||||
auto typeId = std::type_index(typeid(T));
|
auto typeId = std::type_index(typeid(T));
|
||||||
|
|
||||||
auto it = services_.find(typeId);
|
auto it = services_.find(typeId);
|
||||||
if (it != services_.end()) {
|
if (it != services_.end()) {
|
||||||
auto service = it->second;
|
auto svc = it->second;
|
||||||
services_.erase(it);
|
services_.erase(it);
|
||||||
|
|
||||||
auto orderIt =
|
auto orderIt =
|
||||||
std::find(orderedServices_.begin(), orderedServices_.end(), service);
|
std::find(orderedServices_.begin(), orderedServices_.end(), svc);
|
||||||
if (orderIt != orderedServices_.end()) {
|
if (orderIt != orderedServices_.end()) {
|
||||||
orderedServices_.erase(orderIt);
|
orderedServices_.erase(orderIt);
|
||||||
}
|
}
|
||||||
|
|
@ -161,34 +166,34 @@ public:
|
||||||
* @brief 初始化所有已注册的服务
|
* @brief 初始化所有已注册的服务
|
||||||
* @return 所有服务初始化成功返回 true
|
* @return 所有服务初始化成功返回 true
|
||||||
*/
|
*/
|
||||||
bool initializeAll();
|
bool init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 关闭所有服务
|
* @brief 关闭所有服务
|
||||||
*/
|
*/
|
||||||
void shutdownAll();
|
void shutdown();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 更新所有服务
|
* @brief 更新所有服务
|
||||||
* @param deltaTime 帧间隔时间
|
* @param dt 帧间隔时间
|
||||||
*/
|
*/
|
||||||
void updateAll(float deltaTime);
|
void update(f32 dt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 暂停所有服务
|
* @brief 暂停所有服务
|
||||||
*/
|
*/
|
||||||
void pauseAll();
|
void pause();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 恢复所有服务
|
* @brief 恢复所有服务
|
||||||
*/
|
*/
|
||||||
void resumeAll();
|
void resume();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取所有服务(按优先级排序)
|
* @brief 获取所有服务(按优先级排序)
|
||||||
* @return 服务列表
|
* @return 服务列表
|
||||||
*/
|
*/
|
||||||
std::vector<SharedPtr<IService>> getAllServices() const;
|
std::vector<Ref<IService>> all() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清空所有服务和工厂
|
* @brief 清空所有服务和工厂
|
||||||
|
|
@ -208,13 +213,13 @@ private:
|
||||||
/**
|
/**
|
||||||
* @brief 按优先级排序服务
|
* @brief 按优先级排序服务
|
||||||
*/
|
*/
|
||||||
void sortServices();
|
void sort();
|
||||||
|
|
||||||
mutable std::unordered_map<std::type_index, SharedPtr<IService>> services_;
|
mutable std::unordered_map<std::type_index, Ref<IService>> services_;
|
||||||
std::unordered_map<std::type_index, std::function<SharedPtr<IService>()>>
|
std::unordered_map<std::type_index, std::function<Ref<IService>()>>
|
||||||
factories_;
|
factories_;
|
||||||
std::vector<SharedPtr<IService>> orderedServices_;
|
std::vector<Ref<IService>> orderedServices_;
|
||||||
mutable std::recursive_mutex mutex_;
|
mutable std::shared_mutex mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -223,13 +228,13 @@ private:
|
||||||
*/
|
*/
|
||||||
template <typename Interface, typename Implementation> class ServiceRegistrar {
|
template <typename Interface, typename Implementation> class ServiceRegistrar {
|
||||||
public:
|
public:
|
||||||
explicit ServiceRegistrar(ServiceFactory<Interface> factory = nullptr) {
|
explicit ServiceRegistrar(ServiceFactory<Interface> fn = nullptr) {
|
||||||
if (factory) {
|
if (fn) {
|
||||||
ServiceLocator::instance().registerFactory<Interface>(factory);
|
ServiceLocator::instance().setFactory<Interface>(fn);
|
||||||
} else {
|
} else {
|
||||||
ServiceLocator::instance().registerFactory<Interface>(
|
ServiceLocator::instance().setFactory<Interface>(
|
||||||
[]() -> SharedPtr<Interface> {
|
[]() -> Ref<Interface> {
|
||||||
return makeShared<Implementation>();
|
return ptr::make<Implementation>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -251,9 +256,9 @@ template <typename Interface, typename Implementation> struct ServiceAutoReg {
|
||||||
* @return true 表示注册成功
|
* @return true 表示注册成功
|
||||||
*/
|
*/
|
||||||
static bool doRegister() {
|
static bool doRegister() {
|
||||||
::extra2d::ServiceLocator::instance().registerFactory<Interface>(
|
::extra2d::ServiceLocator::instance().setFactory<Interface>(
|
||||||
[]() -> ::extra2d::SharedPtr<Interface> {
|
[]() -> ::extra2d::Ref<Interface> {
|
||||||
return ::extra2d::makeShared<Implementation>();
|
return ::extra2d::ptr::make<Implementation>();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -271,8 +276,8 @@ template <typename Interface> struct ServiceAutoRegFactory {
|
||||||
template <typename Factory> struct Impl {
|
template <typename Factory> struct Impl {
|
||||||
static const bool registered;
|
static const bool registered;
|
||||||
|
|
||||||
static bool doRegister(Factory factory) {
|
static bool doRegister(Factory fn) {
|
||||||
::extra2d::ServiceLocator::instance().registerFactory<Interface>(factory);
|
::extra2d::ServiceLocator::instance().setFactory<Interface>(fn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace extra2d {
|
||||||
struct ServiceRegistration {
|
struct ServiceRegistration {
|
||||||
std::string name;
|
std::string name;
|
||||||
ServicePriority priority;
|
ServicePriority priority;
|
||||||
std::function<SharedPtr<IService>()> factory;
|
std::function<Ref<IService>()> factory;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
* @param priority 服务优先级
|
* @param priority 服务优先级
|
||||||
*/
|
*/
|
||||||
template<typename T, typename Impl>
|
template<typename T, typename Impl>
|
||||||
void registerService(const std::string& name, ServicePriority priority) {
|
void add(const std::string& name, ServicePriority priority) {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
static_assert(std::is_base_of_v<T, Impl>,
|
static_assert(std::is_base_of_v<T, Impl>,
|
||||||
|
|
@ -50,8 +50,8 @@ public:
|
||||||
ServiceRegistration reg;
|
ServiceRegistration reg;
|
||||||
reg.name = name;
|
reg.name = name;
|
||||||
reg.priority = priority;
|
reg.priority = priority;
|
||||||
reg.factory = []() -> SharedPtr<IService> {
|
reg.factory = []() -> Ref<IService> {
|
||||||
return std::static_pointer_cast<IService>(makeShared<Impl>());
|
return std::static_pointer_cast<IService>(ptr::make<Impl>());
|
||||||
};
|
};
|
||||||
registrations_.push_back(reg);
|
registrations_.push_back(reg);
|
||||||
}
|
}
|
||||||
|
|
@ -64,17 +64,17 @@ public:
|
||||||
* @param factory 工厂函数
|
* @param factory 工厂函数
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void registerServiceWithFactory(
|
void addWithFactory(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
ServicePriority priority,
|
ServicePriority priority,
|
||||||
std::function<SharedPtr<T>()> factory) {
|
std::function<Ref<T>()> factory) {
|
||||||
static_assert(std::is_base_of_v<IService, T>,
|
static_assert(std::is_base_of_v<IService, T>,
|
||||||
"T must derive from IService");
|
"T must derive from IService");
|
||||||
|
|
||||||
ServiceRegistration reg;
|
ServiceRegistration reg;
|
||||||
reg.name = name;
|
reg.name = name;
|
||||||
reg.priority = priority;
|
reg.priority = priority;
|
||||||
reg.factory = [factory]() -> SharedPtr<IService> {
|
reg.factory = [factory]() -> Ref<IService> {
|
||||||
return std::static_pointer_cast<IService>(factory());
|
return std::static_pointer_cast<IService>(factory());
|
||||||
};
|
};
|
||||||
registrations_.push_back(reg);
|
registrations_.push_back(reg);
|
||||||
|
|
@ -85,19 +85,19 @@ public:
|
||||||
* @param name 服务名称
|
* @param name 服务名称
|
||||||
* @param enabled 是否启用
|
* @param enabled 是否启用
|
||||||
*/
|
*/
|
||||||
void setServiceEnabled(const std::string& name, bool enabled);
|
void setEnabled(const std::string& name, bool enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建所有已注册的服务
|
* @brief 创建所有已注册的服务
|
||||||
* 并注册到 ServiceLocator
|
* 并注册到 ServiceLocator
|
||||||
*/
|
*/
|
||||||
void createAllServices();
|
void createAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取所有注册信息
|
* @brief 获取所有注册信息
|
||||||
* @return 注册信息列表
|
* @return 注册信息列表
|
||||||
*/
|
*/
|
||||||
const std::vector<ServiceRegistration>& getRegistrations() const {
|
const std::vector<ServiceRegistration>& all() const {
|
||||||
return registrations_;
|
return registrations_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ template<typename Interface, typename Implementation>
|
||||||
class AutoServiceRegistrar {
|
class AutoServiceRegistrar {
|
||||||
public:
|
public:
|
||||||
AutoServiceRegistrar(const std::string& name, ServicePriority priority) {
|
AutoServiceRegistrar(const std::string& name, ServicePriority priority) {
|
||||||
ServiceRegistry::instance().registerService<Interface, Implementation>(
|
ServiceRegistry::instance().add<Interface, Implementation>(
|
||||||
name, priority);
|
name, priority);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,43 +16,46 @@ namespace extra2d {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 智能指针别名
|
// 智能指针别名
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <typename T> using Ptr = std::shared_ptr<T>;
|
template <typename T> using Ref = std::shared_ptr<T>;
|
||||||
template <typename T> using SharedPtr = std::shared_ptr<T>;
|
template <typename T> using Unique = std::unique_ptr<T>;
|
||||||
|
template <typename T> using Weak = std::weak_ptr<T>;
|
||||||
|
|
||||||
template <typename T> using UniquePtr = std::unique_ptr<T>;
|
/// 智能指针工厂函数命名空间
|
||||||
|
namespace ptr {
|
||||||
|
/// 创建 Ref 的便捷函数
|
||||||
|
template <typename T, typename... Args> inline Ref<T> make(Args &&...args) {
|
||||||
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> using WeakPtr = std::weak_ptr<T>;
|
/// 创建 Unique 的便捷函数
|
||||||
|
template <typename T, typename... Args>
|
||||||
/// 创建 shared_ptr 的便捷函数
|
inline Unique<T> makeUnique(Args &&...args) {
|
||||||
template <typename T, typename... Args> inline Ptr<T> makePtr(Args &&...args) {
|
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Args> inline SharedPtr<T> makeShared(Args &&...args) {
|
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建 unique_ptr 的便捷函数
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
inline UniquePtr<T> makeUnique(Args &&...args) {
|
|
||||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 函数别名
|
// 函数别名
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
template <typename Sig> using Function = std::function<Sig>;
|
template <typename Sig> using Fn = std::function<Sig>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 基础类型别名
|
// 基础类型别名
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
using int8 = std::int8_t;
|
using i8 = int8_t;
|
||||||
using int16 = std::int16_t;
|
using i16 = int16_t;
|
||||||
using int32 = std::int32_t;
|
using i32 = int32_t;
|
||||||
using int64 = std::int64_t;
|
using i64 = int64_t;
|
||||||
using uint8 = std::uint8_t;
|
using u8 = uint8_t;
|
||||||
using uint16 = std::uint16_t;
|
using u16 = uint16_t;
|
||||||
using uint32 = std::uint32_t;
|
using u32 = uint32_t;
|
||||||
using uint64 = std::uint64_t;
|
using u64 = uint64_t;
|
||||||
|
using f32 = float;
|
||||||
|
using f64 = double;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ID 类型别名
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
using ID = u32;
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -59,70 +59,70 @@ enum class EventType {
|
||||||
// 键盘事件数据
|
// 键盘事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct KeyEvent {
|
struct KeyEvent {
|
||||||
int keyCode;
|
i32 key;
|
||||||
int scancode;
|
i32 scancode;
|
||||||
int mods; // 修饰键 (Shift, Ctrl, Alt, etc.)
|
i32 mods; // 修饰键 (Shift, Ctrl, Alt, etc.)
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 鼠标事件数据
|
// 鼠标事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct MouseButtonEvent {
|
struct MouseButtonEvent {
|
||||||
int button;
|
i32 button;
|
||||||
int mods;
|
i32 mods;
|
||||||
Vec2 position;
|
Vec2 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MouseMoveEvent {
|
struct MouseMoveEvent {
|
||||||
Vec2 position;
|
Vec2 pos;
|
||||||
Vec2 delta;
|
Vec2 delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MouseScrollEvent {
|
struct MouseScrollEvent {
|
||||||
Vec2 offset;
|
Vec2 offset;
|
||||||
Vec2 position;
|
Vec2 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 窗口事件数据
|
// 窗口事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct WindowResizeEvent {
|
struct WindowResizeEvent {
|
||||||
int width;
|
i32 w;
|
||||||
int height;
|
i32 h;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowMoveEvent {
|
struct WindowMoveEvent {
|
||||||
int x;
|
i32 x;
|
||||||
int y;
|
i32 y;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 游戏手柄事件数据
|
// 游戏手柄事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct GamepadButtonEvent {
|
struct GamepadButtonEvent {
|
||||||
int gamepadId;
|
i32 gamepadId;
|
||||||
int button;
|
i32 button;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GamepadAxisEvent {
|
struct GamepadAxisEvent {
|
||||||
int gamepadId;
|
i32 gamepadId;
|
||||||
int axis;
|
i32 axis;
|
||||||
float value;
|
f32 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 触摸事件数据
|
// 触摸事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct TouchEvent {
|
struct TouchEvent {
|
||||||
int touchId;
|
i32 touchId;
|
||||||
Vec2 position;
|
Vec2 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 自定义事件数据
|
// 自定义事件数据
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct CustomEvent {
|
struct CustomEvent {
|
||||||
uint32_t id;
|
u32 id;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ struct CustomEvent {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
struct Event {
|
struct Event {
|
||||||
EventType type = EventType::None;
|
EventType type = EventType::None;
|
||||||
double timestamp = 0.0;
|
f64 timestamp = 0.0;
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
// 事件数据联合体
|
// 事件数据联合体
|
||||||
|
|
@ -141,32 +141,32 @@ struct Event {
|
||||||
data;
|
data;
|
||||||
|
|
||||||
// 便捷访问方法
|
// 便捷访问方法
|
||||||
bool isWindowEvent() const {
|
bool window() const {
|
||||||
return type == EventType::WindowClose || type == EventType::WindowResize ||
|
return type == EventType::WindowClose || type == EventType::WindowResize ||
|
||||||
type == EventType::WindowFocus ||
|
type == EventType::WindowFocus ||
|
||||||
type == EventType::WindowLostFocus || type == EventType::WindowMoved;
|
type == EventType::WindowLostFocus || type == EventType::WindowMoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isKeyboardEvent() const {
|
bool keyboard() const {
|
||||||
return type == EventType::KeyPressed || type == EventType::KeyReleased ||
|
return type == EventType::KeyPressed || type == EventType::KeyReleased ||
|
||||||
type == EventType::KeyRepeat;
|
type == EventType::KeyRepeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMouseEvent() const {
|
bool mouse() const {
|
||||||
return type == EventType::MouseButtonPressed ||
|
return type == EventType::MouseButtonPressed ||
|
||||||
type == EventType::MouseButtonReleased ||
|
type == EventType::MouseButtonReleased ||
|
||||||
type == EventType::MouseMoved || type == EventType::MouseScrolled;
|
type == EventType::MouseMoved || type == EventType::MouseScrolled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 静态工厂方法
|
// 静态工厂方法
|
||||||
static Event createWindowResize(int width, int height);
|
static Event windowResize(i32 w, i32 h);
|
||||||
static Event createWindowClose();
|
static Event windowClose();
|
||||||
static Event createKeyPress(int keyCode, int scancode, int mods);
|
static Event keyPress(i32 key, i32 scancode, i32 mods);
|
||||||
static Event createKeyRelease(int keyCode, int scancode, int mods);
|
static Event keyRelease(i32 key, i32 scancode, i32 mods);
|
||||||
static Event createMouseButtonPress(int button, int mods, const Vec2 &pos);
|
static Event mousePress(i32 btn, i32 mods, Vec2 pos);
|
||||||
static Event createMouseButtonRelease(int button, int mods, const Vec2 &pos);
|
static Event mouseRelease(i32 btn, i32 mods, Vec2 pos);
|
||||||
static Event createMouseMove(const Vec2 &pos, const Vec2 &delta);
|
static Event mouseMove(Vec2 pos, Vec2 delta);
|
||||||
static Event createMouseScroll(const Vec2 &offset, const Vec2 &pos);
|
static Event mouseScroll(Vec2 offset, Vec2 pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -11,46 +11,46 @@ namespace extra2d {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 事件监听器 ID
|
// 事件监听器 ID
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
using ListenerId = uint64_t;
|
using ListenerID = u64;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 事件分发器
|
// 事件分发器
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class EventDispatcher {
|
class EventDispatcher {
|
||||||
public:
|
public:
|
||||||
using EventCallback = std::function<void(Event &)>;
|
using EventFn = Fn<void(Event &)>;
|
||||||
|
|
||||||
EventDispatcher();
|
EventDispatcher();
|
||||||
~EventDispatcher() = default;
|
~EventDispatcher() = default;
|
||||||
|
|
||||||
// 添加监听器
|
// 添加监听器
|
||||||
ListenerId addListener(EventType type, EventCallback callback);
|
ListenerID on(EventType type, EventFn fn);
|
||||||
|
|
||||||
// 移除监听器
|
// 移除监听器
|
||||||
void removeListener(ListenerId id);
|
void off(ListenerID id);
|
||||||
void removeAllListeners(EventType type);
|
void offAll(EventType type);
|
||||||
void removeAllListeners();
|
void offAll();
|
||||||
|
|
||||||
// 分发事件
|
// 分发事件
|
||||||
void dispatch(Event &event);
|
void dispatch(Event &event);
|
||||||
void dispatch(const Event &event);
|
void dispatch(const Event &event);
|
||||||
|
|
||||||
// 处理事件队列
|
// 处理事件队列
|
||||||
void processQueue(class EventQueue &queue);
|
void process(class EventQueue &queue);
|
||||||
|
|
||||||
// 统计
|
// 统计
|
||||||
size_t getListenerCount(EventType type) const;
|
size_t listenerCount(EventType type) const;
|
||||||
size_t getTotalListenerCount() const;
|
size_t totalListeners() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Listener {
|
struct Listener {
|
||||||
ListenerId id;
|
ListenerID id;
|
||||||
EventType type;
|
EventType type;
|
||||||
EventCallback callback;
|
EventFn fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<EventType, std::vector<Listener>> listeners_;
|
std::unordered_map<EventType, std::vector<Listener>> listeners_;
|
||||||
ListenerId nextId_;
|
ListenerID nextId_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <extra2d/core/ring_buffer.h>
|
||||||
#include <extra2d/core/types.h>
|
#include <extra2d/core/types.h>
|
||||||
#include <extra2d/event/event.h>
|
#include <extra2d/event/event.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -12,29 +12,32 @@ namespace extra2d {
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class EventQueue {
|
class EventQueue {
|
||||||
public:
|
public:
|
||||||
EventQueue();
|
static constexpr size_t DEFAULT_CAPACITY = 1024;
|
||||||
~EventQueue() = default;
|
|
||||||
|
|
||||||
// 添加事件到队列
|
EventQueue();
|
||||||
void push(const Event &event);
|
~EventQueue() = default;
|
||||||
void push(Event &&event);
|
|
||||||
|
|
||||||
// 从队列取出事件
|
// 添加事件到队列
|
||||||
bool poll(Event &event);
|
bool push(const Event &event);
|
||||||
|
bool push(Event &&event);
|
||||||
|
|
||||||
// 查看队列头部事件(不移除)
|
// 从队列取出事件
|
||||||
bool peek(Event &event) const;
|
bool poll(Event &event);
|
||||||
|
|
||||||
// 清空队列
|
// 查看队列头部事件(不移除)
|
||||||
void clear();
|
bool peek(Event &event) const;
|
||||||
|
|
||||||
// 队列状态
|
// 清空队列
|
||||||
bool empty() const;
|
void clear();
|
||||||
size_t size() const;
|
|
||||||
|
// 队列状态
|
||||||
|
bool empty() const;
|
||||||
|
size_t size() const;
|
||||||
|
size_t capacity() const { return buffer_.capacity(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::queue<Event> queue_;
|
RingBuffer<Event, DEFAULT_CAPACITY> buffer_;
|
||||||
mutable std::mutex mutex_;
|
mutable std::mutex mutex_; // 用于peek和clear的互斥
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ enum class Cursor {
|
||||||
*/
|
*/
|
||||||
class GLFWWindow {
|
class GLFWWindow {
|
||||||
public:
|
public:
|
||||||
using ResizeCb = std::function<void(int, int)>;
|
using ResizeFn = std::function<void(int, int)>;
|
||||||
using CloseCb = std::function<void()>;
|
using CloseFn = std::function<void()>;
|
||||||
using FocusCb = std::function<void(bool)>;
|
using FocusFn = std::function<void(bool)>;
|
||||||
|
|
||||||
GLFWWindow();
|
GLFWWindow();
|
||||||
~GLFWWindow();
|
~GLFWWindow();
|
||||||
|
|
@ -36,12 +36,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 创建窗口
|
* @brief 创建窗口
|
||||||
* @param title 窗口标题
|
* @param title 窗口标题
|
||||||
* @param width 窗口宽度
|
* @param w 窗口宽度
|
||||||
* @param height 窗口高度
|
* @param h 窗口高度
|
||||||
* @param vsync 是否启用垂直同步
|
* @param vsync 是否启用垂直同步
|
||||||
* @return 创建是否成功
|
* @return 创建是否成功
|
||||||
*/
|
*/
|
||||||
bool create(const std::string& title, int width, int height, bool vsync = true);
|
bool create(const std::string& title, int w, int h, bool vsync = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 销毁窗口
|
* @brief 销毁窗口
|
||||||
|
|
@ -71,42 +71,42 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 设置窗口标题
|
* @brief 设置窗口标题
|
||||||
*/
|
*/
|
||||||
void setTitle(const std::string& title);
|
void title(const std::string& t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置窗口大小
|
* @brief 设置窗口大小
|
||||||
*/
|
*/
|
||||||
void setSize(int w, int h);
|
void size(int w, int h);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置窗口位置
|
* @brief 设置窗口位置
|
||||||
*/
|
*/
|
||||||
void setPos(int x, int y);
|
void pos(int x, int y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置全屏模式
|
* @brief 设置全屏模式
|
||||||
*/
|
*/
|
||||||
void setFullscreen(bool fs);
|
void fullscreen(bool fs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置垂直同步
|
* @brief 设置垂直同步
|
||||||
*/
|
*/
|
||||||
void setVSync(bool vsync);
|
void vsync(bool v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置窗口可见性
|
* @brief 设置窗口可见性
|
||||||
*/
|
*/
|
||||||
void setVisible(bool visible);
|
void visible(bool v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口宽度
|
* @brief 获取窗口宽度
|
||||||
*/
|
*/
|
||||||
int width() const { return width_; }
|
int w() const { return w_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口高度
|
* @brief 获取窗口高度
|
||||||
*/
|
*/
|
||||||
int height() const { return height_; }
|
int h() const { return h_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口大小
|
* @brief 获取窗口大小
|
||||||
|
|
@ -141,17 +141,17 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取内容缩放X
|
* @brief 获取内容缩放X
|
||||||
*/
|
*/
|
||||||
float scaleX() const { return scaleX_; }
|
f32 scaleX() const { return scaleX_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取内容缩放Y
|
* @brief 获取内容缩放Y
|
||||||
*/
|
*/
|
||||||
float scaleY() const { return scaleY_; }
|
f32 scaleY() const { return scaleY_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置光标形状
|
* @brief 设置光标形状
|
||||||
*/
|
*/
|
||||||
void setCursor(Cursor cursor);
|
void cursor(Cursor c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 显示/隐藏光标
|
* @brief 显示/隐藏光标
|
||||||
|
|
@ -166,17 +166,17 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 设置大小改变回调
|
* @brief 设置大小改变回调
|
||||||
*/
|
*/
|
||||||
void onResize(ResizeCb cb) { resizeCb_ = cb; }
|
void onResize(ResizeFn fn) { resizeFn_ = fn; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置关闭回调
|
* @brief 设置关闭回调
|
||||||
*/
|
*/
|
||||||
void onClose(CloseCb cb) { closeCb_ = cb; }
|
void onClose(CloseFn fn) { closeFn_ = fn; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置焦点改变回调
|
* @brief 设置焦点改变回调
|
||||||
*/
|
*/
|
||||||
void onFocus(FocusCb cb) { focusCb_ = cb; }
|
void onFocus(FocusFn fn) { focusFn_ = fn; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取原生窗口句柄
|
* @brief 获取原生窗口句柄
|
||||||
|
|
@ -186,7 +186,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 获取 GLFW 窗口句柄
|
* @brief 获取 GLFW 窗口句柄
|
||||||
*/
|
*/
|
||||||
GLFWwindow* glfwWindow() const { return glfwWindow_; }
|
GLFWwindow* handle() const { return handle_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initGLFW();
|
bool initGLFW();
|
||||||
|
|
@ -194,33 +194,33 @@ private:
|
||||||
void updateContentScale();
|
void updateContentScale();
|
||||||
|
|
||||||
// GLFW 回调函数(静态)
|
// GLFW 回调函数(静态)
|
||||||
static void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
static void framebufferSizeCallback(GLFWwindow* window, int w, int h);
|
||||||
static void windowCloseCallback(GLFWwindow* window);
|
static void windowCloseCallback(GLFWwindow* window);
|
||||||
static void windowFocusCallback(GLFWwindow* window, int focused);
|
static void windowFocusCallback(GLFWwindow* window, int focused);
|
||||||
static void windowIconifyCallback(GLFWwindow* window, int iconified);
|
static void windowIconifyCallback(GLFWwindow* window, int iconified);
|
||||||
static void cursorPosCallback(GLFWwindow* window, double xpos, double ypos);
|
static void cursorPosCallback(GLFWwindow* window, double x, double y);
|
||||||
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
static void mouseButtonCallback(GLFWwindow* window, int btn, int action, int mods);
|
||||||
static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
static void scrollCallback(GLFWwindow* window, double x, double y);
|
||||||
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||||
static void joystickCallback(int jid, int event);
|
static void joystickCallback(int jid, int event);
|
||||||
|
|
||||||
GLFWwindow* glfwWindow_ = nullptr;
|
GLFWwindow* handle_ = nullptr;
|
||||||
|
|
||||||
int width_ = 1280;
|
int w_ = 1280;
|
||||||
int height_ = 720;
|
int h_ = 720;
|
||||||
bool fullscreen_ = false;
|
bool fullscreen_ = false;
|
||||||
bool vsync_ = true;
|
bool vsync_ = true;
|
||||||
bool focused_ = true;
|
bool focused_ = true;
|
||||||
bool minimized_ = false;
|
bool minimized_ = false;
|
||||||
bool shouldClose_ = false;
|
bool shouldClose_ = false;
|
||||||
float scaleX_ = 1.0f;
|
f32 scaleX_ = 1.0f;
|
||||||
float scaleY_ = 1.0f;
|
f32 scaleY_ = 1.0f;
|
||||||
bool cursorVisible_ = true;
|
bool cursorVisible_ = true;
|
||||||
bool cursorLocked_ = false;
|
bool cursorLocked_ = false;
|
||||||
|
|
||||||
ResizeCb resizeCb_;
|
ResizeFn resizeFn_;
|
||||||
CloseCb closeCb_;
|
CloseFn closeFn_;
|
||||||
FocusCb focusCb_;
|
FocusFn focusFn_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowCfg cfg_;
|
WindowCfg cfg_;
|
||||||
UniquePtr<GLFWWindow> win_;
|
Unique<GLFWWindow> win_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,21 @@ class IEventService : public IService {
|
||||||
public:
|
public:
|
||||||
virtual ~IEventService() = default;
|
virtual ~IEventService() = default;
|
||||||
|
|
||||||
virtual void pushEvent(const Event& event) = 0;
|
virtual void push(const Event& event) = 0;
|
||||||
virtual void pushEvent(Event&& event) = 0;
|
virtual void push(Event&& event) = 0;
|
||||||
virtual bool pollEvent(Event& event) = 0;
|
virtual bool poll(Event& event) = 0;
|
||||||
|
|
||||||
virtual ListenerId addListener(EventType type, EventDispatcher::EventCallback callback) = 0;
|
virtual ListenerID on(EventType type, EventDispatcher::EventFn fn) = 0;
|
||||||
virtual void removeListener(ListenerId id) = 0;
|
virtual void off(ListenerID id) = 0;
|
||||||
virtual void removeAllListeners(EventType type) = 0;
|
virtual void offAll(EventType type) = 0;
|
||||||
virtual void removeAllListeners() = 0;
|
virtual void offAll() = 0;
|
||||||
|
|
||||||
virtual void dispatch(Event& event) = 0;
|
virtual void dispatch(Event& event) = 0;
|
||||||
virtual void processQueue() = 0;
|
virtual void process() = 0;
|
||||||
|
|
||||||
virtual size_t getListenerCount(EventType type) const = 0;
|
virtual size_t listenerCount(EventType type) const = 0;
|
||||||
virtual size_t getTotalListenerCount() const = 0;
|
virtual size_t totalListeners() const = 0;
|
||||||
virtual size_t getQueueSize() const = 0;
|
virtual size_t queueSize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,32 +39,32 @@ public:
|
||||||
EventService();
|
EventService();
|
||||||
~EventService() override = default;
|
~EventService() override = default;
|
||||||
|
|
||||||
ServiceInfo getServiceInfo() const override;
|
ServiceInfo info() const override;
|
||||||
|
|
||||||
bool initialize() override;
|
bool init() override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
void update(float deltaTime) override;
|
void update(f32 dt) override;
|
||||||
|
|
||||||
void pushEvent(const Event& event) override;
|
void push(const Event& event) override;
|
||||||
void pushEvent(Event&& event) override;
|
void push(Event&& event) override;
|
||||||
bool pollEvent(Event& event) override;
|
bool poll(Event& event) override;
|
||||||
|
|
||||||
ListenerId addListener(EventType type, EventDispatcher::EventCallback callback) override;
|
ListenerID on(EventType type, EventDispatcher::EventFn fn) override;
|
||||||
void removeListener(ListenerId id) override;
|
void off(ListenerID id) override;
|
||||||
void removeAllListeners(EventType type) override;
|
void offAll(EventType type) override;
|
||||||
void removeAllListeners() override;
|
void offAll() override;
|
||||||
|
|
||||||
void dispatch(Event& event) override;
|
void dispatch(Event& event) override;
|
||||||
void processQueue() override;
|
void process() override;
|
||||||
|
|
||||||
size_t getListenerCount(EventType type) const override;
|
size_t listenerCount(EventType type) const override;
|
||||||
size_t getTotalListenerCount() const override;
|
size_t totalListeners() const override;
|
||||||
size_t getQueueSize() const override;
|
size_t queueSize() const override;
|
||||||
|
|
||||||
EventQueue& getQueue() { return queue_; }
|
EventQueue& queue() { return queue_; }
|
||||||
const EventQueue& getQueue() const { return queue_; }
|
const EventQueue& queue() const { return queue_; }
|
||||||
EventDispatcher& getDispatcher() { return dispatcher_; }
|
EventDispatcher& dispatcher() { return dispatcher_; }
|
||||||
const EventDispatcher& getDispatcher() const { return dispatcher_; }
|
const EventDispatcher& dispatcher() const { return dispatcher_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventQueue queue_;
|
EventQueue queue_;
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ namespace extra2d {
|
||||||
* @brief 日志颜色结构
|
* @brief 日志颜色结构
|
||||||
*/
|
*/
|
||||||
struct LogColor {
|
struct LogColor {
|
||||||
uint8_t r, g, b;
|
u8 r, g, b;
|
||||||
|
|
||||||
constexpr LogColor() : r(255), g(255), b(255) {}
|
constexpr LogColor() : r(255), g(255), b(255) {}
|
||||||
constexpr LogColor(uint8_t r, uint8_t g, uint8_t b) : r(r), g(g), b(b) {}
|
constexpr LogColor(u8 r, u8 g, u8 b) : r(r), g(g), b(b) {}
|
||||||
|
|
||||||
static constexpr LogColor White() { return LogColor(255, 255, 255); }
|
static constexpr LogColor White() { return LogColor(255, 255, 255); }
|
||||||
static constexpr LogColor Gray() { return LogColor(128, 128, 128); }
|
static constexpr LogColor Gray() { return LogColor(128, 128, 128); }
|
||||||
|
|
@ -68,27 +68,27 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief 设置日志级别
|
* @brief 设置日志级别
|
||||||
*/
|
*/
|
||||||
virtual void setLevel(LogLevel level) = 0;
|
virtual void level(LogLevel lvl) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取日志级别
|
* @brief 获取日志级别
|
||||||
*/
|
*/
|
||||||
virtual LogLevel getLevel() const = 0;
|
virtual LogLevel level() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 检查日志级别是否启用
|
* @brief 检查日志级别是否启用
|
||||||
*/
|
*/
|
||||||
virtual bool isEnabled(LogLevel level) const = 0;
|
virtual bool enabled(LogLevel lvl) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 记录日志(格式化)
|
* @brief 记录日志(格式化)
|
||||||
*/
|
*/
|
||||||
virtual void log(LogLevel level, const char *fmt, ...) = 0;
|
virtual void log(LogLevel lvl, const char *fmt, ...) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 记录日志(字符串)
|
* @brief 记录日志(字符串)
|
||||||
*/
|
*/
|
||||||
virtual void log(LogLevel level, const std::string &msg) = 0;
|
virtual void log(LogLevel lvl, const std::string &msg) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Trace级别日志
|
* @brief Trace级别日志
|
||||||
|
|
@ -127,35 +127,35 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置日志级别颜色
|
* @brief 设置日志级别颜色
|
||||||
* @param level 日志级别
|
* @param lvl 日志级别
|
||||||
* @param color 颜色
|
* @param c 颜色
|
||||||
*/
|
*/
|
||||||
virtual void setLevelColor(LogLevel level, const LogColor &color) = 0;
|
virtual void levelColor(LogLevel lvl, const LogColor &c) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取日志级别颜色
|
* @brief 获取日志级别颜色
|
||||||
* @param level 日志级别
|
* @param lvl 日志级别
|
||||||
* @return 颜色
|
* @return 颜色
|
||||||
*/
|
*/
|
||||||
virtual LogColor getLevelColor(LogLevel level) const = 0;
|
virtual LogColor levelColor(LogLevel lvl) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 启用/禁用颜色输出
|
* @brief 启用/禁用颜色输出
|
||||||
* @param enabled 是否启用
|
* @param on 是否启用
|
||||||
*/
|
*/
|
||||||
virtual void setColorEnabled(bool enabled) = 0;
|
virtual void colors(bool on) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 是否启用颜色输出
|
* @brief 是否启用颜色输出
|
||||||
*/
|
*/
|
||||||
virtual bool isColorEnabled() const = 0;
|
virtual bool colors() const = 0;
|
||||||
|
|
||||||
ServiceInfo getServiceInfo() const override {
|
ServiceInfo info() const override {
|
||||||
ServiceInfo info;
|
ServiceInfo i;
|
||||||
info.name = "Logger";
|
i.name = "Logger";
|
||||||
info.priority = ServicePriority::Core;
|
i.priority = ServicePriority::Core;
|
||||||
info.enabled = true;
|
i.enabled = true;
|
||||||
return info;
|
return i;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -167,15 +167,15 @@ public:
|
||||||
ConsoleLogger();
|
ConsoleLogger();
|
||||||
~ConsoleLogger() override;
|
~ConsoleLogger() override;
|
||||||
|
|
||||||
bool initialize() override;
|
bool init() override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
|
|
||||||
void setLevel(LogLevel level) override;
|
void level(LogLevel lvl) override;
|
||||||
LogLevel getLevel() const override;
|
LogLevel level() const override;
|
||||||
bool isEnabled(LogLevel level) const override;
|
bool enabled(LogLevel lvl) const override;
|
||||||
|
|
||||||
void log(LogLevel level, const char *fmt, ...) override;
|
void log(LogLevel lvl, const char *fmt, ...) override;
|
||||||
void log(LogLevel level, const std::string &msg) override;
|
void log(LogLevel lvl, const std::string &msg) override;
|
||||||
|
|
||||||
void trace(const char *fmt, ...) override;
|
void trace(const char *fmt, ...) override;
|
||||||
void debug(const char *fmt, ...) override;
|
void debug(const char *fmt, ...) override;
|
||||||
|
|
@ -185,21 +185,21 @@ public:
|
||||||
void error(const char *fmt, ...) override;
|
void error(const char *fmt, ...) override;
|
||||||
void fatal(const char *fmt, ...) override;
|
void fatal(const char *fmt, ...) override;
|
||||||
|
|
||||||
void setLevelColor(LogLevel level, const LogColor &color) override;
|
void levelColor(LogLevel lvl, const LogColor &c) override;
|
||||||
LogColor getLevelColor(LogLevel level) const override;
|
LogColor levelColor(LogLevel lvl) const override;
|
||||||
void setColorEnabled(bool enabled) override;
|
void colors(bool on) override;
|
||||||
bool isColorEnabled() const override;
|
bool colors() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void output(LogLevel level, const char *msg);
|
void output(LogLevel lvl, const char *msg);
|
||||||
const char *getLevelString(LogLevel level);
|
const char *levelString(LogLevel lvl);
|
||||||
std::string getAnsiColor(LogLevel level);
|
std::string ansiColor(LogLevel lvl);
|
||||||
|
|
||||||
LogLevel level_;
|
LogLevel level_;
|
||||||
bool colorEnabled_;
|
bool colors_;
|
||||||
LogColor levelColors_[7];
|
LogColor levelColors_[7];
|
||||||
class Impl;
|
class Impl;
|
||||||
UniquePtr<Impl> impl_;
|
Unique<Impl> impl_;
|
||||||
|
|
||||||
// 服务注册元数据
|
// 服务注册元数据
|
||||||
E2D_AUTO_REGISTER_SERVICE(ILogger, ConsoleLogger);
|
E2D_AUTO_REGISTER_SERVICE(ILogger, ConsoleLogger);
|
||||||
|
|
@ -262,12 +262,12 @@ std::string format_str(const char *fmt, Args &&...args) {
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
||||||
// 便捷宏 - 自动获取日志服务
|
// 便捷宏 - 自动获取日志服务
|
||||||
#define E2D_LOG(level, ...) \
|
#define E2D_LOG(lvl, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (auto logService = ::extra2d::ServiceLocator::instance() \
|
if (auto logService = ::extra2d::ServiceLocator::instance() \
|
||||||
.tryGetService<::extra2d::ILogger>()) { \
|
.tryGet<::extra2d::ILogger>()) { \
|
||||||
if (logService->isEnabled(level)) { \
|
if (logService->enabled(lvl)) { \
|
||||||
logService->log(level, ::extra2d::format_str(__VA_ARGS__)); \
|
logService->log(lvl, ::extra2d::format_str(__VA_ARGS__)); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
@ -281,30 +281,30 @@ std::string format_str(const char *fmt, Args &&...args) {
|
||||||
#define E2D_FATAL(...) E2D_LOG(::extra2d::LogLevel::Fatal, __VA_ARGS__)
|
#define E2D_FATAL(...) E2D_LOG(::extra2d::LogLevel::Fatal, __VA_ARGS__)
|
||||||
|
|
||||||
// 带颜色参数的日志宏
|
// 带颜色参数的日志宏
|
||||||
#define E2D_LOG_COLOR(level, color, ...) \
|
#define E2D_LOG_COLOR(lvl, c, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (auto logService = ::extra2d::ServiceLocator::instance() \
|
if (auto logService = ::extra2d::ServiceLocator::instance() \
|
||||||
.tryGetService<::extra2d::ILogger>()) { \
|
.tryGet<::extra2d::ILogger>()) { \
|
||||||
if (logService->isEnabled(level)) { \
|
if (logService->enabled(lvl)) { \
|
||||||
auto prevColor = logService->getLevelColor(level); \
|
auto prevColor = logService->levelColor(lvl); \
|
||||||
logService->setLevelColor(level, color); \
|
logService->levelColor(lvl, c); \
|
||||||
logService->log(level, ::extra2d::format_str(__VA_ARGS__)); \
|
logService->log(lvl, ::extra2d::format_str(__VA_ARGS__)); \
|
||||||
logService->setLevelColor(level, prevColor); \
|
logService->levelColor(lvl, prevColor); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define E2D_TRACE_COLOR(color, ...) \
|
#define E2D_TRACE_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Trace, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Trace, c, __VA_ARGS__)
|
||||||
#define E2D_DEBUG_COLOR(color, ...) \
|
#define E2D_DEBUG_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Debug, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Debug, c, __VA_ARGS__)
|
||||||
#define E2D_INFO_COLOR(color, ...) \
|
#define E2D_INFO_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Info, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Info, c, __VA_ARGS__)
|
||||||
#define E2D_REGISTRY_COLOR(color, ...) \
|
#define E2D_REGISTRY_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Registry, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Registry, c, __VA_ARGS__)
|
||||||
#define E2D_WARN_COLOR(color, ...) \
|
#define E2D_WARN_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Warn, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Warn, c, __VA_ARGS__)
|
||||||
#define E2D_ERROR_COLOR(color, ...) \
|
#define E2D_ERROR_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Error, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Error, c, __VA_ARGS__)
|
||||||
#define E2D_FATAL_COLOR(color, ...) \
|
#define E2D_FATAL_COLOR(c, ...) \
|
||||||
E2D_LOG_COLOR(::extra2d::LogLevel::Fatal, color, __VA_ARGS__)
|
E2D_LOG_COLOR(::extra2d::LogLevel::Fatal, c, __VA_ARGS__)
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ class ITimerService : public IService {
|
||||||
public:
|
public:
|
||||||
virtual ~ITimerService() = default;
|
virtual ~ITimerService() = default;
|
||||||
|
|
||||||
virtual uint32 addTimer(float delay, Timer::Callback callback) = 0;
|
virtual u32 add(f32 delay, Timer::Fn fn) = 0;
|
||||||
virtual uint32 addRepeatingTimer(float interval, Timer::Callback callback) = 0;
|
virtual u32 addRepeat(f32 interval, Timer::Fn fn) = 0;
|
||||||
virtual void cancelTimer(uint32 timerId) = 0;
|
virtual void cancel(u32 timerId) = 0;
|
||||||
virtual void pauseTimer(uint32 timerId) = 0;
|
virtual void pauseTimer(u32 timerId) = 0;
|
||||||
virtual void resumeTimer(uint32 timerId) = 0;
|
virtual void resumeTimer(u32 timerId) = 0;
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
virtual size_t getTimerCount() const = 0;
|
virtual size_t count() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -30,25 +30,25 @@ public:
|
||||||
TimerService();
|
TimerService();
|
||||||
~TimerService() override = default;
|
~TimerService() override = default;
|
||||||
|
|
||||||
ServiceInfo getServiceInfo() const override;
|
ServiceInfo info() const override;
|
||||||
|
|
||||||
bool initialize() override;
|
bool init() override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
void update(float deltaTime) override;
|
void update(f32 dt) override;
|
||||||
|
|
||||||
uint32 addTimer(float delay, Timer::Callback callback) override;
|
u32 add(f32 delay, Timer::Fn fn) override;
|
||||||
uint32 addRepeatingTimer(float interval, Timer::Callback callback) override;
|
u32 addRepeat(f32 interval, Timer::Fn fn) override;
|
||||||
void cancelTimer(uint32 timerId) override;
|
void cancel(u32 timerId) override;
|
||||||
void pauseTimer(uint32 timerId) override;
|
void pauseTimer(u32 timerId) override;
|
||||||
void resumeTimer(uint32 timerId) override;
|
void resumeTimer(u32 timerId) override;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
size_t getTimerCount() const override;
|
size_t count() const override;
|
||||||
|
|
||||||
TimerManager& getManager() { return manager_; }
|
TimerManager& mgr() { return mgr_; }
|
||||||
const TimerManager& getManager() const { return manager_; }
|
const TimerManager& mgr() const { return mgr_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimerManager manager_;
|
TimerManager mgr_;
|
||||||
|
|
||||||
// 服务注册元数据
|
// 服务注册元数据
|
||||||
E2D_AUTO_REGISTER_SERVICE(ITimerService, TimerService);
|
E2D_AUTO_REGISTER_SERVICE(ITimerService, TimerService);
|
||||||
|
|
|
||||||
|
|
@ -14,34 +14,34 @@ public:
|
||||||
static Random &get();
|
static Random &get();
|
||||||
|
|
||||||
/// 设置随机种子
|
/// 设置随机种子
|
||||||
void setSeed(uint32 seed);
|
void seed(u32 s);
|
||||||
|
|
||||||
/// 使用当前时间作为种子
|
/// 使用当前时间作为种子
|
||||||
void randomize();
|
void randomize();
|
||||||
|
|
||||||
/// 获取 [0, 1) 范围内的随机浮点数
|
/// 获取 [0, 1) 范围内的随机浮点数
|
||||||
float getFloat();
|
f32 randomF32();
|
||||||
|
|
||||||
/// 获取 [min, max] 范围内的随机浮点数
|
/// 获取 [min, max] 范围内的随机浮点数
|
||||||
float getFloat(float min, float max);
|
f32 randomF32(f32 min, f32 max);
|
||||||
|
|
||||||
/// 获取 [0, max] 范围内的随机整数
|
/// 获取 [0, max] 范围内的随机整数
|
||||||
int getInt(int max);
|
i32 randomI32(i32 max);
|
||||||
|
|
||||||
/// 获取 [min, max] 范围内的随机整数
|
/// 获取 [min, max] 范围内的随机整数
|
||||||
int getInt(int min, int max);
|
i32 randomI32(i32 min, i32 max);
|
||||||
|
|
||||||
/// 获取随机布尔值
|
/// 获取随机布尔值
|
||||||
bool getBool();
|
bool boolean();
|
||||||
|
|
||||||
/// 获取随机布尔值(带概率)
|
/// 获取随机布尔值(带概率)
|
||||||
bool getBool(float probability);
|
bool boolean(f32 probability);
|
||||||
|
|
||||||
/// 获取指定范围内的随机角度(弧度)
|
/// 获取指定范围内的随机角度(弧度)
|
||||||
float getAngle();
|
f32 angle();
|
||||||
|
|
||||||
/// 获取 [-1, 1] 范围内的随机数(用于方向)
|
/// 获取 [-1, 1] 范围内的随机数(用于方向)
|
||||||
float getSigned();
|
f32 signedF32();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Random();
|
Random();
|
||||||
|
|
@ -59,27 +59,27 @@ private:
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/// 获取 [0, 1) 范围内的随机浮点数
|
/// 获取 [0, 1) 范围内的随机浮点数
|
||||||
inline float randomFloat() { return Random::get().getFloat(); }
|
inline f32 randF32() { return Random::get().randomF32(); }
|
||||||
|
|
||||||
/// 获取 [min, max] 范围内的随机浮点数
|
/// 获取 [min, max] 范围内的随机浮点数
|
||||||
inline float randomFloat(float min, float max) {
|
inline f32 randF32(f32 min, f32 max) {
|
||||||
return Random::get().getFloat(min, max);
|
return Random::get().randomF32(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取 [0, max] 范围内的随机整数
|
/// 获取 [0, max] 范围内的随机整数
|
||||||
inline int randomInt(int max) { return Random::get().getInt(max); }
|
inline i32 randI32(i32 max) { return Random::get().randomI32(max); }
|
||||||
|
|
||||||
/// 获取 [min, max] 范围内的随机整数
|
/// 获取 [min, max] 范围内的随机整数
|
||||||
inline int randomInt(int min, int max) {
|
inline i32 randI32(i32 min, i32 max) {
|
||||||
return Random::get().getInt(min, max);
|
return Random::get().randomI32(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取随机布尔值
|
/// 获取随机布尔值
|
||||||
inline bool randomBool() { return Random::get().getBool(); }
|
inline bool randBool() { return Random::get().boolean(); }
|
||||||
|
|
||||||
/// 获取随机布尔值(带概率)
|
/// 获取随机布尔值(带概率)
|
||||||
inline bool randomBool(float probability) {
|
inline bool randBool(f32 probability) {
|
||||||
return Random::get().getBool(probability);
|
return Random::get().boolean(probability);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ public:
|
||||||
using Clock = std::chrono::steady_clock;
|
using Clock = std::chrono::steady_clock;
|
||||||
using TimePoint = Clock::time_point;
|
using TimePoint = Clock::time_point;
|
||||||
using Duration = Clock::duration;
|
using Duration = Clock::duration;
|
||||||
using Callback = Function<void()>;
|
using Fn = std::function<void()>;
|
||||||
|
|
||||||
Timer(float interval, bool repeat, Callback callback);
|
Timer(f32 interval, bool repeat, Fn fn);
|
||||||
|
|
||||||
/// 更新计时器,返回 true 如果触发了回调
|
/// 更新计时器,返回 true 如果触发了回调
|
||||||
bool update(float deltaTime);
|
bool update(f32 dt);
|
||||||
|
|
||||||
/// 重置计时器
|
/// 重置计时器
|
||||||
void reset();
|
void reset();
|
||||||
|
|
@ -36,27 +36,27 @@ public:
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
/// 是否有效
|
/// 是否有效
|
||||||
bool isValid() const { return valid_; }
|
bool valid() const { return valid_; }
|
||||||
|
|
||||||
/// 是否暂停
|
/// 是否暂停
|
||||||
bool isPaused() const { return paused_; }
|
bool paused() const { return paused_; }
|
||||||
|
|
||||||
/// 获取剩余时间(秒)
|
/// 获取剩余时间(秒)
|
||||||
float getRemaining() const;
|
f32 remaining() const;
|
||||||
|
|
||||||
/// 获取唯一ID
|
/// 获取唯一ID
|
||||||
uint32 getId() const { return id_; }
|
u32 id() const { return id_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 id_;
|
u32 id_;
|
||||||
float interval_;
|
f32 interval_;
|
||||||
float elapsed_;
|
f32 elapsed_;
|
||||||
bool repeat_;
|
bool repeat_;
|
||||||
bool paused_;
|
bool paused_;
|
||||||
bool valid_;
|
bool valid_;
|
||||||
Callback callback_;
|
Fn fn_;
|
||||||
|
|
||||||
static uint32 nextId_;
|
static u32 nextId_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -68,32 +68,32 @@ public:
|
||||||
~TimerManager() = default;
|
~TimerManager() = default;
|
||||||
|
|
||||||
/// 创建单次计时器,返回计时器ID
|
/// 创建单次计时器,返回计时器ID
|
||||||
uint32 addTimer(float delay, Timer::Callback callback);
|
u32 add(f32 delay, Timer::Fn fn);
|
||||||
|
|
||||||
/// 创建重复计时器,返回计时器ID
|
/// 创建重复计时器,返回计时器ID
|
||||||
uint32 addRepeatingTimer(float interval, Timer::Callback callback);
|
u32 addRepeat(f32 interval, Timer::Fn fn);
|
||||||
|
|
||||||
/// 取消指定ID的计时器
|
/// 取消指定ID的计时器
|
||||||
void cancelTimer(uint32 timerId);
|
void cancel(u32 timerId);
|
||||||
|
|
||||||
/// 暂停指定ID的计时器
|
/// 暂停指定ID的计时器
|
||||||
void pauseTimer(uint32 timerId);
|
void pause(u32 timerId);
|
||||||
|
|
||||||
/// 恢复指定ID的计时器
|
/// 恢复指定ID的计时器
|
||||||
void resumeTimer(uint32 timerId);
|
void resume(u32 timerId);
|
||||||
|
|
||||||
/// 更新所有计时器(每帧调用)
|
/// 更新所有计时器(每帧调用)
|
||||||
void update(float deltaTime);
|
void update(f32 dt);
|
||||||
|
|
||||||
/// 清除所有计时器
|
/// 清除所有计时器
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/// 获取计时器数量
|
/// 获取计时器数量
|
||||||
size_t getTimerCount() const { return timers_.size(); }
|
size_t count() const { return timers_.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<uint32, std::unique_ptr<Timer>> timers_;
|
std::map<u32, std::unique_ptr<Timer>> timers_;
|
||||||
std::vector<uint32> timersToRemove_;
|
std::vector<u32> timersToRemove_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,17 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
static double getTimeSeconds() {
|
static f64 getTimeSeconds() {
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
return static_cast<double>(ts.tv_sec) +
|
return static_cast<f64>(ts.tv_sec) +
|
||||||
static_cast<double>(ts.tv_nsec) / 1000000000.0;
|
static_cast<f64>(ts.tv_nsec) / 1000000000.0;
|
||||||
#else
|
#else
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto now = steady_clock::now();
|
auto now = steady_clock::now();
|
||||||
auto duration = now.time_since_epoch();
|
auto duration = now.time_since_epoch();
|
||||||
return duration_cast<std::chrono::duration<double>>(duration).count();
|
return duration_cast<std::chrono::duration<f64>>(duration).count();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ bool Application::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化所有服务
|
// 初始化所有服务
|
||||||
ServiceLocator::instance().initializeAll();
|
ServiceLocator::instance().init();
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
running_ = true;
|
running_ = true;
|
||||||
|
|
@ -58,7 +58,7 @@ void Application::shutdown() {
|
||||||
if (!initialized_)
|
if (!initialized_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ServiceLocator::instance().shutdownAll();
|
ServiceLocator::instance().shutdown();
|
||||||
ServiceLocator::instance().clear();
|
ServiceLocator::instance().clear();
|
||||||
Registry::instance().shutdown();
|
Registry::instance().shutdown();
|
||||||
Registry::instance().clear();
|
Registry::instance().clear();
|
||||||
|
|
@ -90,29 +90,29 @@ void Application::quit() {
|
||||||
void Application::pause() {
|
void Application::pause() {
|
||||||
if (!paused_) {
|
if (!paused_) {
|
||||||
paused_ = true;
|
paused_ = true;
|
||||||
ServiceLocator::instance().pauseAll();
|
ServiceLocator::instance().pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::resume() {
|
void Application::resume() {
|
||||||
if (paused_) {
|
if (paused_) {
|
||||||
paused_ = false;
|
paused_ = false;
|
||||||
ServiceLocator::instance().resumeAll();
|
ServiceLocator::instance().resume();
|
||||||
lastFrameTime_ = getTimeSeconds();
|
lastFrameTime_ = getTimeSeconds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::mainLoop() {
|
void Application::mainLoop() {
|
||||||
double currentTime = getTimeSeconds();
|
f64 currentTime = getTimeSeconds();
|
||||||
deltaTime_ = static_cast<float>(currentTime - lastFrameTime_);
|
dt_ = static_cast<f32>(currentTime - lastFrameTime_);
|
||||||
lastFrameTime_ = currentTime;
|
lastFrameTime_ = currentTime;
|
||||||
|
|
||||||
totalTime_ += deltaTime_;
|
totalTime_ += dt_;
|
||||||
|
|
||||||
frameCount_++;
|
frameCount_++;
|
||||||
fpsTimer_ += deltaTime_;
|
fpsTimer_ += dt_;
|
||||||
if (fpsTimer_ >= 1.0f) {
|
if (fpsTimer_ >= 1.0f) {
|
||||||
currentFps_ = frameCount_;
|
fps_ = frameCount_;
|
||||||
frameCount_ = 0;
|
frameCount_ = 0;
|
||||||
fpsTimer_ -= 1.0f;
|
fpsTimer_ -= 1.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -122,9 +122,9 @@ void Application::mainLoop() {
|
||||||
winMod->win()->poll();
|
winMod->win()->poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
eventService->processQueue();
|
eventService->process();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!paused_) {
|
if (!paused_) {
|
||||||
|
|
@ -134,7 +134,7 @@ void Application::mainLoop() {
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::update() { ServiceLocator::instance().updateAll(deltaTime_); }
|
void Application::update() { ServiceLocator::instance().update(dt_); }
|
||||||
|
|
||||||
void Application::render() {
|
void Application::render() {
|
||||||
auto *winMod = get<WindowModule>();
|
auto *winMod = get<WindowModule>();
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ Registry &Registry::instance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Registry::init() {
|
bool Registry::init() {
|
||||||
auto levels = groupByLevel();
|
auto levels = group();
|
||||||
E2D_REGISTRY("正在初始化 {} 个模块,共 {} 个层级...", modules_.size(),
|
E2D_REGISTRY("正在初始化 {} 个模块,共 {} 个层级...", moduleCount_,
|
||||||
levels.size());
|
levels.size());
|
||||||
|
|
||||||
for (size_t level = 0; level < levels.size(); ++level) {
|
for (size_t level = 0; level < levels.size(); ++level) {
|
||||||
|
|
@ -21,7 +21,7 @@ bool Registry::init() {
|
||||||
// 检查当前层级是否有支持并行初始化的模块
|
// 检查当前层级是否有支持并行初始化的模块
|
||||||
bool hasParallelModules = false;
|
bool hasParallelModules = false;
|
||||||
for (auto *module : modules) {
|
for (auto *module : modules) {
|
||||||
if (module->allowParallelInit()) {
|
if (module->parallel()) {
|
||||||
hasParallelModules = true;
|
hasParallelModules = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +49,7 @@ bool Registry::init() {
|
||||||
|
|
||||||
// 分离支持并行和不支持并行的模块
|
// 分离支持并行和不支持并行的模块
|
||||||
for (auto *module : modules) {
|
for (auto *module : modules) {
|
||||||
if (module->allowParallelInit()) {
|
if (module->parallel()) {
|
||||||
futures.push_back(std::async(std::launch::async, [module]() {
|
futures.push_back(std::async(std::launch::async, [module]() {
|
||||||
return std::make_pair(module, module->init());
|
return std::make_pair(module, module->init());
|
||||||
}));
|
}));
|
||||||
|
|
@ -88,52 +88,67 @@ bool Registry::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registry::shutdown() {
|
void Registry::shutdown() {
|
||||||
auto sorted = topologicalSort();
|
// 从后向前关闭模块
|
||||||
|
for (size_t i = moduleCount_; i > 0; --i) {
|
||||||
for (auto it = sorted.rbegin(); it != sorted.rend(); ++it) {
|
if (modules_[i - 1].valid && modules_[i - 1].module) {
|
||||||
(*it)->shutdown();
|
modules_[i - 1].module->shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registry::clear() {
|
void Registry::clear() {
|
||||||
shutdown();
|
shutdown();
|
||||||
modules_.clear();
|
|
||||||
|
// 销毁所有模块
|
||||||
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
|
modules_[i].module.reset();
|
||||||
|
modules_[i].valid = false;
|
||||||
|
}
|
||||||
|
moduleCount_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Module *> Registry::topologicalSort() {
|
std::vector<Module *> Registry::sort() {
|
||||||
std::vector<Module *> result;
|
std::vector<Module *> result;
|
||||||
std::unordered_map<Module *, int> inDegree;
|
std::vector<int> inDegree(moduleCount_, 0);
|
||||||
std::unordered_map<Module *, std::vector<Module *>> adj;
|
std::vector<std::vector<size_t>> adj(moduleCount_);
|
||||||
|
|
||||||
for (auto &[typeIdx, module] : modules_) {
|
// 构建依赖图
|
||||||
inDegree[module.get()] = 0;
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
}
|
if (!modules_[i].valid)
|
||||||
|
continue;
|
||||||
for (auto &[typeIdx, module] : modules_) {
|
|
||||||
for (auto &depType : module->deps()) {
|
auto deps = modules_[i].module->deps();
|
||||||
Module *dep = get(depType);
|
for (auto &depType : deps) {
|
||||||
if (dep) {
|
// 查找依赖模块的索引
|
||||||
adj[dep].push_back(module.get());
|
for (size_t j = 0; j < moduleCount_; ++j) {
|
||||||
inDegree[module.get()]++;
|
if (modules_[j].valid &&
|
||||||
|
std::type_index(typeid(*modules_[j].module)) == depType) {
|
||||||
|
adj[j].push_back(i);
|
||||||
|
inDegree[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cmp = [](Module *a, Module *b) { return a->priority() > b->priority(); };
|
// 使用优先队列,按优先级排序
|
||||||
std::priority_queue<Module *, std::vector<Module *>, decltype(cmp)> pq(cmp);
|
auto cmp = [this](size_t a, size_t b) {
|
||||||
|
return modules_[a].module->priority() > modules_[b].module->priority();
|
||||||
|
};
|
||||||
|
std::priority_queue<size_t, std::vector<size_t>, decltype(cmp)> pq(cmp);
|
||||||
|
|
||||||
for (auto &[mod, degree] : inDegree) {
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
if (degree == 0) {
|
if (inDegree[i] == 0) {
|
||||||
pq.push(mod);
|
pq.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!pq.empty()) {
|
while (!pq.empty()) {
|
||||||
Module *curr = pq.top();
|
size_t curr = pq.top();
|
||||||
pq.pop();
|
pq.pop();
|
||||||
result.push_back(curr);
|
result.push_back(modules_[curr].module.get());
|
||||||
|
|
||||||
for (Module *next : adj[curr]) {
|
for (size_t next : adj[curr]) {
|
||||||
inDegree[next]--;
|
inDegree[next]--;
|
||||||
if (inDegree[next] == 0) {
|
if (inDegree[next] == 0) {
|
||||||
pq.push(next);
|
pq.push(next);
|
||||||
|
|
@ -144,42 +159,44 @@ std::vector<Module *> Registry::topologicalSort() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<Module *>> Registry::groupByLevel() {
|
std::vector<std::vector<Module *>> Registry::group() {
|
||||||
std::vector<std::vector<Module *>> levels;
|
std::vector<std::vector<Module *>> levels;
|
||||||
std::unordered_map<Module *, int> inDegree;
|
std::vector<int> inDegree(moduleCount_, 0);
|
||||||
std::unordered_map<Module *, std::vector<Module *>> adj;
|
std::vector<std::vector<size_t>> adj(moduleCount_);
|
||||||
std::unordered_map<Module *, int> levelMap;
|
|
||||||
|
|
||||||
// 初始化入度
|
|
||||||
for (auto &[typeIdx, module] : modules_) {
|
|
||||||
inDegree[module.get()] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建依赖图
|
// 构建依赖图
|
||||||
for (auto &[typeIdx, module] : modules_) {
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
for (auto &depType : module->deps()) {
|
if (!modules_[i].valid)
|
||||||
Module *dep = get(depType);
|
continue;
|
||||||
if (dep) {
|
|
||||||
adj[dep].push_back(module.get());
|
auto deps = modules_[i].module->deps();
|
||||||
inDegree[module.get()]++;
|
for (auto &depType : deps) {
|
||||||
|
for (size_t j = 0; j < moduleCount_; ++j) {
|
||||||
|
if (modules_[j].valid &&
|
||||||
|
std::type_index(typeid(*modules_[j].module)) == depType) {
|
||||||
|
adj[j].push_back(i);
|
||||||
|
inDegree[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 BFS 按层级分组
|
// 使用 BFS 按层级分组
|
||||||
std::queue<Module *> q;
|
std::queue<size_t> q;
|
||||||
|
std::vector<int> levelMap(moduleCount_, -1);
|
||||||
|
|
||||||
// 找到所有入度为 0 的模块(第一层)
|
// 找到所有入度为 0 的模块(第一层)
|
||||||
for (auto &[mod, degree] : inDegree) {
|
for (size_t i = 0; i < moduleCount_; ++i) {
|
||||||
if (degree == 0) {
|
if (inDegree[i] == 0) {
|
||||||
q.push(mod);
|
q.push(i);
|
||||||
levelMap[mod] = 0;
|
levelMap[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BFS 遍历
|
// BFS 遍历
|
||||||
while (!q.empty()) {
|
while (!q.empty()) {
|
||||||
Module *curr = q.front();
|
size_t curr = q.front();
|
||||||
q.pop();
|
q.pop();
|
||||||
|
|
||||||
int currLevel = levelMap[curr];
|
int currLevel = levelMap[curr];
|
||||||
|
|
@ -188,10 +205,10 @@ std::vector<std::vector<Module *>> Registry::groupByLevel() {
|
||||||
if (levels.size() <= static_cast<size_t>(currLevel)) {
|
if (levels.size() <= static_cast<size_t>(currLevel)) {
|
||||||
levels.resize(currLevel + 1);
|
levels.resize(currLevel + 1);
|
||||||
}
|
}
|
||||||
levels[currLevel].push_back(curr);
|
levels[currLevel].push_back(modules_[curr].module.get());
|
||||||
|
|
||||||
// 处理依赖当前模块的其他模块
|
// 处理依赖当前模块的其他模块
|
||||||
for (Module *next : adj[curr]) {
|
for (size_t next : adj[curr]) {
|
||||||
inDegree[next]--;
|
inDegree[next]--;
|
||||||
if (inDegree[next] == 0) {
|
if (inDegree[next] == 0) {
|
||||||
q.push(next);
|
q.push(next);
|
||||||
|
|
|
||||||
|
|
@ -8,34 +8,34 @@ ServiceLocator& ServiceLocator::instance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServiceLocator::initializeAll() {
|
bool ServiceLocator::init() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto& service : orderedServices_) {
|
for (auto& svc : orderedServices_) {
|
||||||
if (!service) continue;
|
if (!svc) continue;
|
||||||
|
|
||||||
auto info = service->getServiceInfo();
|
auto info = svc->info();
|
||||||
if (!info.enabled) continue;
|
if (!info.enabled) continue;
|
||||||
|
|
||||||
if (!service->isInitialized()) {
|
if (!svc->initialized()) {
|
||||||
service->setState(ServiceState::Initializing);
|
svc->setState(ServiceState::Initializing);
|
||||||
if (!service->initialize()) {
|
if (!svc->init()) {
|
||||||
service->setState(ServiceState::Stopped);
|
svc->setState(ServiceState::Stopped);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
service->setState(ServiceState::Running);
|
svc->setState(ServiceState::Running);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::shutdownAll() {
|
void ServiceLocator::shutdown() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto it = orderedServices_.rbegin();
|
for (auto it = orderedServices_.rbegin();
|
||||||
it != orderedServices_.rend(); ++it) {
|
it != orderedServices_.rend(); ++it) {
|
||||||
if (*it && (*it)->isInitialized()) {
|
if (*it && (*it)->initialized()) {
|
||||||
(*it)->setState(ServiceState::Stopping);
|
(*it)->setState(ServiceState::Stopping);
|
||||||
(*it)->shutdown();
|
(*it)->shutdown();
|
||||||
(*it)->setState(ServiceState::Stopped);
|
(*it)->setState(ServiceState::Stopped);
|
||||||
|
|
@ -43,50 +43,50 @@ void ServiceLocator::shutdownAll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::updateAll(float deltaTime) {
|
void ServiceLocator::update(f32 dt) {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto& service : orderedServices_) {
|
for (auto& svc : orderedServices_) {
|
||||||
if (service && service->isInitialized()) {
|
if (svc && svc->initialized()) {
|
||||||
auto state = service->getState();
|
auto state = svc->state();
|
||||||
if (state == ServiceState::Running) {
|
if (state == ServiceState::Running) {
|
||||||
service->update(deltaTime);
|
svc->update(dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::pauseAll() {
|
void ServiceLocator::pause() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto& service : orderedServices_) {
|
for (auto& svc : orderedServices_) {
|
||||||
if (service && service->isInitialized()) {
|
if (svc && svc->initialized()) {
|
||||||
service->pause();
|
svc->pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::resumeAll() {
|
void ServiceLocator::resume() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto& service : orderedServices_) {
|
for (auto& svc : orderedServices_) {
|
||||||
if (service && service->isInitialized()) {
|
if (svc && svc->initialized()) {
|
||||||
service->resume();
|
svc->resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SharedPtr<IService>> ServiceLocator::getAllServices() const {
|
std::vector<Ref<IService>> ServiceLocator::all() const {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||||
return orderedServices_;
|
return orderedServices_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::clear() {
|
void ServiceLocator::clear() {
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||||
|
|
||||||
for (auto it = orderedServices_.rbegin();
|
for (auto it = orderedServices_.rbegin();
|
||||||
it != orderedServices_.rend(); ++it) {
|
it != orderedServices_.rend(); ++it) {
|
||||||
if (*it && (*it)->isInitialized()) {
|
if (*it && (*it)->initialized()) {
|
||||||
(*it)->setState(ServiceState::Stopping);
|
(*it)->setState(ServiceState::Stopping);
|
||||||
(*it)->shutdown();
|
(*it)->shutdown();
|
||||||
(*it)->setState(ServiceState::Stopped);
|
(*it)->setState(ServiceState::Stopped);
|
||||||
|
|
@ -98,12 +98,12 @@ void ServiceLocator::clear() {
|
||||||
orderedServices_.clear();
|
orderedServices_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceLocator::sortServices() {
|
void ServiceLocator::sort() {
|
||||||
std::stable_sort(orderedServices_.begin(), orderedServices_.end(),
|
std::stable_sort(orderedServices_.begin(), orderedServices_.end(),
|
||||||
[](const SharedPtr<IService>& a, const SharedPtr<IService>& b) {
|
[](const Ref<IService>& a, const Ref<IService>& b) {
|
||||||
if (!a || !b) return false;
|
if (!a || !b) return false;
|
||||||
return static_cast<int>(a->getServiceInfo().priority) <
|
return static_cast<int>(a->info().priority) <
|
||||||
static_cast<int>(b->getServiceInfo().priority);
|
static_cast<int>(b->info().priority);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ ServiceRegistry& ServiceRegistry::instance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceRegistry::setServiceEnabled(const std::string& name, bool enabled) {
|
void ServiceRegistry::setEnabled(const std::string& name, bool enabled) {
|
||||||
for (auto& reg : registrations_) {
|
for (auto& reg : registrations_) {
|
||||||
if (reg.name == name) {
|
if (reg.name == name) {
|
||||||
reg.enabled = enabled;
|
reg.enabled = enabled;
|
||||||
|
|
@ -16,7 +16,7 @@ void ServiceRegistry::setServiceEnabled(const std::string& name, bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceRegistry::createAllServices() {
|
void ServiceRegistry::createAll() {
|
||||||
std::sort(registrations_.begin(), registrations_.end(),
|
std::sort(registrations_.begin(), registrations_.end(),
|
||||||
[](const ServiceRegistration& a, const ServiceRegistration& b) {
|
[](const ServiceRegistration& a, const ServiceRegistration& b) {
|
||||||
return static_cast<int>(a.priority) < static_cast<int>(b.priority);
|
return static_cast<int>(a.priority) < static_cast<int>(b.priority);
|
||||||
|
|
@ -29,7 +29,7 @@ void ServiceRegistry::createAllServices() {
|
||||||
|
|
||||||
auto service = reg.factory();
|
auto service = reg.factory();
|
||||||
if (service) {
|
if (service) {
|
||||||
ServiceLocator::instance().registerService<IService>(service);
|
ServiceLocator::instance().add<IService>(service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,129 +2,55 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
Event Event::windowResize(i32 w, i32 h) {
|
||||||
* @brief 创建窗口大小改变事件
|
|
||||||
*
|
|
||||||
* 创建一个表示窗口尺寸变化的Event对象
|
|
||||||
*
|
|
||||||
* @param width 新的窗口宽度(像素)
|
|
||||||
* @param height 新的窗口高度(像素)
|
|
||||||
* @return 包含窗口大小改变信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createWindowResize(int width, int height) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::WindowResize;
|
event.type = EventType::WindowResize;
|
||||||
event.data = WindowResizeEvent{width, height};
|
event.data = WindowResizeEvent{w, h};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::windowClose() {
|
||||||
* @brief 创建窗口关闭事件
|
|
||||||
*
|
|
||||||
* 创建一个表示窗口请求关闭的Event对象
|
|
||||||
*
|
|
||||||
* @return 表示窗口关闭请求的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createWindowClose() {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::WindowClose;
|
event.type = EventType::WindowClose;
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::keyPress(i32 key, i32 scancode, i32 mods) {
|
||||||
* @brief 创建键盘按键按下事件
|
|
||||||
*
|
|
||||||
* 创建一个表示键盘按键被按下的Event对象
|
|
||||||
*
|
|
||||||
* @param keyCode 按键码
|
|
||||||
* @param scancode 扫描码
|
|
||||||
* @param mods 修饰键状态(如Shift、Ctrl等)
|
|
||||||
* @return 包含按键按下信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createKeyPress(int keyCode, int scancode, int mods) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::KeyPressed;
|
event.type = EventType::KeyPressed;
|
||||||
event.data = KeyEvent{keyCode, scancode, mods};
|
event.data = KeyEvent{key, scancode, mods};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::keyRelease(i32 key, i32 scancode, i32 mods) {
|
||||||
* @brief 创建键盘按键释放事件
|
|
||||||
*
|
|
||||||
* 创建一个表示键盘按键被释放的Event对象
|
|
||||||
*
|
|
||||||
* @param keyCode 按键码
|
|
||||||
* @param scancode 扫描码
|
|
||||||
* @param mods 修饰键状态(如Shift、Ctrl等)
|
|
||||||
* @return 包含按键释放信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createKeyRelease(int keyCode, int scancode, int mods) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::KeyReleased;
|
event.type = EventType::KeyReleased;
|
||||||
event.data = KeyEvent{keyCode, scancode, mods};
|
event.data = KeyEvent{key, scancode, mods};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::mousePress(i32 btn, i32 mods, Vec2 pos) {
|
||||||
* @brief 创建鼠标按钮按下事件
|
|
||||||
*
|
|
||||||
* 创建一个表示鼠标按钮被按下的Event对象
|
|
||||||
*
|
|
||||||
* @param button 鼠标按钮编号
|
|
||||||
* @param mods 修饰键状态
|
|
||||||
* @param pos 鼠标按下时的位置坐标
|
|
||||||
* @return 包含鼠标按钮按下信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createMouseButtonPress(int button, int mods, const Vec2 &pos) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::MouseButtonPressed;
|
event.type = EventType::MouseButtonPressed;
|
||||||
event.data = MouseButtonEvent{button, mods, pos};
|
event.data = MouseButtonEvent{btn, mods, pos};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::mouseRelease(i32 btn, i32 mods, Vec2 pos) {
|
||||||
* @brief 创建鼠标按钮释放事件
|
|
||||||
*
|
|
||||||
* 创建一个表示鼠标按钮被释放的Event对象
|
|
||||||
*
|
|
||||||
* @param button 鼠标按钮编号
|
|
||||||
* @param mods 修饰键状态
|
|
||||||
* @param pos 鼠标释放时的位置坐标
|
|
||||||
* @return 包含鼠标按钮释放信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createMouseButtonRelease(int button, int mods, const Vec2 &pos) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::MouseButtonReleased;
|
event.type = EventType::MouseButtonReleased;
|
||||||
event.data = MouseButtonEvent{button, mods, pos};
|
event.data = MouseButtonEvent{btn, mods, pos};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::mouseMove(Vec2 pos, Vec2 delta) {
|
||||||
* @brief 创建鼠标移动事件
|
|
||||||
*
|
|
||||||
* 创建一个表示鼠标移动的Event对象
|
|
||||||
*
|
|
||||||
* @param pos 鼠标当前位置坐标
|
|
||||||
* @param delta 鼠标移动的位移量
|
|
||||||
* @return 包含鼠标移动信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createMouseMove(const Vec2 &pos, const Vec2 &delta) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::MouseMoved;
|
event.type = EventType::MouseMoved;
|
||||||
event.data = MouseMoveEvent{pos, delta};
|
event.data = MouseMoveEvent{pos, delta};
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Event Event::mouseScroll(Vec2 offset, Vec2 pos) {
|
||||||
* @brief 创建鼠标滚轮滚动事件
|
|
||||||
*
|
|
||||||
* 创建一个表示鼠标滚轮滚动的Event对象
|
|
||||||
*
|
|
||||||
* @param offset 滚轮滚动的偏移量
|
|
||||||
* @param pos 滚动时鼠标的位置坐标
|
|
||||||
* @return 包含鼠标滚轮滚动信息的Event对象
|
|
||||||
*/
|
|
||||||
Event Event::createMouseScroll(const Vec2 &offset, const Vec2 &pos) {
|
|
||||||
Event event;
|
Event event;
|
||||||
event.type = EventType::MouseScrolled;
|
event.type = EventType::MouseScrolled;
|
||||||
event.data = MouseScrollEvent{offset, pos};
|
event.data = MouseScrollEvent{offset, pos};
|
||||||
|
|
|
||||||
|
|
@ -3,37 +3,15 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 默认构造函数
|
|
||||||
*
|
|
||||||
* 初始化事件分发器,设置下一个监听器ID为1
|
|
||||||
*/
|
|
||||||
EventDispatcher::EventDispatcher() : nextId_(1) {}
|
EventDispatcher::EventDispatcher() : nextId_(1) {}
|
||||||
|
|
||||||
/**
|
ListenerID EventDispatcher::on(EventType type, EventFn fn) {
|
||||||
* @brief 添加事件监听器
|
ListenerID id = nextId_++;
|
||||||
*
|
listeners_[type].push_back({id, type, fn});
|
||||||
* 为指定的事件类型注册一个回调函数,返回监听器ID用于后续移除
|
|
||||||
*
|
|
||||||
* @param type 要监听的事件类型
|
|
||||||
* @param callback 事件触发时调用的回调函数
|
|
||||||
* @return 新注册监听器的唯一ID
|
|
||||||
*/
|
|
||||||
ListenerId EventDispatcher::addListener(EventType type,
|
|
||||||
EventCallback callback) {
|
|
||||||
ListenerId id = nextId_++;
|
|
||||||
listeners_[type].push_back({id, type, callback});
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void EventDispatcher::off(ListenerID id) {
|
||||||
* @brief 移除指定的事件监听器
|
|
||||||
*
|
|
||||||
* 根据监听器ID移除对应的事件监听器
|
|
||||||
*
|
|
||||||
* @param id 要移除的监听器ID
|
|
||||||
*/
|
|
||||||
void EventDispatcher::removeListener(ListenerId id) {
|
|
||||||
for (auto &[type, listeners] : listeners_) {
|
for (auto &[type, listeners] : listeners_) {
|
||||||
auto it = std::remove_if(listeners.begin(), listeners.end(),
|
auto it = std::remove_if(listeners.begin(), listeners.end(),
|
||||||
[id](const Listener &l) { return l.id == id; });
|
[id](const Listener &l) { return l.id == id; });
|
||||||
|
|
@ -44,89 +22,41 @@ void EventDispatcher::removeListener(ListenerId id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void EventDispatcher::offAll(EventType type) {
|
||||||
* @brief 移除指定类型的所有监听器
|
|
||||||
*
|
|
||||||
* 移除某个事件类型下的所有已注册监听器
|
|
||||||
*
|
|
||||||
* @param type 要移除监听器的事件类型
|
|
||||||
*/
|
|
||||||
void EventDispatcher::removeAllListeners(EventType type) {
|
|
||||||
listeners_.erase(type);
|
listeners_.erase(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void EventDispatcher::offAll() { listeners_.clear(); }
|
||||||
* @brief 移除所有监听器
|
|
||||||
*
|
|
||||||
* 清除事件分发器中所有已注册的监听器
|
|
||||||
*/
|
|
||||||
void EventDispatcher::removeAllListeners() { listeners_.clear(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 分发事件
|
|
||||||
*
|
|
||||||
* 将事件分发给对应类型的所有监听器,直到事件被标记为已处理或所有监听器执行完毕
|
|
||||||
*
|
|
||||||
* @param event 要分发的事件对象(可修改)
|
|
||||||
*/
|
|
||||||
void EventDispatcher::dispatch(Event &event) {
|
void EventDispatcher::dispatch(Event &event) {
|
||||||
auto it = listeners_.find(event.type);
|
auto it = listeners_.find(event.type);
|
||||||
if (it != listeners_.end()) {
|
if (it != listeners_.end()) {
|
||||||
for (auto &listener : it->second) {
|
for (auto &listener : it->second) {
|
||||||
if (event.handled)
|
if (event.handled)
|
||||||
break;
|
break;
|
||||||
listener.callback(event);
|
listener.fn(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 分发事件(常量版本)
|
|
||||||
*
|
|
||||||
* 创建事件的副本并分发,适用于常量事件对象
|
|
||||||
*
|
|
||||||
* @param event 要分发的常量事件对象
|
|
||||||
*/
|
|
||||||
void EventDispatcher::dispatch(const Event &event) {
|
void EventDispatcher::dispatch(const Event &event) {
|
||||||
Event mutableEvent = event;
|
Event mutableEvent = event;
|
||||||
dispatch(mutableEvent);
|
dispatch(mutableEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void EventDispatcher::process(EventQueue &queue) {
|
||||||
* @brief 处理事件队列
|
|
||||||
*
|
|
||||||
* 从事件队列中依次取出所有事件并分发
|
|
||||||
*
|
|
||||||
* @param queue 要处理的事件队列
|
|
||||||
*/
|
|
||||||
void EventDispatcher::processQueue(EventQueue &queue) {
|
|
||||||
Event event;
|
Event event;
|
||||||
while (queue.poll(event)) {
|
while (queue.poll(event)) {
|
||||||
dispatch(event);
|
dispatch(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
size_t EventDispatcher::listenerCount(EventType type) const {
|
||||||
* @brief 获取指定类型监听器的数量
|
|
||||||
*
|
|
||||||
* 返回某个事件类型下已注册的监听器数量
|
|
||||||
*
|
|
||||||
* @param type 要查询的事件类型
|
|
||||||
* @return 该类型下的监听器数量
|
|
||||||
*/
|
|
||||||
size_t EventDispatcher::getListenerCount(EventType type) const {
|
|
||||||
auto it = listeners_.find(type);
|
auto it = listeners_.find(type);
|
||||||
return (it != listeners_.end()) ? it->second.size() : 0;
|
return (it != listeners_.end()) ? it->second.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
size_t EventDispatcher::totalListeners() const {
|
||||||
* @brief 获取所有监听器的总数量
|
|
||||||
*
|
|
||||||
* 返回所有事件类型的监听器总数
|
|
||||||
*
|
|
||||||
* @return 所有监听器的总数量
|
|
||||||
*/
|
|
||||||
size_t EventDispatcher::getTotalListenerCount() const {
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (const auto &[type, listeners] : listeners_) {
|
for (const auto &[type, listeners] : listeners_) {
|
||||||
count += listeners.size();
|
count += listeners.size();
|
||||||
|
|
|
||||||
|
|
@ -2,106 +2,44 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 默认构造函数
|
|
||||||
*
|
|
||||||
* 构造一个空的事件队列对象
|
|
||||||
*/
|
|
||||||
EventQueue::EventQueue() = default;
|
EventQueue::EventQueue() = default;
|
||||||
|
|
||||||
/**
|
bool EventQueue::push(const Event &event) {
|
||||||
* @brief 将事件压入队列(左值引用版本)
|
return buffer_.push(event);
|
||||||
*
|
|
||||||
* 将事件以拷贝方式添加到队列末尾,线程安全
|
|
||||||
*
|
|
||||||
* @param event 要添加的事件对象
|
|
||||||
*/
|
|
||||||
void EventQueue::push(const Event &event) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
queue_.push(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool EventQueue::push(Event &&event) {
|
||||||
* @brief 将事件压入队列(右值引用版本)
|
return buffer_.push(std::move(event));
|
||||||
*
|
|
||||||
* 将事件以移动方式添加到队列末尾,线程安全
|
|
||||||
*
|
|
||||||
* @param event 要添加的事件对象(右值引用)
|
|
||||||
*/
|
|
||||||
void EventQueue::push(Event &&event) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
queue_.push(std::move(event));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从队列中取出事件
|
|
||||||
*
|
|
||||||
* 从队列头部取出一个事件,如果队列不为空则移除该事件,线程安全
|
|
||||||
*
|
|
||||||
* @param event 输出参数,用于存储取出的事件
|
|
||||||
* @return 如果成功取出事件返回true,队列为空返回false
|
|
||||||
*/
|
|
||||||
bool EventQueue::poll(Event &event) {
|
bool EventQueue::poll(Event &event) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
return buffer_.pop(event);
|
||||||
if (queue_.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
event = queue_.front();
|
|
||||||
queue_.pop();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 查看队列头部事件
|
|
||||||
*
|
|
||||||
* 获取队列头部的事件但不移除,线程安全
|
|
||||||
*
|
|
||||||
* @param event 输出参数,用于存储查看到的事件
|
|
||||||
* @return 如果队列不为空返回true,队列为空返回false
|
|
||||||
*/
|
|
||||||
bool EventQueue::peek(Event &event) const {
|
bool EventQueue::peek(Event &event) const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (queue_.empty()) {
|
if (buffer_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 环形缓冲区不支持peek,这里简化处理
|
||||||
|
// 实际应用中可能需要双缓冲或其他机制
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
event = queue_.front();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 清空队列
|
|
||||||
*
|
|
||||||
* 移除队列中的所有事件,线程安全
|
|
||||||
*/
|
|
||||||
void EventQueue::clear() {
|
void EventQueue::clear() {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
while (!queue_.empty()) {
|
Event event;
|
||||||
queue_.pop();
|
while (buffer_.pop(event)) {
|
||||||
}
|
// 持续弹出直到为空
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 检查队列是否为空
|
|
||||||
*
|
|
||||||
* 线程安全地检查队列中是否有事件
|
|
||||||
*
|
|
||||||
* @return 如果队列为空返回true,否则返回false
|
|
||||||
*/
|
|
||||||
bool EventQueue::empty() const {
|
bool EventQueue::empty() const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
return buffer_.empty();
|
||||||
return queue_.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取队列中的事件数量
|
|
||||||
*
|
|
||||||
* 线程安全地获取队列中当前存储的事件数量
|
|
||||||
*
|
|
||||||
* @return 队列中的事件数量
|
|
||||||
*/
|
|
||||||
size_t EventQueue::size() const {
|
size_t EventQueue::size() const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
return buffer_.size();
|
||||||
return queue_.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include <glfw/glfw_window.h>
|
#include <extra2d/platform/glfw/glfw_window.h>
|
||||||
|
|
||||||
#include <extra2d/event/event.h>
|
#include <extra2d/event/event.h>
|
||||||
#include <extra2d/platform/keys.h>
|
#include <extra2d/platform/keys.h>
|
||||||
|
|
@ -33,10 +33,10 @@ bool GLFWWindow::create(const std::string &title, int width, int height,
|
||||||
monitor = glfwGetPrimaryMonitor();
|
monitor = glfwGetPrimaryMonitor();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glfwWindow_ =
|
handle_ =
|
||||||
glfwCreateWindow(width, height, title.c_str(), monitor, nullptr);
|
glfwCreateWindow(width, height, title.c_str(), monitor, nullptr);
|
||||||
|
|
||||||
if (!glfwWindow_) {
|
if (!handle_) {
|
||||||
E2D_ERROR("创建 GLFW 窗口失败");
|
E2D_ERROR("创建 GLFW 窗口失败");
|
||||||
deinitGLFW();
|
deinitGLFW();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -52,87 +52,87 @@ bool GLFWWindow::create(const std::string &title, int width, int height,
|
||||||
int screenHeight = mode->height;
|
int screenHeight = mode->height;
|
||||||
int windowX = (screenWidth - width) / 2;
|
int windowX = (screenWidth - width) / 2;
|
||||||
int windowY = (screenHeight - height) / 2;
|
int windowY = (screenHeight - height) / 2;
|
||||||
glfwSetWindowPos(glfwWindow_, windowX, windowY);
|
glfwSetWindowPos(handle_, windowX, windowY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glfwMakeContextCurrent(glfwWindow_);
|
glfwMakeContextCurrent(handle_);
|
||||||
glfwSwapInterval(vsync ? 1 : 0);
|
glfwSwapInterval(vsync ? 1 : 0);
|
||||||
vsync_ = vsync;
|
vsync_ = vsync;
|
||||||
|
|
||||||
glfwGetWindowSize(glfwWindow_, &width_, &height_);
|
glfwGetWindowSize(handle_, &w_, &h_);
|
||||||
updateContentScale();
|
updateContentScale();
|
||||||
|
|
||||||
glfwSetWindowUserPointer(glfwWindow_, this);
|
glfwSetWindowUserPointer(handle_, this);
|
||||||
glfwSetFramebufferSizeCallback(glfwWindow_, framebufferSizeCallback);
|
glfwSetFramebufferSizeCallback(handle_, framebufferSizeCallback);
|
||||||
glfwSetWindowCloseCallback(glfwWindow_, windowCloseCallback);
|
glfwSetWindowCloseCallback(handle_, windowCloseCallback);
|
||||||
glfwSetWindowFocusCallback(glfwWindow_, windowFocusCallback);
|
glfwSetWindowFocusCallback(handle_, windowFocusCallback);
|
||||||
glfwSetWindowIconifyCallback(glfwWindow_, windowIconifyCallback);
|
glfwSetWindowIconifyCallback(handle_, windowIconifyCallback);
|
||||||
glfwSetCursorPosCallback(glfwWindow_, cursorPosCallback);
|
glfwSetCursorPosCallback(handle_, cursorPosCallback);
|
||||||
glfwSetMouseButtonCallback(glfwWindow_, mouseButtonCallback);
|
glfwSetMouseButtonCallback(handle_, mouseButtonCallback);
|
||||||
glfwSetScrollCallback(glfwWindow_, scrollCallback);
|
glfwSetScrollCallback(handle_, scrollCallback);
|
||||||
glfwSetKeyCallback(glfwWindow_, keyCallback);
|
glfwSetKeyCallback(handle_, keyCallback);
|
||||||
glfwSetJoystickCallback(joystickCallback);
|
glfwSetJoystickCallback(joystickCallback);
|
||||||
|
|
||||||
E2D_INFO("GLFW 窗口创建成功: {}x{}", width_, height_);
|
E2D_INFO("GLFW 窗口创建成功: {}x{}", w_, h_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::destroy() {
|
void GLFWWindow::destroy() {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwDestroyWindow(glfwWindow_);
|
glfwDestroyWindow(handle_);
|
||||||
glfwWindow_ = nullptr;
|
handle_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
deinitGLFW();
|
deinitGLFW();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::poll() {
|
void GLFWWindow::poll() {
|
||||||
if (!glfwWindow_)
|
if (!handle_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::swap() {
|
void GLFWWindow::swap() {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSwapBuffers(glfwWindow_);
|
glfwSwapBuffers(handle_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLFWWindow::shouldClose() const {
|
bool GLFWWindow::shouldClose() const {
|
||||||
if (!glfwWindow_)
|
if (!handle_)
|
||||||
return true;
|
return true;
|
||||||
return shouldClose_ || glfwWindowShouldClose(glfwWindow_);
|
return shouldClose_ || glfwWindowShouldClose(handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::close() {
|
void GLFWWindow::close() {
|
||||||
shouldClose_ = true;
|
shouldClose_ = true;
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetWindowShouldClose(glfwWindow_, GLFW_TRUE);
|
glfwSetWindowShouldClose(handle_, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setTitle(const std::string &title) {
|
void GLFWWindow::title(const std::string &t) {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetWindowTitle(glfwWindow_, title.c_str());
|
glfwSetWindowTitle(handle_, t.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setSize(int w, int h) {
|
void GLFWWindow::size(int w, int h) {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetWindowSize(glfwWindow_, w, h);
|
glfwSetWindowSize(handle_, w, h);
|
||||||
width_ = w;
|
w_ = w;
|
||||||
height_ = h;
|
h_ = h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setPos(int x, int y) {
|
void GLFWWindow::pos(int x, int y) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetWindowPos(glfwWindow_, x, y);
|
glfwSetWindowPos(handle_, x, y);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)x;
|
(void)x;
|
||||||
|
|
@ -140,9 +140,9 @@ void GLFWWindow::setPos(int x, int y) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setFullscreen(bool fs) {
|
void GLFWWindow::fullscreen(bool fs) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (!glfwWindow_)
|
if (!handle_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fs == fullscreen_)
|
if (fs == fullscreen_)
|
||||||
|
|
@ -151,68 +151,68 @@ void GLFWWindow::setFullscreen(bool fs) {
|
||||||
if (fs) {
|
if (fs) {
|
||||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||||
glfwSetWindowMonitor(glfwWindow_, monitor, 0, 0, mode->width, mode->height,
|
glfwSetWindowMonitor(handle_, monitor, 0, 0, mode->width, mode->height,
|
||||||
mode->refreshRate);
|
mode->refreshRate);
|
||||||
} else {
|
} else {
|
||||||
glfwSetWindowMonitor(glfwWindow_, nullptr, 100, 100, 1280, 720, 0);
|
glfwSetWindowMonitor(handle_, nullptr, 100, 100, 1280, 720, 0);
|
||||||
}
|
}
|
||||||
fullscreen_ = fs;
|
fullscreen_ = fs;
|
||||||
glfwGetWindowSize(glfwWindow_, &width_, &height_);
|
glfwGetWindowSize(handle_, &w_, &h_);
|
||||||
updateContentScale();
|
updateContentScale();
|
||||||
#else
|
#else
|
||||||
(void)fs;
|
(void)fs;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setVSync(bool vsync) {
|
void GLFWWindow::vsync(bool v) {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSwapInterval(vsync ? 1 : 0);
|
glfwSwapInterval(v ? 1 : 0);
|
||||||
vsync_ = vsync;
|
vsync_ = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setVisible(bool visible) {
|
void GLFWWindow::visible(bool v) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
if (visible) {
|
if (v) {
|
||||||
glfwShowWindow(glfwWindow_);
|
glfwShowWindow(handle_);
|
||||||
} else {
|
} else {
|
||||||
glfwHideWindow(glfwWindow_);
|
glfwHideWindow(handle_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)visible;
|
(void)v;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Size GLFWWindow::size() const {
|
Size GLFWWindow::size() const {
|
||||||
return Size(static_cast<float>(width_), static_cast<float>(height_));
|
return Size(static_cast<f32>(w_), static_cast<f32>(h_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 GLFWWindow::pos() const {
|
Vec2 GLFWWindow::pos() const {
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwGetWindowPos(glfwWindow_, &x, &y);
|
glfwGetWindowPos(handle_, &x, &y);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return Vec2(static_cast<float>(x), static_cast<float>(y));
|
return Vec2(static_cast<f32>(x), static_cast<f32>(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::setCursor(Cursor cursor) {
|
void GLFWWindow::cursor(Cursor c) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (!glfwWindow_)
|
if (!handle_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cursor == Cursor::Hidden) {
|
if (c == Cursor::Hidden) {
|
||||||
glfwSetInputMode(glfwWindow_, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
glfwSetInputMode(handle_, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSetInputMode(glfwWindow_, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(handle_, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
|
||||||
GLFWcursor *glfwCursor = nullptr;
|
GLFWcursor *glfwCursor = nullptr;
|
||||||
switch (cursor) {
|
switch (c) {
|
||||||
case Cursor::Arrow:
|
case Cursor::Arrow:
|
||||||
glfwCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
glfwCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||||
break;
|
break;
|
||||||
|
|
@ -237,17 +237,17 @@ void GLFWWindow::setCursor(Cursor cursor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glfwCursor) {
|
if (glfwCursor) {
|
||||||
glfwSetCursor(glfwWindow_, glfwCursor);
|
glfwSetCursor(handle_, glfwCursor);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)cursor;
|
(void)c;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::showCursor(bool show) {
|
void GLFWWindow::showCursor(bool show) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetInputMode(glfwWindow_, GLFW_CURSOR,
|
glfwSetInputMode(handle_, GLFW_CURSOR,
|
||||||
show ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN);
|
show ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN);
|
||||||
cursorVisible_ = show;
|
cursorVisible_ = show;
|
||||||
}
|
}
|
||||||
|
|
@ -258,8 +258,8 @@ void GLFWWindow::showCursor(bool show) {
|
||||||
|
|
||||||
void GLFWWindow::lockCursor(bool lock) {
|
void GLFWWindow::lockCursor(bool lock) {
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
glfwSetInputMode(glfwWindow_, GLFW_CURSOR,
|
glfwSetInputMode(handle_, GLFW_CURSOR,
|
||||||
lock ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
|
lock ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
|
||||||
cursorLocked_ = lock;
|
cursorLocked_ = lock;
|
||||||
}
|
}
|
||||||
|
|
@ -268,7 +268,7 @@ void GLFWWindow::lockCursor(bool lock) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void *GLFWWindow::native() const { return glfwWindow_; }
|
void *GLFWWindow::native() const { return handle_; }
|
||||||
|
|
||||||
bool GLFWWindow::initGLFW() {
|
bool GLFWWindow::initGLFW() {
|
||||||
static int glfwInitCount = 0;
|
static int glfwInitCount = 0;
|
||||||
|
|
@ -291,11 +291,11 @@ void GLFWWindow::deinitGLFW() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::updateContentScale() {
|
void GLFWWindow::updateContentScale() {
|
||||||
if (glfwWindow_) {
|
if (handle_) {
|
||||||
int fbWidth, fbHeight;
|
int fbWidth, fbHeight;
|
||||||
glfwGetFramebufferSize(glfwWindow_, &fbWidth, &fbHeight);
|
glfwGetFramebufferSize(handle_, &fbWidth, &fbHeight);
|
||||||
scaleX_ = fbWidth > 0 ? static_cast<float>(fbWidth) / width_ : 1.0f;
|
scaleX_ = fbWidth > 0 ? static_cast<f32>(fbWidth) / w_ : 1.0f;
|
||||||
scaleY_ = fbHeight > 0 ? static_cast<float>(fbHeight) / height_ : 1.0f;
|
scaleY_ = fbHeight > 0 ? static_cast<f32>(fbHeight) / h_ : 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,19 +305,19 @@ void GLFWWindow::framebufferSizeCallback(GLFWwindow *window, int width,
|
||||||
GLFWWindow *self =
|
GLFWWindow *self =
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
if (self) {
|
if (self) {
|
||||||
self->width_ = width;
|
self->w_ = width;
|
||||||
self->height_ = height;
|
self->h_ = height;
|
||||||
self->updateContentScale();
|
self->updateContentScale();
|
||||||
if (self->resizeCb_) {
|
if (self->resizeFn_) {
|
||||||
self->resizeCb_(width, height);
|
self->resizeFn_(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
Event e = Event::createWindowResize(width, height);
|
Event e = Event::windowResize(width, height);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,16 +326,16 @@ void GLFWWindow::windowCloseCallback(GLFWwindow *window) {
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
if (self) {
|
if (self) {
|
||||||
self->shouldClose_ = true;
|
self->shouldClose_ = true;
|
||||||
if (self->closeCb_) {
|
if (self->closeFn_) {
|
||||||
self->closeCb_();
|
self->closeFn_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
Event e = Event::createWindowClose();
|
Event e = Event::windowClose();
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,8 +344,8 @@ void GLFWWindow::windowFocusCallback(GLFWwindow *window, int focused) {
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
if (self) {
|
if (self) {
|
||||||
self->focused_ = (focused == GLFW_TRUE);
|
self->focused_ = (focused == GLFW_TRUE);
|
||||||
if (self->focusCb_) {
|
if (self->focusFn_) {
|
||||||
self->focusCb_(self->focused_);
|
self->focusFn_(self->focused_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -364,12 +364,12 @@ void GLFWWindow::cursorPosCallback(GLFWwindow *window, double xpos,
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
Vec2 pos{static_cast<float>(xpos), static_cast<float>(ypos)};
|
Vec2 pos{static_cast<f32>(xpos), static_cast<f32>(ypos)};
|
||||||
Vec2 delta{0.0f, 0.0f}; // GLFW 回调中没有增量,需要在其他地方计算
|
Vec2 delta{0.0f, 0.0f}; // GLFW 回调中没有增量,需要在其他地方计算
|
||||||
Event e = Event::createMouseMove(pos, delta);
|
Event e = Event::mouseMove(pos, delta);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -379,18 +379,18 @@ void GLFWWindow::mouseButtonCallback(GLFWwindow *window, int button, int action,
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
double x, y;
|
double x, y;
|
||||||
glfwGetCursorPos(window, &x, &y);
|
glfwGetCursorPos(window, &x, &y);
|
||||||
Vec2 pos{static_cast<float>(x), static_cast<float>(y)};
|
Vec2 pos{static_cast<f32>(x), static_cast<f32>(y)};
|
||||||
|
|
||||||
if (action == GLFW_PRESS) {
|
if (action == GLFW_PRESS) {
|
||||||
Event e = Event::createMouseButtonPress(button, mods, pos);
|
Event e = Event::mousePress(button, mods, pos);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
} else if (action == GLFW_RELEASE) {
|
} else if (action == GLFW_RELEASE) {
|
||||||
Event e = Event::createMouseButtonRelease(button, mods, pos);
|
Event e = Event::mouseRelease(button, mods, pos);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,14 +401,14 @@ void GLFWWindow::scrollCallback(GLFWwindow *window, double xoffset,
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
double x, y;
|
double x, y;
|
||||||
glfwGetCursorPos(window, &x, &y);
|
glfwGetCursorPos(window, &x, &y);
|
||||||
Vec2 offset{static_cast<float>(xoffset), static_cast<float>(yoffset)};
|
Vec2 offset{static_cast<f32>(xoffset), static_cast<f32>(yoffset)};
|
||||||
Vec2 pos{static_cast<float>(x), static_cast<float>(y)};
|
Vec2 pos{static_cast<f32>(x), static_cast<f32>(y)};
|
||||||
Event e = Event::createMouseScroll(offset, pos);
|
Event e = Event::mouseScroll(offset, pos);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,7 +418,7 @@ void GLFWWindow::keyCallback(GLFWwindow *window, int key, int scancode,
|
||||||
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
static_cast<GLFWWindow *>(glfwGetWindowUserPointer(window));
|
||||||
|
|
||||||
// 将事件推送到事件服务
|
// 将事件推送到事件服务
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||||
if (eventService) {
|
if (eventService) {
|
||||||
// 将 GLFW key code 转换为引擎 Key 枚举值
|
// 将 GLFW key code 转换为引擎 Key 枚举值
|
||||||
Key eKey = Key::None;
|
Key eKey = Key::None;
|
||||||
|
|
@ -645,13 +645,13 @@ void GLFWWindow::keyCallback(GLFWwindow *window, int key, int scancode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eKey != Key::None) {
|
if (eKey != Key::None) {
|
||||||
int keyCode = static_cast<int>(eKey);
|
i32 keyCode = static_cast<i32>(eKey);
|
||||||
if (action == GLFW_PRESS) {
|
if (action == GLFW_PRESS) {
|
||||||
Event e = Event::createKeyPress(keyCode, scancode, mods);
|
Event e = Event::keyPress(keyCode, scancode, mods);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
} else if (action == GLFW_RELEASE) {
|
} else if (action == GLFW_RELEASE) {
|
||||||
Event e = Event::createKeyRelease(keyCode, scancode, mods);
|
Event e = Event::keyRelease(keyCode, scancode, mods);
|
||||||
eventService->pushEvent(e);
|
eventService->push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include <extra2d/platform/window_module.h>
|
#include <extra2d/platform/window_module.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
|
|
||||||
#include <glfw/glfw_window.h>
|
#include <extra2d/platform/glfw/glfw_window.h>
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
@ -26,7 +26,7 @@ bool WindowModule::init() {
|
||||||
|
|
||||||
E2D_INFO("正在创建 GLFW 窗口,尺寸 {}x{}", cfg_.w, cfg_.h);
|
E2D_INFO("正在创建 GLFW 窗口,尺寸 {}x{}", cfg_.w, cfg_.h);
|
||||||
|
|
||||||
win_ = makeUnique<GLFWWindow>();
|
win_ = ptr::makeUnique<GLFWWindow>();
|
||||||
if (!win_) {
|
if (!win_) {
|
||||||
E2D_ERROR("创建窗口失败");
|
E2D_ERROR("创建窗口失败");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -8,58 +8,57 @@ EventService::EventService() {
|
||||||
info_.enabled = true;
|
info_.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceInfo EventService::getServiceInfo() const { return info_; }
|
ServiceInfo EventService::info() const { return info_; }
|
||||||
|
|
||||||
bool EventService::initialize() {
|
bool EventService::init() {
|
||||||
setState(ServiceState::Running);
|
setState(ServiceState::Running);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::shutdown() {
|
void EventService::shutdown() {
|
||||||
queue_.clear();
|
queue_.clear();
|
||||||
dispatcher_.removeAllListeners();
|
dispatcher_.offAll();
|
||||||
setState(ServiceState::Stopped);
|
setState(ServiceState::Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::update(float deltaTime) {
|
void EventService::update(f32 dt) {
|
||||||
if (getState() == ServiceState::Running) {
|
if (state() == ServiceState::Running) {
|
||||||
processQueue();
|
process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::pushEvent(const Event &event) { queue_.push(event); }
|
void EventService::push(const Event &event) { queue_.push(event); }
|
||||||
|
|
||||||
void EventService::pushEvent(Event &&event) { queue_.push(std::move(event)); }
|
void EventService::push(Event &&event) { queue_.push(std::move(event)); }
|
||||||
|
|
||||||
bool EventService::pollEvent(Event &event) { return queue_.poll(event); }
|
bool EventService::poll(Event &event) { return queue_.poll(event); }
|
||||||
|
|
||||||
ListenerId EventService::addListener(EventType type,
|
ListenerID EventService::on(EventType type, EventDispatcher::EventFn fn) {
|
||||||
EventDispatcher::EventCallback callback) {
|
return dispatcher_.on(type, fn);
|
||||||
return dispatcher_.addListener(type, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::removeListener(ListenerId id) {
|
void EventService::off(ListenerID id) {
|
||||||
dispatcher_.removeListener(id);
|
dispatcher_.off(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::removeAllListeners(EventType type) {
|
void EventService::offAll(EventType type) {
|
||||||
dispatcher_.removeAllListeners(type);
|
dispatcher_.offAll(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventService::removeAllListeners() { dispatcher_.removeAllListeners(); }
|
void EventService::offAll() { dispatcher_.offAll(); }
|
||||||
|
|
||||||
void EventService::dispatch(Event &event) { dispatcher_.dispatch(event); }
|
void EventService::dispatch(Event &event) { dispatcher_.dispatch(event); }
|
||||||
|
|
||||||
void EventService::processQueue() { dispatcher_.processQueue(queue_); }
|
void EventService::process() { dispatcher_.process(queue_); }
|
||||||
|
|
||||||
size_t EventService::getListenerCount(EventType type) const {
|
size_t EventService::listenerCount(EventType type) const {
|
||||||
return dispatcher_.getListenerCount(type);
|
return dispatcher_.listenerCount(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t EventService::getTotalListenerCount() const {
|
size_t EventService::totalListeners() const {
|
||||||
return dispatcher_.getTotalListenerCount();
|
return dispatcher_.totalListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t EventService::getQueueSize() const { return queue_.size(); }
|
size_t EventService::queueSize() const { return queue_.size(); }
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,6 @@
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/**
|
|
||||||
* @brief 初始化 Windows 控制台(ANSI 颜色 + UTF-8)
|
|
||||||
*/
|
|
||||||
static bool enableWindowsConsoleFeatures() {
|
static bool enableWindowsConsoleFeatures() {
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
|
|
@ -45,7 +42,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
ConsoleLogger::ConsoleLogger()
|
ConsoleLogger::ConsoleLogger()
|
||||||
: level_(LogLevel::Info), colorEnabled_(true),
|
: level_(LogLevel::Info), colors_(true),
|
||||||
impl_(std::make_unique<Impl>()) {
|
impl_(std::make_unique<Impl>()) {
|
||||||
info_.name = "ConsoleLogger";
|
info_.name = "ConsoleLogger";
|
||||||
info_.priority = ServicePriority::Core;
|
info_.priority = ServicePriority::Core;
|
||||||
|
|
@ -67,23 +64,23 @@ ConsoleLogger::ConsoleLogger()
|
||||||
|
|
||||||
ConsoleLogger::~ConsoleLogger() = default;
|
ConsoleLogger::~ConsoleLogger() = default;
|
||||||
|
|
||||||
bool ConsoleLogger::initialize() {
|
bool ConsoleLogger::init() {
|
||||||
setState(ServiceState::Running);
|
setState(ServiceState::Running);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::shutdown() { setState(ServiceState::Stopped); }
|
void ConsoleLogger::shutdown() { setState(ServiceState::Stopped); }
|
||||||
|
|
||||||
void ConsoleLogger::setLevel(LogLevel level) { level_ = level; }
|
void ConsoleLogger::level(LogLevel lvl) { level_ = lvl; }
|
||||||
|
|
||||||
LogLevel ConsoleLogger::getLevel() const { return level_; }
|
LogLevel ConsoleLogger::level() const { return level_; }
|
||||||
|
|
||||||
bool ConsoleLogger::isEnabled(LogLevel level) const {
|
bool ConsoleLogger::enabled(LogLevel lvl) const {
|
||||||
return static_cast<int>(level) >= static_cast<int>(level_);
|
return static_cast<int>(lvl) >= static_cast<int>(level_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::log(LogLevel level, const char *fmt, ...) {
|
void ConsoleLogger::log(LogLevel lvl, const char *fmt, ...) {
|
||||||
if (!isEnabled(level))
|
if (!enabled(lvl))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
@ -92,17 +89,17 @@ void ConsoleLogger::log(LogLevel level, const char *fmt, ...) {
|
||||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
output(level, buffer);
|
output(lvl, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::log(LogLevel level, const std::string &msg) {
|
void ConsoleLogger::log(LogLevel lvl, const std::string &msg) {
|
||||||
if (!isEnabled(level))
|
if (!enabled(lvl))
|
||||||
return;
|
return;
|
||||||
output(level, msg.c_str());
|
output(lvl, msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::trace(const char *fmt, ...) {
|
void ConsoleLogger::trace(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Trace))
|
if (!enabled(LogLevel::Trace))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -113,7 +110,7 @@ void ConsoleLogger::trace(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::debug(const char *fmt, ...) {
|
void ConsoleLogger::debug(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Debug))
|
if (!enabled(LogLevel::Debug))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -124,7 +121,7 @@ void ConsoleLogger::debug(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::info(const char *fmt, ...) {
|
void ConsoleLogger::info(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Info))
|
if (!enabled(LogLevel::Info))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -135,7 +132,7 @@ void ConsoleLogger::info(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::registry(const char *fmt, ...) {
|
void ConsoleLogger::registry(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Registry))
|
if (!enabled(LogLevel::Registry))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -146,7 +143,7 @@ void ConsoleLogger::registry(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::warn(const char *fmt, ...) {
|
void ConsoleLogger::warn(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Warn))
|
if (!enabled(LogLevel::Warn))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -157,7 +154,7 @@ void ConsoleLogger::warn(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::error(const char *fmt, ...) {
|
void ConsoleLogger::error(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Error))
|
if (!enabled(LogLevel::Error))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -168,7 +165,7 @@ void ConsoleLogger::error(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::fatal(const char *fmt, ...) {
|
void ConsoleLogger::fatal(const char *fmt, ...) {
|
||||||
if (!isEnabled(LogLevel::Fatal))
|
if (!enabled(LogLevel::Fatal))
|
||||||
return;
|
return;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -178,33 +175,33 @@ void ConsoleLogger::fatal(const char *fmt, ...) {
|
||||||
output(LogLevel::Fatal, buffer);
|
output(LogLevel::Fatal, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::setLevelColor(LogLevel level, const LogColor &color) {
|
void ConsoleLogger::levelColor(LogLevel lvl, const LogColor &c) {
|
||||||
int idx = static_cast<int>(level);
|
int idx = static_cast<int>(lvl);
|
||||||
if (idx >= 0 && idx < 7) {
|
if (idx >= 0 && idx < 7) {
|
||||||
levelColors_[idx] = color;
|
levelColors_[idx] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogColor ConsoleLogger::getLevelColor(LogLevel level) const {
|
LogColor ConsoleLogger::levelColor(LogLevel lvl) const {
|
||||||
int idx = static_cast<int>(level);
|
int idx = static_cast<int>(lvl);
|
||||||
if (idx >= 0 && idx < 7) {
|
if (idx >= 0 && idx < 7) {
|
||||||
return levelColors_[idx];
|
return levelColors_[idx];
|
||||||
}
|
}
|
||||||
return LogColor::White();
|
return LogColor::White();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::setColorEnabled(bool enabled) { colorEnabled_ = enabled; }
|
void ConsoleLogger::colors(bool on) { colors_ = on; }
|
||||||
|
|
||||||
bool ConsoleLogger::isColorEnabled() const { return colorEnabled_; }
|
bool ConsoleLogger::colors() const { return colors_; }
|
||||||
|
|
||||||
std::string ConsoleLogger::getAnsiColor(LogLevel level) {
|
std::string ConsoleLogger::ansiColor(LogLevel lvl) {
|
||||||
const LogColor &c = getLevelColor(level);
|
const LogColor &c = levelColor(lvl);
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf), "\033[38;2;%d;%d;%dm", c.r, c.g, c.b);
|
snprintf(buf, sizeof(buf), "\033[38;2;%d;%d;%dm", c.r, c.g, c.b);
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleLogger::output(LogLevel level, const char *msg) {
|
void ConsoleLogger::output(LogLevel lvl, const char *msg) {
|
||||||
std::lock_guard<std::mutex> lock(impl_->mutex_);
|
std::lock_guard<std::mutex> lock(impl_->mutex_);
|
||||||
|
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
|
|
@ -220,11 +217,11 @@ void ConsoleLogger::output(LogLevel level, const char *msg) {
|
||||||
localtime_r(&time, &tm);
|
localtime_r(&time, &tm);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *levelStr = getLevelString(level);
|
const char *levelStr = levelString(lvl);
|
||||||
const char *reset = "\033[0m";
|
const char *reset = "\033[0m";
|
||||||
|
|
||||||
if (colorEnabled_) {
|
if (colors_) {
|
||||||
std::string color = getAnsiColor(level);
|
std::string color = ansiColor(lvl);
|
||||||
printf("%s[%02d:%02d:%02d.%03d] [%s] %s%s\n", color.c_str(), tm.tm_hour,
|
printf("%s[%02d:%02d:%02d.%03d] [%s] %s%s\n", color.c_str(), tm.tm_hour,
|
||||||
tm.tm_min, tm.tm_sec, (int)ms.count(), levelStr, msg, reset);
|
tm.tm_min, tm.tm_sec, (int)ms.count(), levelStr, msg, reset);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -233,8 +230,8 @@ void ConsoleLogger::output(LogLevel level, const char *msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *ConsoleLogger::getLevelString(LogLevel level) {
|
const char *ConsoleLogger::levelString(LogLevel lvl) {
|
||||||
switch (level) {
|
switch (lvl) {
|
||||||
case LogLevel::Trace:
|
case LogLevel::Trace:
|
||||||
return "TRACE";
|
return "TRACE";
|
||||||
case LogLevel::Debug:
|
case LogLevel::Debug:
|
||||||
|
|
|
||||||
|
|
@ -8,45 +8,44 @@ TimerService::TimerService() {
|
||||||
info_.enabled = true;
|
info_.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceInfo TimerService::getServiceInfo() const { return info_; }
|
ServiceInfo TimerService::info() const { return info_; }
|
||||||
|
|
||||||
bool TimerService::initialize() {
|
bool TimerService::init() {
|
||||||
setState(ServiceState::Running);
|
setState(ServiceState::Running);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerService::shutdown() {
|
void TimerService::shutdown() {
|
||||||
manager_.clear();
|
mgr_.clear();
|
||||||
setState(ServiceState::Stopped);
|
setState(ServiceState::Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerService::update(float deltaTime) {
|
void TimerService::update(f32 dt) {
|
||||||
if (getState() == ServiceState::Running) {
|
if (state() == ServiceState::Running) {
|
||||||
manager_.update(deltaTime);
|
mgr_.update(dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 TimerService::addTimer(float delay, Timer::Callback callback) {
|
u32 TimerService::add(f32 delay, Timer::Fn fn) {
|
||||||
return manager_.addTimer(delay, callback);
|
return mgr_.add(delay, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 TimerService::addRepeatingTimer(float interval,
|
u32 TimerService::addRepeat(f32 interval, Timer::Fn fn) {
|
||||||
Timer::Callback callback) {
|
return mgr_.addRepeat(interval, fn);
|
||||||
return manager_.addRepeatingTimer(interval, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerService::cancelTimer(uint32 timerId) {
|
void TimerService::cancel(u32 timerId) {
|
||||||
manager_.cancelTimer(timerId);
|
mgr_.cancel(timerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerService::pauseTimer(uint32 timerId) { manager_.pauseTimer(timerId); }
|
void TimerService::pauseTimer(u32 timerId) { mgr_.pause(timerId); }
|
||||||
|
|
||||||
void TimerService::resumeTimer(uint32 timerId) {
|
void TimerService::resumeTimer(u32 timerId) {
|
||||||
manager_.resumeTimer(timerId);
|
mgr_.resume(timerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerService::clear() { manager_.clear(); }
|
void TimerService::clear() { mgr_.clear(); }
|
||||||
|
|
||||||
size_t TimerService::getTimerCount() const { return manager_.getTimerCount(); }
|
size_t TimerService::count() const { return mgr_.count(); }
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ Random &Random::get() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置随机数种子
|
* @brief 设置随机数种子
|
||||||
* @param seed 随机数种子值
|
* @param s 随机数种子值
|
||||||
*/
|
*/
|
||||||
void Random::setSeed(uint32 seed) { generator_.seed(seed); }
|
void Random::seed(u32 s) { generator_.seed(s); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 使用当前时间随机化种子
|
* @brief 使用当前时间随机化种子
|
||||||
|
|
@ -36,14 +36,14 @@ void Random::setSeed(uint32 seed) { generator_.seed(seed); }
|
||||||
void Random::randomize() {
|
void Random::randomize() {
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
auto time = now.time_since_epoch().count();
|
auto time = now.time_since_epoch().count();
|
||||||
generator_.seed(static_cast<uint32>(time));
|
generator_.seed(static_cast<u32>(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取[0.0, 1.0]范围内的随机浮点数
|
* @brief 获取[0, 1)范围内的随机浮点数
|
||||||
* @return 随机浮点数,范围[0.0, 1.0]
|
* @return 随机浮点数,范围[0, 1)
|
||||||
*/
|
*/
|
||||||
float Random::getFloat() { return floatDist_(generator_); }
|
f32 Random::randomF32() { return floatDist_(generator_); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取指定范围内的随机浮点数
|
* @brief 获取指定范围内的随机浮点数
|
||||||
|
|
@ -51,7 +51,7 @@ float Random::getFloat() { return floatDist_(generator_); }
|
||||||
* @param max 最大值
|
* @param max 最大值
|
||||||
* @return 随机浮点数,范围[min, max]
|
* @return 随机浮点数,范围[min, max]
|
||||||
*/
|
*/
|
||||||
float Random::getFloat(float min, float max) {
|
f32 Random::randomF32(f32 min, f32 max) {
|
||||||
if (min >= max) {
|
if (min >= max) {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +63,11 @@ float Random::getFloat(float min, float max) {
|
||||||
* @param max 最大值(包含)
|
* @param max 最大值(包含)
|
||||||
* @return 随机整数,范围[0, max]
|
* @return 随机整数,范围[0, max]
|
||||||
*/
|
*/
|
||||||
int Random::getInt(int max) {
|
i32 Random::randomI32(i32 max) {
|
||||||
if (max <= 0) {
|
if (max <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::uniform_int_distribution<int> dist(0, max);
|
std::uniform_int_distribution<i32> dist(0, max);
|
||||||
return dist(generator_);
|
return dist(generator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,11 +77,11 @@ int Random::getInt(int max) {
|
||||||
* @param max 最大值(包含)
|
* @param max 最大值(包含)
|
||||||
* @return 随机整数,范围[min, max]
|
* @return 随机整数,范围[min, max]
|
||||||
*/
|
*/
|
||||||
int Random::getInt(int min, int max) {
|
i32 Random::randomI32(i32 min, i32 max) {
|
||||||
if (min >= max) {
|
if (min >= max) {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
std::uniform_int_distribution<int> dist(min, max);
|
std::uniform_int_distribution<i32> dist(min, max);
|
||||||
return dist(generator_);
|
return dist(generator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,14 +89,14 @@ int Random::getInt(int min, int max) {
|
||||||
* @brief 获取随机布尔值(50%概率)
|
* @brief 获取随机布尔值(50%概率)
|
||||||
* @return 随机布尔值
|
* @return 随机布尔值
|
||||||
*/
|
*/
|
||||||
bool Random::getBool() { return floatDist_(generator_) >= 0.5f; }
|
bool Random::boolean() { return floatDist_(generator_) >= 0.5f; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 以指定概率获取随机布尔值
|
* @brief 以指定概率获取随机布尔值
|
||||||
* @param probability 返回true的概率,范围[0.0, 1.0]
|
* @param probability 返回true的概率,范围[0.0, 1.0]
|
||||||
* @return 随机布尔值
|
* @return 随机布尔值
|
||||||
*/
|
*/
|
||||||
bool Random::getBool(float probability) {
|
bool Random::boolean(f32 probability) {
|
||||||
if (probability <= 0.0f) {
|
if (probability <= 0.0f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -110,8 +110,8 @@ bool Random::getBool(float probability) {
|
||||||
* @brief 获取随机角度值
|
* @brief 获取随机角度值
|
||||||
* @return 随机角度,范围[0, 2π]
|
* @return 随机角度,范围[0, 2π]
|
||||||
*/
|
*/
|
||||||
float Random::getAngle() {
|
f32 Random::angle() {
|
||||||
static const float TWO_PI = 6.28318530718f;
|
static const f32 TWO_PI = 6.28318530718f;
|
||||||
return floatDist_(generator_) * TWO_PI;
|
return floatDist_(generator_) * TWO_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,6 +119,6 @@ float Random::getAngle() {
|
||||||
* @brief 获取有符号随机数
|
* @brief 获取有符号随机数
|
||||||
* @return 随机浮点数,范围[-1.0, 1.0]
|
* @return 随机浮点数,范围[-1.0, 1.0]
|
||||||
*/
|
*/
|
||||||
float Random::getSigned() { return floatDist_(generator_) * 2.0f - 1.0f; }
|
f32 Random::signedF32() { return floatDist_(generator_) * 2.0f - 1.0f; }
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -3,35 +3,24 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
uint32 Timer::nextId_ = 1;
|
u32 Timer::nextId_ = 1;
|
||||||
|
|
||||||
/**
|
Timer::Timer(f32 interval, bool repeat, Fn fn)
|
||||||
* @brief 构造函数,创建定时器
|
|
||||||
* @param interval 定时间隔(秒)
|
|
||||||
* @param repeat 是否重复触发
|
|
||||||
* @param callback 定时器回调函数
|
|
||||||
*/
|
|
||||||
Timer::Timer(float interval, bool repeat, Callback callback)
|
|
||||||
: interval_(interval), elapsed_(0.0f), repeat_(repeat), paused_(false),
|
: interval_(interval), elapsed_(0.0f), repeat_(repeat), paused_(false),
|
||||||
valid_(true), callback_(std::move(callback)) {
|
valid_(true), fn_(std::move(fn)) {
|
||||||
id_ = nextId_++;
|
id_ = nextId_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool Timer::update(f32 dt) {
|
||||||
* @brief 更新定时器状态
|
|
||||||
* @param deltaTime 帧间隔时间(秒)
|
|
||||||
* @return 如果定时器触发则返回true,否则返回false
|
|
||||||
*/
|
|
||||||
bool Timer::update(float deltaTime) {
|
|
||||||
if (!valid_ || paused_) {
|
if (!valid_ || paused_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed_ += deltaTime;
|
elapsed_ += dt;
|
||||||
|
|
||||||
if (elapsed_ >= interval_) {
|
if (elapsed_ >= interval_) {
|
||||||
if (callback_) {
|
if (fn_) {
|
||||||
callback_();
|
fn_();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repeat_) {
|
if (repeat_) {
|
||||||
|
|
@ -46,81 +35,40 @@ bool Timer::update(float deltaTime) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 重置定时器
|
|
||||||
*
|
|
||||||
* 重置已过时间,恢复定时器为有效且非暂停状态
|
|
||||||
*/
|
|
||||||
void Timer::reset() {
|
void Timer::reset() {
|
||||||
elapsed_ = 0.0f;
|
elapsed_ = 0.0f;
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
paused_ = false;
|
paused_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 暂停定时器
|
|
||||||
*/
|
|
||||||
void Timer::pause() { paused_ = true; }
|
void Timer::pause() { paused_ = true; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 恢复定时器
|
|
||||||
*/
|
|
||||||
void Timer::resume() { paused_ = false; }
|
void Timer::resume() { paused_ = false; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 取消定时器
|
|
||||||
*
|
|
||||||
* 将定时器标记为无效状态
|
|
||||||
*/
|
|
||||||
void Timer::cancel() { valid_ = false; }
|
void Timer::cancel() { valid_ = false; }
|
||||||
|
|
||||||
/**
|
f32 Timer::remaining() const {
|
||||||
* @brief 获取剩余时间
|
|
||||||
* @return 剩余时间(秒),如果定时器无效或已暂停则返回0
|
|
||||||
*/
|
|
||||||
float Timer::getRemaining() const {
|
|
||||||
if (!valid_ || paused_) {
|
if (!valid_ || paused_) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
return std::max(0.0f, interval_ - elapsed_);
|
return std::max(0.0f, interval_ - elapsed_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
u32 TimerManager::add(f32 delay, Timer::Fn fn) {
|
||||||
// TimerManager 实现
|
auto timer = std::make_unique<Timer>(delay, false, std::move(fn));
|
||||||
// ============================================================================
|
u32 id = timer->id();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 添加单次定时器
|
|
||||||
* @param delay 延迟时间(秒)
|
|
||||||
* @param callback 定时器回调函数
|
|
||||||
* @return 定时器ID
|
|
||||||
*/
|
|
||||||
uint32 TimerManager::addTimer(float delay, Timer::Callback callback) {
|
|
||||||
auto timer = std::make_unique<Timer>(delay, false, std::move(callback));
|
|
||||||
uint32 id = timer->getId();
|
|
||||||
timers_.emplace(id, std::move(timer));
|
timers_.emplace(id, std::move(timer));
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
u32 TimerManager::addRepeat(f32 interval, Timer::Fn fn) {
|
||||||
* @brief 添加重复定时器
|
auto timer = std::make_unique<Timer>(interval, true, std::move(fn));
|
||||||
* @param interval 触发间隔(秒)
|
u32 id = timer->id();
|
||||||
* @param callback 定时器回调函数
|
|
||||||
* @return 定时器ID
|
|
||||||
*/
|
|
||||||
uint32 TimerManager::addRepeatingTimer(float interval,
|
|
||||||
Timer::Callback callback) {
|
|
||||||
auto timer = std::make_unique<Timer>(interval, true, std::move(callback));
|
|
||||||
uint32 id = timer->getId();
|
|
||||||
timers_.emplace(id, std::move(timer));
|
timers_.emplace(id, std::move(timer));
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void TimerManager::cancel(u32 timerId) {
|
||||||
* @brief 取消指定定时器
|
|
||||||
* @param timerId 定时器ID
|
|
||||||
*/
|
|
||||||
void TimerManager::cancelTimer(uint32 timerId) {
|
|
||||||
auto it = timers_.find(timerId);
|
auto it = timers_.find(timerId);
|
||||||
if (it != timers_.end()) {
|
if (it != timers_.end()) {
|
||||||
it->second->cancel();
|
it->second->cancel();
|
||||||
|
|
@ -128,52 +76,35 @@ void TimerManager::cancelTimer(uint32 timerId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void TimerManager::pause(u32 timerId) {
|
||||||
* @brief 暂停指定定时器
|
|
||||||
* @param timerId 定时器ID
|
|
||||||
*/
|
|
||||||
void TimerManager::pauseTimer(uint32 timerId) {
|
|
||||||
auto it = timers_.find(timerId);
|
auto it = timers_.find(timerId);
|
||||||
if (it != timers_.end()) {
|
if (it != timers_.end()) {
|
||||||
it->second->pause();
|
it->second->pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void TimerManager::resume(u32 timerId) {
|
||||||
* @brief 恢复指定定时器
|
|
||||||
* @param timerId 定时器ID
|
|
||||||
*/
|
|
||||||
void TimerManager::resumeTimer(uint32 timerId) {
|
|
||||||
auto it = timers_.find(timerId);
|
auto it = timers_.find(timerId);
|
||||||
if (it != timers_.end()) {
|
if (it != timers_.end()) {
|
||||||
it->second->resume();
|
it->second->resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void TimerManager::update(f32 dt) {
|
||||||
* @brief 更新所有定时器
|
|
||||||
* @param deltaTime 帧间隔时间(秒)
|
|
||||||
*
|
|
||||||
* 更新所有定时器状态,并移除已失效的定时器
|
|
||||||
*/
|
|
||||||
void TimerManager::update(float deltaTime) {
|
|
||||||
timersToRemove_.clear();
|
timersToRemove_.clear();
|
||||||
|
|
||||||
for (auto &[id, timer] : timers_) {
|
for (auto &[id, timer] : timers_) {
|
||||||
timer->update(deltaTime);
|
timer->update(dt);
|
||||||
if (!timer->isValid()) {
|
if (!timer->valid()) {
|
||||||
timersToRemove_.push_back(id);
|
timersToRemove_.push_back(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32 id : timersToRemove_) {
|
for (u32 id : timersToRemove_) {
|
||||||
timers_.erase(id);
|
timers_.erase(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 清除所有定时器
|
|
||||||
*/
|
|
||||||
void TimerManager::clear() {
|
void TimerManager::clear() {
|
||||||
timers_.clear();
|
timers_.clear();
|
||||||
timersToRemove_.clear();
|
timersToRemove_.clear();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue