feat: 实现服务定位器模式并重构核心服务架构
重构应用程序架构,引入服务定位器模式解耦模块依赖 新增服务注册表和服务定位器核心组件 实现核心服务接口及实现类(场景、计时器、事件、相机服务) 重构Application类使用服务定位器管理服务 添加服务自动注册宏和类型安全服务获取机制
This commit is contained in:
parent
f8ecf7e03a
commit
453a057c7d
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/types.h>
|
||||
#include <extra2d/core/service_locator.h>
|
||||
#include <extra2d/config/app_config.h>
|
||||
#include <extra2d/config/config_manager.h>
|
||||
#include <extra2d/config/module_config.h>
|
||||
|
|
@ -10,70 +11,209 @@
|
|||
namespace extra2d {
|
||||
|
||||
class IInput;
|
||||
class SceneManager;
|
||||
class TimerManager;
|
||||
class EventQueue;
|
||||
class EventDispatcher;
|
||||
class Camera;
|
||||
class ViewportAdapter;
|
||||
class RenderBackend;
|
||||
|
||||
/**
|
||||
* @brief 应用程序类
|
||||
* 使用服务定位器模式管理模块依赖,支持依赖注入和测试Mock
|
||||
*/
|
||||
class Application {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
* @return 应用程序实例引用
|
||||
*/
|
||||
static Application& get();
|
||||
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 使用默认配置初始化
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool init();
|
||||
|
||||
/**
|
||||
* @brief 使用指定配置初始化
|
||||
* @param config 应用配置
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool init(const AppConfig& config);
|
||||
|
||||
/**
|
||||
* @brief 使用配置文件初始化
|
||||
* @param configPath 配置文件路径
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool init(const std::string& configPath);
|
||||
|
||||
/**
|
||||
* @brief 关闭应用程序
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* @brief 运行主循环
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* @brief 请求退出
|
||||
*/
|
||||
void quit();
|
||||
|
||||
/**
|
||||
* @brief 暂停应用程序
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* @brief 恢复应用程序
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* @brief 检查是否暂停
|
||||
* @return 暂停状态返回 true
|
||||
*/
|
||||
bool isPaused() const { return paused_; }
|
||||
|
||||
/**
|
||||
* @brief 检查是否运行中
|
||||
* @return 运行中返回 true
|
||||
*/
|
||||
bool isRunning() const { return running_; }
|
||||
|
||||
/**
|
||||
* @brief 获取窗口
|
||||
* @return 窗口引用
|
||||
*/
|
||||
IWindow& window() { return *window_; }
|
||||
|
||||
/**
|
||||
* @brief 获取渲染器
|
||||
* @return 渲染器引用
|
||||
*/
|
||||
RenderBackend& renderer();
|
||||
|
||||
/**
|
||||
* @brief 获取输入接口
|
||||
* @return 输入接口引用
|
||||
*/
|
||||
IInput& input();
|
||||
|
||||
SceneManager& scenes();
|
||||
TimerManager& timers();
|
||||
EventQueue& eventQueue();
|
||||
EventDispatcher& eventDispatcher();
|
||||
Camera& camera();
|
||||
ViewportAdapter& viewportAdapter();
|
||||
/**
|
||||
* @brief 获取场景服务
|
||||
* @return 场景服务共享指针
|
||||
*/
|
||||
SharedPtr<class ISceneService> scenes();
|
||||
|
||||
/**
|
||||
* @brief 获取计时器服务
|
||||
* @return 计时器服务共享指针
|
||||
*/
|
||||
SharedPtr<class ITimerService> timers();
|
||||
|
||||
/**
|
||||
* @brief 获取事件服务
|
||||
* @return 事件服务共享指针
|
||||
*/
|
||||
SharedPtr<class IEventService> events();
|
||||
|
||||
/**
|
||||
* @brief 获取相机服务
|
||||
* @return 相机服务共享指针
|
||||
*/
|
||||
SharedPtr<class ICameraService> camera();
|
||||
|
||||
/**
|
||||
* @brief 进入场景
|
||||
* @param scene 场景指针
|
||||
*/
|
||||
void enterScene(Ptr<class Scene> scene);
|
||||
|
||||
/**
|
||||
* @brief 获取帧间隔时间
|
||||
* @return 帧间隔时间(秒)
|
||||
*/
|
||||
float deltaTime() const { return deltaTime_; }
|
||||
|
||||
/**
|
||||
* @brief 获取总运行时间
|
||||
* @return 总运行时间(秒)
|
||||
*/
|
||||
float totalTime() const { return totalTime_; }
|
||||
|
||||
/**
|
||||
* @brief 获取当前帧率
|
||||
* @return 帧率
|
||||
*/
|
||||
int fps() const { return currentFps_; }
|
||||
|
||||
/**
|
||||
* @brief 获取配置管理器
|
||||
* @return 配置管理器引用
|
||||
*/
|
||||
ConfigManager& config();
|
||||
|
||||
/**
|
||||
* @brief 获取应用配置
|
||||
* @return 应用配置常量引用
|
||||
*/
|
||||
const AppConfig& getConfig() const;
|
||||
|
||||
/**
|
||||
* @brief 注册自定义服务
|
||||
* @tparam T 服务接口类型
|
||||
* @param service 服务实例
|
||||
*/
|
||||
template<typename T>
|
||||
void registerService(SharedPtr<T> service) {
|
||||
ServiceLocator::instance().registerService(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取服务
|
||||
* @tparam T 服务接口类型
|
||||
* @return 服务共享指针
|
||||
*/
|
||||
template<typename T>
|
||||
SharedPtr<T> getService() {
|
||||
return ServiceLocator::instance().getService<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
Application() = default;
|
||||
~Application();
|
||||
|
||||
/**
|
||||
* @brief 初始化模块
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool initModules();
|
||||
|
||||
/**
|
||||
* @brief 注册核心服务
|
||||
*/
|
||||
void registerCoreServices();
|
||||
|
||||
/**
|
||||
* @brief 主循环
|
||||
*/
|
||||
void mainLoop();
|
||||
|
||||
/**
|
||||
* @brief 更新
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* @brief 渲染
|
||||
*/
|
||||
void render();
|
||||
|
||||
IWindow* window_ = nullptr;
|
||||
UniquePtr<SceneManager> sceneManager_;
|
||||
UniquePtr<TimerManager> timerManager_;
|
||||
UniquePtr<EventQueue> eventQueue_;
|
||||
UniquePtr<EventDispatcher> eventDispatcher_;
|
||||
UniquePtr<Camera> camera_;
|
||||
UniquePtr<ViewportAdapter> viewportAdapter_;
|
||||
|
||||
bool initialized_ = false;
|
||||
bool running_ = false;
|
||||
|
|
@ -88,4 +228,4 @@ private:
|
|||
int currentFps_ = 0;
|
||||
};
|
||||
|
||||
} // namespace extra2d
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/types.h>
|
||||
#include <string>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 服务优先级枚举
|
||||
* 定义服务的初始化顺序,数值越小越先初始化
|
||||
*/
|
||||
enum class ServicePriority : int {
|
||||
Core = 0,
|
||||
Event = 100,
|
||||
Timer = 200,
|
||||
Scene = 300,
|
||||
Camera = 400,
|
||||
Resource = 500,
|
||||
Audio = 600,
|
||||
User = 1000
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 服务状态枚举
|
||||
*/
|
||||
enum class ServiceState {
|
||||
Uninitialized,
|
||||
Initializing,
|
||||
Running,
|
||||
Paused,
|
||||
Stopping,
|
||||
Stopped
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 服务信息结构体
|
||||
*/
|
||||
struct ServiceInfo {
|
||||
std::string name;
|
||||
ServicePriority priority = ServicePriority::User;
|
||||
ServiceState state = ServiceState::Uninitialized;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 服务接口基类
|
||||
* 所有服务必须实现此接口,支持依赖注入和生命周期管理
|
||||
*/
|
||||
class IService {
|
||||
friend class ServiceLocator;
|
||||
|
||||
public:
|
||||
virtual ~IService() = default;
|
||||
|
||||
/**
|
||||
* @brief 获取服务信息
|
||||
* @return 服务信息结构体
|
||||
*/
|
||||
virtual ServiceInfo getServiceInfo() const = 0;
|
||||
|
||||
/**
|
||||
* @brief 初始化服务
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
virtual bool initialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 关闭服务
|
||||
*/
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
/**
|
||||
* @brief 暂停服务
|
||||
*/
|
||||
virtual void pause() {
|
||||
info_.state = ServiceState::Paused;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 恢复服务
|
||||
*/
|
||||
virtual void resume() {
|
||||
if (info_.state == ServiceState::Paused) {
|
||||
info_.state = ServiceState::Running;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 更新服务
|
||||
* @param deltaTime 帧间隔时间
|
||||
*/
|
||||
virtual void update(float deltaTime) { }
|
||||
|
||||
/**
|
||||
* @brief 检查服务是否已初始化
|
||||
* @return 已初始化返回 true
|
||||
*/
|
||||
virtual bool isInitialized() const {
|
||||
return info_.state == ServiceState::Running ||
|
||||
info_.state == ServiceState::Paused;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取服务状态
|
||||
* @return 当前服务状态
|
||||
*/
|
||||
ServiceState getState() const { return info_.state; }
|
||||
|
||||
/**
|
||||
* @brief 获取服务名称
|
||||
* @return 服务名称
|
||||
*/
|
||||
const std::string& getName() const { return info_.name; }
|
||||
|
||||
protected:
|
||||
ServiceInfo info_;
|
||||
|
||||
/**
|
||||
* @brief 设置服务状态
|
||||
* @param state 新状态
|
||||
*/
|
||||
void setState(ServiceState state) { info_.state = state; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 类型ID生成器
|
||||
* 用于为每种服务类型生成唯一ID
|
||||
*/
|
||||
using ServiceTypeId = size_t;
|
||||
|
||||
namespace detail {
|
||||
inline ServiceTypeId nextServiceTypeId() {
|
||||
static ServiceTypeId id = 0;
|
||||
return ++id;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ServiceTypeId getServiceTypeId() {
|
||||
static ServiceTypeId id = nextServiceTypeId();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/core/types.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <typeindex>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 服务工厂函数类型
|
||||
*/
|
||||
template<typename T>
|
||||
using ServiceFactory = std::function<SharedPtr<T>()>;
|
||||
|
||||
/**
|
||||
* @brief 服务定位器
|
||||
* 实现依赖注入和服务发现模式,解耦模块间依赖
|
||||
*
|
||||
* 特性:
|
||||
* - 类型安全的服务注册和获取
|
||||
* - 支持服务工厂延迟创建
|
||||
* - 支持服务依赖声明
|
||||
* - 线程安全
|
||||
* - 支持 Mock 测试
|
||||
*/
|
||||
class ServiceLocator {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
* @return 服务定位器实例引用
|
||||
*/
|
||||
static ServiceLocator& instance();
|
||||
|
||||
ServiceLocator(const ServiceLocator&) = delete;
|
||||
ServiceLocator& operator=(const ServiceLocator&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 注册服务实例
|
||||
* @tparam T 服务接口类型
|
||||
* @param service 服务实例
|
||||
*/
|
||||
template<typename T>
|
||||
void registerService(SharedPtr<T> service) {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
services_[typeId] = std::static_pointer_cast<IService>(service);
|
||||
orderedServices_.push_back(service);
|
||||
sortServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注册服务工厂
|
||||
* @tparam T 服务接口类型
|
||||
* @param factory 服务工厂函数
|
||||
*/
|
||||
template<typename T>
|
||||
void registerFactory(ServiceFactory<T> factory) {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
factories_[typeId] = [factory]() -> SharedPtr<IService> {
|
||||
return std::static_pointer_cast<IService>(factory());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取服务实例
|
||||
* @tparam T 服务接口类型
|
||||
* @return 服务实例,不存在返回 nullptr
|
||||
*/
|
||||
template<typename T>
|
||||
SharedPtr<T> getService() const {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
|
||||
auto it = services_.find(typeId);
|
||||
if (it != services_.end()) {
|
||||
return std::static_pointer_cast<T>(it->second);
|
||||
}
|
||||
|
||||
auto factoryIt = factories_.find(typeId);
|
||||
if (factoryIt != factories_.end()) {
|
||||
auto service = factoryIt->second();
|
||||
services_[typeId] = service;
|
||||
return std::static_pointer_cast<T>(service);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试获取服务实例(不创建)
|
||||
* @tparam T 服务接口类型
|
||||
* @return 服务实例,不存在返回 nullptr
|
||||
*/
|
||||
template<typename T>
|
||||
SharedPtr<T> tryGetService() const {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
auto it = services_.find(typeId);
|
||||
if (it != services_.end()) {
|
||||
return std::static_pointer_cast<T>(it->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查服务是否已注册
|
||||
* @tparam T 服务接口类型
|
||||
* @return 已注册返回 true
|
||||
*/
|
||||
template<typename T>
|
||||
bool hasService() const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
return services_.find(typeId) != services_.end() ||
|
||||
factories_.find(typeId) != factories_.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注销服务
|
||||
* @tparam T 服务接口类型
|
||||
*/
|
||||
template<typename T>
|
||||
void unregisterService() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto typeId = std::type_index(typeid(T));
|
||||
|
||||
auto it = services_.find(typeId);
|
||||
if (it != services_.end()) {
|
||||
auto service = it->second;
|
||||
services_.erase(it);
|
||||
|
||||
auto orderIt = std::find(orderedServices_.begin(),
|
||||
orderedServices_.end(), service);
|
||||
if (orderIt != orderedServices_.end()) {
|
||||
orderedServices_.erase(orderIt);
|
||||
}
|
||||
}
|
||||
|
||||
factories_.erase(typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化所有已注册的服务
|
||||
* @return 所有服务初始化成功返回 true
|
||||
*/
|
||||
bool initializeAll();
|
||||
|
||||
/**
|
||||
* @brief 关闭所有服务
|
||||
*/
|
||||
void shutdownAll();
|
||||
|
||||
/**
|
||||
* @brief 更新所有服务
|
||||
* @param deltaTime 帧间隔时间
|
||||
*/
|
||||
void updateAll(float deltaTime);
|
||||
|
||||
/**
|
||||
* @brief 暂停所有服务
|
||||
*/
|
||||
void pauseAll();
|
||||
|
||||
/**
|
||||
* @brief 恢复所有服务
|
||||
*/
|
||||
void resumeAll();
|
||||
|
||||
/**
|
||||
* @brief 获取所有服务(按优先级排序)
|
||||
* @return 服务列表
|
||||
*/
|
||||
std::vector<SharedPtr<IService>> getAllServices() const;
|
||||
|
||||
/**
|
||||
* @brief 清空所有服务和工厂
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief 获取已注册服务数量
|
||||
* @return 服务数量
|
||||
*/
|
||||
size_t size() const { return services_.size(); }
|
||||
|
||||
private:
|
||||
ServiceLocator() = default;
|
||||
~ServiceLocator() = default;
|
||||
|
||||
/**
|
||||
* @brief 按优先级排序服务
|
||||
*/
|
||||
void sortServices();
|
||||
|
||||
mutable std::unordered_map<std::type_index, SharedPtr<IService>> services_;
|
||||
std::unordered_map<std::type_index, std::function<SharedPtr<IService>()>> factories_;
|
||||
std::vector<SharedPtr<IService>> orderedServices_;
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 服务注册器
|
||||
* 用于静态注册服务
|
||||
*/
|
||||
template<typename Interface, typename Implementation>
|
||||
class ServiceRegistrar {
|
||||
public:
|
||||
explicit ServiceRegistrar(ServiceFactory<Interface> factory = nullptr) {
|
||||
if (factory) {
|
||||
ServiceLocator::instance().registerFactory<Interface>(factory);
|
||||
} else {
|
||||
ServiceLocator::instance().registerFactory<Interface>(
|
||||
[]() -> SharedPtr<Interface> {
|
||||
return makeShared<Implementation>();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define E2D_REGISTER_SERVICE(Interface, Implementation) \
|
||||
namespace { \
|
||||
static ::extra2d::ServiceRegistrar<Interface, Implementation> \
|
||||
E2D_CONCAT(service_registrar_, __LINE__); \
|
||||
}
|
||||
|
||||
#define E2D_REGISTER_SERVICE_FACTORY(Interface, Factory) \
|
||||
namespace { \
|
||||
static ::extra2d::ServiceRegistrar<Interface, Interface> \
|
||||
E2D_CONCAT(service_factory_registrar_, __LINE__)(Factory); \
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/core/service_locator.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 服务注册信息
|
||||
*/
|
||||
struct ServiceRegistration {
|
||||
std::string name;
|
||||
ServicePriority priority;
|
||||
std::function<SharedPtr<IService>()> factory;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 服务注册表
|
||||
* 管理服务的注册信息,支持延迟创建和配置
|
||||
*/
|
||||
class ServiceRegistry {
|
||||
public:
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
* @return 服务注册表实例引用
|
||||
*/
|
||||
static ServiceRegistry& instance();
|
||||
|
||||
ServiceRegistry(const ServiceRegistry&) = delete;
|
||||
ServiceRegistry& operator=(const ServiceRegistry&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 注册服务
|
||||
* @tparam T 服务接口类型
|
||||
* @tparam Impl 服务实现类型
|
||||
* @param name 服务名称
|
||||
* @param priority 服务优先级
|
||||
*/
|
||||
template<typename T, typename Impl>
|
||||
void registerService(const std::string& name, ServicePriority priority) {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
static_assert(std::is_base_of_v<T, Impl>,
|
||||
"Impl must derive from T");
|
||||
|
||||
ServiceRegistration reg;
|
||||
reg.name = name;
|
||||
reg.priority = priority;
|
||||
reg.factory = []() -> SharedPtr<IService> {
|
||||
return std::static_pointer_cast<IService>(makeShared<Impl>());
|
||||
};
|
||||
registrations_.push_back(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注册服务(带工厂函数)
|
||||
* @tparam T 服务接口类型
|
||||
* @param name 服务名称
|
||||
* @param priority 服务优先级
|
||||
* @param factory 工厂函数
|
||||
*/
|
||||
template<typename T>
|
||||
void registerServiceWithFactory(
|
||||
const std::string& name,
|
||||
ServicePriority priority,
|
||||
std::function<SharedPtr<T>()> factory) {
|
||||
static_assert(std::is_base_of_v<IService, T>,
|
||||
"T must derive from IService");
|
||||
|
||||
ServiceRegistration reg;
|
||||
reg.name = name;
|
||||
reg.priority = priority;
|
||||
reg.factory = [factory]() -> SharedPtr<IService> {
|
||||
return std::static_pointer_cast<IService>(factory());
|
||||
};
|
||||
registrations_.push_back(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启用/禁用服务
|
||||
* @param name 服务名称
|
||||
* @param enabled 是否启用
|
||||
*/
|
||||
void setServiceEnabled(const std::string& name, bool enabled);
|
||||
|
||||
/**
|
||||
* @brief 创建所有已注册的服务
|
||||
* 并注册到 ServiceLocator
|
||||
*/
|
||||
void createAllServices();
|
||||
|
||||
/**
|
||||
* @brief 获取所有注册信息
|
||||
* @return 注册信息列表
|
||||
*/
|
||||
const std::vector<ServiceRegistration>& getRegistrations() const {
|
||||
return registrations_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清空所有注册
|
||||
*/
|
||||
void clear() {
|
||||
registrations_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
ServiceRegistry() = default;
|
||||
~ServiceRegistry() = default;
|
||||
|
||||
std::vector<ServiceRegistration> registrations_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 自动服务注册器
|
||||
* 在全局作用域使用,自动注册服务
|
||||
*/
|
||||
template<typename Interface, typename Implementation>
|
||||
class AutoServiceRegistrar {
|
||||
public:
|
||||
AutoServiceRegistrar(const std::string& name, ServicePriority priority) {
|
||||
ServiceRegistry::instance().registerService<Interface, Implementation>(
|
||||
name, priority);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define E2D_REGISTER_SERVICE_AUTO(Interface, Implementation, Name, Priority) \
|
||||
namespace { \
|
||||
static ::extra2d::AutoServiceRegistrar<Interface, Implementation> \
|
||||
E2D_CONCAT(auto_service_registrar_, __LINE__)(Name, Priority); \
|
||||
}
|
||||
|
|
@ -7,10 +7,17 @@
|
|||
|
||||
namespace extra2d {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 宏定义
|
||||
// ---------------------------------------------------------------------------
|
||||
#define E2D_CONCAT_IMPL(a, b) a##b
|
||||
#define E2D_CONCAT(a, b) E2D_CONCAT_IMPL(a, b)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 智能指针别名
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T> using Ptr = std::shared_ptr<T>;
|
||||
template <typename T> using SharedPtr = std::shared_ptr<T>;
|
||||
|
||||
template <typename T> using UniquePtr = std::unique_ptr<T>;
|
||||
|
||||
|
|
@ -21,6 +28,10 @@ template <typename T, typename... Args> inline Ptr<T> makePtr(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) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/graphics/camera.h>
|
||||
#include <extra2d/graphics/viewport_adapter.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 相机服务接口
|
||||
*/
|
||||
class ICameraService : public IService {
|
||||
public:
|
||||
virtual ~ICameraService() = default;
|
||||
|
||||
virtual void setPosition(const Vec2& position) = 0;
|
||||
virtual void setPosition(float x, float y) = 0;
|
||||
virtual Vec2 getPosition() const = 0;
|
||||
|
||||
virtual void setRotation(float degrees) = 0;
|
||||
virtual float getRotation() const = 0;
|
||||
|
||||
virtual void setZoom(float zoom) = 0;
|
||||
virtual float getZoom() const = 0;
|
||||
|
||||
virtual void setViewport(float left, float right, float bottom, float top) = 0;
|
||||
virtual Rect getViewport() const = 0;
|
||||
|
||||
virtual glm::mat4 getViewMatrix() const = 0;
|
||||
virtual glm::mat4 getProjectionMatrix() const = 0;
|
||||
virtual glm::mat4 getViewProjectionMatrix() const = 0;
|
||||
|
||||
virtual Vec2 screenToWorld(const Vec2& screenPos) const = 0;
|
||||
virtual Vec2 worldToScreen(const Vec2& worldPos) const = 0;
|
||||
|
||||
virtual void move(const Vec2& offset) = 0;
|
||||
virtual void move(float x, float y) = 0;
|
||||
|
||||
virtual void setBounds(const Rect& bounds) = 0;
|
||||
virtual void clearBounds() = 0;
|
||||
|
||||
virtual void lookAt(const Vec2& target) = 0;
|
||||
|
||||
virtual void setViewportConfig(const ViewportConfig& config) = 0;
|
||||
virtual const ViewportConfig& getViewportConfig() const = 0;
|
||||
virtual void updateViewport(int screenWidth, int screenHeight) = 0;
|
||||
virtual const ViewportResult& getViewportResult() const = 0;
|
||||
|
||||
virtual void applyViewportAdapter() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 相机服务实现
|
||||
*/
|
||||
class CameraService : public ICameraService {
|
||||
public:
|
||||
CameraService();
|
||||
explicit CameraService(float left, float right, float bottom, float top);
|
||||
~CameraService() override = default;
|
||||
|
||||
ServiceInfo getServiceInfo() const override;
|
||||
|
||||
bool initialize() override;
|
||||
void shutdown() override;
|
||||
|
||||
void setPosition(const Vec2& position) override;
|
||||
void setPosition(float x, float y) override;
|
||||
Vec2 getPosition() const override;
|
||||
|
||||
void setRotation(float degrees) override;
|
||||
float getRotation() const override;
|
||||
|
||||
void setZoom(float zoom) override;
|
||||
float getZoom() const override;
|
||||
|
||||
void setViewport(float left, float right, float bottom, float top) override;
|
||||
Rect getViewport() const override;
|
||||
|
||||
glm::mat4 getViewMatrix() const override;
|
||||
glm::mat4 getProjectionMatrix() const override;
|
||||
glm::mat4 getViewProjectionMatrix() const override;
|
||||
|
||||
Vec2 screenToWorld(const Vec2& screenPos) const override;
|
||||
Vec2 worldToScreen(const Vec2& worldPos) const override;
|
||||
|
||||
void move(const Vec2& offset) override;
|
||||
void move(float x, float y) override;
|
||||
|
||||
void setBounds(const Rect& bounds) override;
|
||||
void clearBounds() override;
|
||||
|
||||
void lookAt(const Vec2& target) override;
|
||||
|
||||
void setViewportConfig(const ViewportConfig& config) override;
|
||||
const ViewportConfig& getViewportConfig() const override;
|
||||
void updateViewport(int screenWidth, int screenHeight) override;
|
||||
const ViewportResult& getViewportResult() const override;
|
||||
|
||||
void applyViewportAdapter() override;
|
||||
|
||||
Camera& getCamera() { return camera_; }
|
||||
const Camera& getCamera() const { return camera_; }
|
||||
ViewportAdapter& getViewportAdapter() { return viewportAdapter_; }
|
||||
const ViewportAdapter& getViewportAdapter() const { return viewportAdapter_; }
|
||||
|
||||
private:
|
||||
Camera camera_;
|
||||
ViewportAdapter viewportAdapter_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/event/event_dispatcher.h>
|
||||
#include <extra2d/event/event_queue.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 事件服务接口
|
||||
*/
|
||||
class IEventService : public IService {
|
||||
public:
|
||||
virtual ~IEventService() = default;
|
||||
|
||||
virtual void pushEvent(const Event& event) = 0;
|
||||
virtual void pushEvent(Event&& event) = 0;
|
||||
virtual bool pollEvent(Event& event) = 0;
|
||||
|
||||
virtual ListenerId addListener(EventType type, EventDispatcher::EventCallback callback) = 0;
|
||||
virtual void removeListener(ListenerId id) = 0;
|
||||
virtual void removeAllListeners(EventType type) = 0;
|
||||
virtual void removeAllListeners() = 0;
|
||||
|
||||
virtual void dispatch(Event& event) = 0;
|
||||
virtual void processQueue() = 0;
|
||||
|
||||
virtual size_t getListenerCount(EventType type) const = 0;
|
||||
virtual size_t getTotalListenerCount() const = 0;
|
||||
virtual size_t getQueueSize() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 事件服务实现
|
||||
*/
|
||||
class EventService : public IEventService {
|
||||
public:
|
||||
EventService();
|
||||
~EventService() override = default;
|
||||
|
||||
ServiceInfo getServiceInfo() const override;
|
||||
|
||||
bool initialize() override;
|
||||
void shutdown() override;
|
||||
void update(float deltaTime) override;
|
||||
|
||||
void pushEvent(const Event& event) override;
|
||||
void pushEvent(Event&& event) override;
|
||||
bool pollEvent(Event& event) override;
|
||||
|
||||
ListenerId addListener(EventType type, EventDispatcher::EventCallback callback) override;
|
||||
void removeListener(ListenerId id) override;
|
||||
void removeAllListeners(EventType type) override;
|
||||
void removeAllListeners() override;
|
||||
|
||||
void dispatch(Event& event) override;
|
||||
void processQueue() override;
|
||||
|
||||
size_t getListenerCount(EventType type) const override;
|
||||
size_t getTotalListenerCount() const override;
|
||||
size_t getQueueSize() const override;
|
||||
|
||||
EventQueue& getQueue() { return queue_; }
|
||||
const EventQueue& getQueue() const { return queue_; }
|
||||
EventDispatcher& getDispatcher() { return dispatcher_; }
|
||||
const EventDispatcher& getDispatcher() const { return dispatcher_; }
|
||||
|
||||
private:
|
||||
EventQueue queue_;
|
||||
EventDispatcher dispatcher_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/scene/scene_manager.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 场景服务接口
|
||||
* 定义场景管理的抽象接口,便于测试和Mock
|
||||
*/
|
||||
class ISceneService : public IService {
|
||||
public:
|
||||
virtual ~ISceneService() = default;
|
||||
|
||||
virtual void runWithScene(Ptr<Scene> scene) = 0;
|
||||
virtual void replaceScene(Ptr<Scene> scene) = 0;
|
||||
virtual void pushScene(Ptr<Scene> scene) = 0;
|
||||
virtual void popScene() = 0;
|
||||
virtual void popToRootScene() = 0;
|
||||
virtual void popToScene(const std::string& name) = 0;
|
||||
|
||||
virtual Ptr<Scene> getCurrentScene() const = 0;
|
||||
virtual Ptr<Scene> getPreviousScene() const = 0;
|
||||
virtual Ptr<Scene> getRootScene() const = 0;
|
||||
virtual Ptr<Scene> getSceneByName(const std::string& name) const = 0;
|
||||
|
||||
virtual size_t getSceneCount() const = 0;
|
||||
virtual bool isEmpty() const = 0;
|
||||
virtual bool hasScene(const std::string& name) const = 0;
|
||||
|
||||
virtual void render(RenderBackend& renderer) = 0;
|
||||
virtual void collectRenderCommands(std::vector<RenderCommand>& commands) = 0;
|
||||
|
||||
virtual bool isTransitioning() const = 0;
|
||||
virtual void setTransitionCallback(SceneManager::TransitionCallback callback) = 0;
|
||||
|
||||
virtual void end() = 0;
|
||||
virtual void purgeCachedScenes() = 0;
|
||||
virtual void enterScene(Ptr<Scene> scene) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 场景服务实现
|
||||
* 包装 SceneManager,实现 IService 接口
|
||||
*/
|
||||
class SceneService : public ISceneService {
|
||||
public:
|
||||
SceneService();
|
||||
~SceneService() override = default;
|
||||
|
||||
ServiceInfo getServiceInfo() const override;
|
||||
|
||||
bool initialize() override;
|
||||
void shutdown() override;
|
||||
void update(float deltaTime) override;
|
||||
|
||||
void runWithScene(Ptr<Scene> scene) override;
|
||||
void replaceScene(Ptr<Scene> scene) override;
|
||||
void pushScene(Ptr<Scene> scene) override;
|
||||
void popScene() override;
|
||||
void popToRootScene() override;
|
||||
void popToScene(const std::string& name) override;
|
||||
|
||||
Ptr<Scene> getCurrentScene() const override;
|
||||
Ptr<Scene> getPreviousScene() const override;
|
||||
Ptr<Scene> getRootScene() const override;
|
||||
Ptr<Scene> getSceneByName(const std::string& name) const override;
|
||||
|
||||
size_t getSceneCount() const override;
|
||||
bool isEmpty() const override;
|
||||
bool hasScene(const std::string& name) const override;
|
||||
|
||||
void render(RenderBackend& renderer) override;
|
||||
void collectRenderCommands(std::vector<RenderCommand>& commands) override;
|
||||
|
||||
bool isTransitioning() const override;
|
||||
void setTransitionCallback(SceneManager::TransitionCallback callback) override;
|
||||
|
||||
void end() override;
|
||||
void purgeCachedScenes() override;
|
||||
void enterScene(Ptr<Scene> scene) override;
|
||||
|
||||
SceneManager& getManager() { return manager_; }
|
||||
const SceneManager& getManager() const { return manager_; }
|
||||
|
||||
private:
|
||||
SceneManager manager_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/service_interface.h>
|
||||
#include <extra2d/utils/timer.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief 计时器服务接口
|
||||
*/
|
||||
class ITimerService : public IService {
|
||||
public:
|
||||
virtual ~ITimerService() = default;
|
||||
|
||||
virtual uint32 addTimer(float delay, Timer::Callback callback) = 0;
|
||||
virtual uint32 addRepeatingTimer(float interval, Timer::Callback callback) = 0;
|
||||
virtual void cancelTimer(uint32 timerId) = 0;
|
||||
virtual void pauseTimer(uint32 timerId) = 0;
|
||||
virtual void resumeTimer(uint32 timerId) = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual size_t getTimerCount() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计时器服务实现
|
||||
*/
|
||||
class TimerService : public ITimerService {
|
||||
public:
|
||||
TimerService();
|
||||
~TimerService() override = default;
|
||||
|
||||
ServiceInfo getServiceInfo() const override;
|
||||
|
||||
bool initialize() override;
|
||||
void shutdown() override;
|
||||
void update(float deltaTime) override;
|
||||
|
||||
uint32 addTimer(float delay, Timer::Callback callback) override;
|
||||
uint32 addRepeatingTimer(float interval, Timer::Callback callback) override;
|
||||
void cancelTimer(uint32 timerId) override;
|
||||
void pauseTimer(uint32 timerId) override;
|
||||
void resumeTimer(uint32 timerId) override;
|
||||
void clear() override;
|
||||
size_t getTimerCount() const override;
|
||||
|
||||
TimerManager& getManager() { return manager_; }
|
||||
const TimerManager& getManager() const { return manager_; }
|
||||
|
||||
private:
|
||||
TimerManager manager_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +1,15 @@
|
|||
#include <extra2d/app/application.h>
|
||||
#include <extra2d/config/config_module.h>
|
||||
#include <extra2d/config/module_registry.h>
|
||||
#include <extra2d/event/event_dispatcher.h>
|
||||
#include <extra2d/event/event_queue.h>
|
||||
#include <extra2d/graphics/camera.h>
|
||||
#include <extra2d/graphics/render_module.h>
|
||||
#include <extra2d/graphics/viewport_adapter.h>
|
||||
#include <extra2d/graphics/vram_manager.h>
|
||||
#include <extra2d/platform/iinput.h>
|
||||
#include <extra2d/platform/platform_init_module.h>
|
||||
#include <extra2d/platform/window_module.h>
|
||||
#include <extra2d/scene/scene_manager.h>
|
||||
#include <extra2d/utils/timer.h>
|
||||
#include <extra2d/services/scene_service.h>
|
||||
#include <extra2d/services/timer_service.h>
|
||||
#include <extra2d/services/event_service.h>
|
||||
#include <extra2d/services/camera_service.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
|
@ -88,6 +86,37 @@ bool Application::init(const std::string& configPath) {
|
|||
return initModules();
|
||||
}
|
||||
|
||||
void Application::registerCoreServices() {
|
||||
auto& locator = ServiceLocator::instance();
|
||||
|
||||
if (!locator.hasService<IEventService>()) {
|
||||
locator.registerService<ISceneService>(makeShared<SceneService>());
|
||||
}
|
||||
|
||||
if (!locator.hasService<ITimerService>()) {
|
||||
locator.registerService<ITimerService>(makeShared<TimerService>());
|
||||
}
|
||||
|
||||
if (!locator.hasService<IEventService>()) {
|
||||
locator.registerService<IEventService>(makeShared<EventService>());
|
||||
}
|
||||
|
||||
if (!locator.hasService<ICameraService>()) {
|
||||
auto cameraService = makeShared<CameraService>();
|
||||
if (window_) {
|
||||
cameraService->setViewport(0, static_cast<float>(window_->width()),
|
||||
static_cast<float>(window_->height()), 0);
|
||||
ViewportConfig vpConfig;
|
||||
vpConfig.logicWidth = static_cast<float>(window_->width());
|
||||
vpConfig.logicHeight = static_cast<float>(window_->height());
|
||||
vpConfig.mode = ViewportMode::AspectRatio;
|
||||
cameraService->setViewportConfig(vpConfig);
|
||||
cameraService->updateViewport(window_->width(), window_->height());
|
||||
}
|
||||
locator.registerService<ICameraService>(cameraService);
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::initModules() {
|
||||
auto initOrder = ModuleRegistry::instance().getInitializationOrder();
|
||||
|
||||
|
|
@ -144,40 +173,28 @@ bool Application::initModules() {
|
|||
}
|
||||
}
|
||||
|
||||
sceneManager_ = makeUnique<SceneManager>();
|
||||
timerManager_ = makeUnique<TimerManager>();
|
||||
eventQueue_ = makeUnique<EventQueue>();
|
||||
eventDispatcher_ = makeUnique<EventDispatcher>();
|
||||
camera_ = makeUnique<Camera>(0, static_cast<float>(window_->width()),
|
||||
static_cast<float>(window_->height()), 0);
|
||||
registerCoreServices();
|
||||
|
||||
viewportAdapter_ = makeUnique<ViewportAdapter>();
|
||||
ViewportConfig vpConfig;
|
||||
vpConfig.logicWidth = static_cast<float>(window_->width());
|
||||
vpConfig.logicHeight = static_cast<float>(window_->height());
|
||||
vpConfig.mode = ViewportMode::AspectRatio;
|
||||
viewportAdapter_->setConfig(vpConfig);
|
||||
if (!ServiceLocator::instance().initializeAll()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
camera_->setViewportAdapter(viewportAdapter_.get());
|
||||
viewportAdapter_->update(window_->width(), window_->height());
|
||||
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
||||
if (cameraService && window_) {
|
||||
window_->onResize([this, cameraService](int width, int height) {
|
||||
cameraService->updateViewport(width, height);
|
||||
cameraService->applyViewportAdapter();
|
||||
|
||||
window_->onResize([this](int width, int height) {
|
||||
if (viewportAdapter_) {
|
||||
viewportAdapter_->update(width, height);
|
||||
}
|
||||
|
||||
if (camera_) {
|
||||
camera_->applyViewportAdapter();
|
||||
}
|
||||
|
||||
if (sceneManager_) {
|
||||
auto currentScene = sceneManager_->getCurrentScene();
|
||||
if (currentScene) {
|
||||
currentScene->setViewportSize(static_cast<float>(width),
|
||||
static_cast<float>(height));
|
||||
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
|
||||
if (sceneService) {
|
||||
auto currentScene = sceneService->getCurrentScene();
|
||||
if (currentScene) {
|
||||
currentScene->setViewportSize(static_cast<float>(width),
|
||||
static_cast<float>(height));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
running_ = true;
|
||||
|
|
@ -191,17 +208,7 @@ void Application::shutdown() {
|
|||
|
||||
VRAMMgr::get().printStats();
|
||||
|
||||
if (sceneManager_) {
|
||||
sceneManager_->end();
|
||||
}
|
||||
|
||||
sceneManager_.reset();
|
||||
viewportAdapter_.reset();
|
||||
camera_.reset();
|
||||
|
||||
timerManager_.reset();
|
||||
eventQueue_.reset();
|
||||
eventDispatcher_.reset();
|
||||
ServiceLocator::instance().clear();
|
||||
|
||||
window_ = nullptr;
|
||||
|
||||
|
|
@ -239,12 +246,14 @@ void Application::quit() {
|
|||
void Application::pause() {
|
||||
if (!paused_) {
|
||||
paused_ = true;
|
||||
ServiceLocator::instance().pauseAll();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::resume() {
|
||||
if (paused_) {
|
||||
paused_ = false;
|
||||
ServiceLocator::instance().resumeAll();
|
||||
lastFrameTime_ = getTimeSeconds();
|
||||
}
|
||||
}
|
||||
|
|
@ -266,8 +275,9 @@ void Application::mainLoop() {
|
|||
|
||||
window_->poll();
|
||||
|
||||
if (eventDispatcher_ && eventQueue_) {
|
||||
eventDispatcher_->processQueue(*eventQueue_);
|
||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||
if (eventService) {
|
||||
eventService->processQueue();
|
||||
}
|
||||
|
||||
if (!paused_) {
|
||||
|
|
@ -291,13 +301,7 @@ void Application::mainLoop() {
|
|||
}
|
||||
|
||||
void Application::update() {
|
||||
if (timerManager_) {
|
||||
timerManager_->update(deltaTime_);
|
||||
}
|
||||
|
||||
if (sceneManager_) {
|
||||
sceneManager_->update(deltaTime_);
|
||||
}
|
||||
ServiceLocator::instance().updateAll(deltaTime_);
|
||||
}
|
||||
|
||||
void Application::render() {
|
||||
|
|
@ -314,8 +318,9 @@ void Application::render() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (viewportAdapter_) {
|
||||
const auto& vp = viewportAdapter_->getViewport();
|
||||
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
||||
if (cameraService) {
|
||||
const auto& vp = cameraService->getViewportResult().viewport;
|
||||
renderer->setViewport(
|
||||
static_cast<int>(vp.origin.x), static_cast<int>(vp.origin.y),
|
||||
static_cast<int>(vp.size.width), static_cast<int>(vp.size.height));
|
||||
|
|
@ -323,8 +328,9 @@ void Application::render() {
|
|||
renderer->setViewport(0, 0, window_->width(), window_->height());
|
||||
}
|
||||
|
||||
if (sceneManager_) {
|
||||
sceneManager_->render(*renderer);
|
||||
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
|
||||
if (sceneService) {
|
||||
sceneService->render(*renderer);
|
||||
}
|
||||
|
||||
window_->swap();
|
||||
|
|
@ -349,35 +355,28 @@ RenderBackend& Application::renderer() {
|
|||
return *dummy;
|
||||
}
|
||||
|
||||
SceneManager& Application::scenes() {
|
||||
return *sceneManager_;
|
||||
SharedPtr<ISceneService> Application::scenes() {
|
||||
return ServiceLocator::instance().getService<ISceneService>();
|
||||
}
|
||||
|
||||
TimerManager& Application::timers() {
|
||||
return *timerManager_;
|
||||
SharedPtr<ITimerService> Application::timers() {
|
||||
return ServiceLocator::instance().getService<ITimerService>();
|
||||
}
|
||||
|
||||
EventQueue& Application::eventQueue() {
|
||||
return *eventQueue_;
|
||||
SharedPtr<IEventService> Application::events() {
|
||||
return ServiceLocator::instance().getService<IEventService>();
|
||||
}
|
||||
|
||||
EventDispatcher& Application::eventDispatcher() {
|
||||
return *eventDispatcher_;
|
||||
}
|
||||
|
||||
Camera& Application::camera() {
|
||||
return *camera_;
|
||||
}
|
||||
|
||||
ViewportAdapter& Application::viewportAdapter() {
|
||||
return *viewportAdapter_;
|
||||
SharedPtr<ICameraService> Application::camera() {
|
||||
return ServiceLocator::instance().getService<ICameraService>();
|
||||
}
|
||||
|
||||
void Application::enterScene(Ptr<Scene> scene) {
|
||||
if (sceneManager_ && scene) {
|
||||
auto sceneService = ServiceLocator::instance().getService<ISceneService>();
|
||||
if (sceneService && scene) {
|
||||
scene->setViewportSize(static_cast<float>(window_->width()),
|
||||
static_cast<float>(window_->height()));
|
||||
sceneManager_->enterScene(scene);
|
||||
sceneService->enterScene(scene);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -389,4 +388,4 @@ const AppConfig& Application::getConfig() const {
|
|||
return ConfigManager::instance().appConfig();
|
||||
}
|
||||
|
||||
} // namespace extra2d
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
#include <extra2d/core/service_locator.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
ServiceLocator& ServiceLocator::instance() {
|
||||
static ServiceLocator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool ServiceLocator::initializeAll() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto& service : orderedServices_) {
|
||||
if (!service) continue;
|
||||
|
||||
auto info = service->getServiceInfo();
|
||||
if (!info.enabled) continue;
|
||||
|
||||
if (!service->isInitialized()) {
|
||||
service->setState(ServiceState::Initializing);
|
||||
if (!service->initialize()) {
|
||||
service->setState(ServiceState::Stopped);
|
||||
return false;
|
||||
}
|
||||
service->setState(ServiceState::Running);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServiceLocator::shutdownAll() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto it = orderedServices_.rbegin();
|
||||
it != orderedServices_.rend(); ++it) {
|
||||
if (*it && (*it)->isInitialized()) {
|
||||
(*it)->setState(ServiceState::Stopping);
|
||||
(*it)->shutdown();
|
||||
(*it)->setState(ServiceState::Stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceLocator::updateAll(float deltaTime) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto& service : orderedServices_) {
|
||||
if (service && service->isInitialized()) {
|
||||
auto state = service->getState();
|
||||
if (state == ServiceState::Running) {
|
||||
service->update(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceLocator::pauseAll() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto& service : orderedServices_) {
|
||||
if (service && service->isInitialized()) {
|
||||
service->pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceLocator::resumeAll() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto& service : orderedServices_) {
|
||||
if (service && service->isInitialized()) {
|
||||
service->resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SharedPtr<IService>> ServiceLocator::getAllServices() const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return orderedServices_;
|
||||
}
|
||||
|
||||
void ServiceLocator::clear() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (auto it = orderedServices_.rbegin();
|
||||
it != orderedServices_.rend(); ++it) {
|
||||
if (*it && (*it)->isInitialized()) {
|
||||
(*it)->setState(ServiceState::Stopping);
|
||||
(*it)->shutdown();
|
||||
(*it)->setState(ServiceState::Stopped);
|
||||
}
|
||||
}
|
||||
|
||||
services_.clear();
|
||||
factories_.clear();
|
||||
orderedServices_.clear();
|
||||
}
|
||||
|
||||
void ServiceLocator::sortServices() {
|
||||
std::stable_sort(orderedServices_.begin(), orderedServices_.end(),
|
||||
[](const SharedPtr<IService>& a, const SharedPtr<IService>& b) {
|
||||
if (!a || !b) return false;
|
||||
return static_cast<int>(a->getServiceInfo().priority) <
|
||||
static_cast<int>(b->getServiceInfo().priority);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#include <extra2d/core/service_registry.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
ServiceRegistry& ServiceRegistry::instance() {
|
||||
static ServiceRegistry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ServiceRegistry::setServiceEnabled(const std::string& name, bool enabled) {
|
||||
for (auto& reg : registrations_) {
|
||||
if (reg.name == name) {
|
||||
reg.enabled = enabled;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceRegistry::createAllServices() {
|
||||
std::sort(registrations_.begin(), registrations_.end(),
|
||||
[](const ServiceRegistration& a, const ServiceRegistration& b) {
|
||||
return static_cast<int>(a.priority) < static_cast<int>(b.priority);
|
||||
});
|
||||
|
||||
for (const auto& reg : registrations_) {
|
||||
if (!reg.enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto service = reg.factory();
|
||||
if (service) {
|
||||
ServiceLocator::instance().registerService<IService>(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
#include <extra2d/services/camera_service.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
CameraService::CameraService() {
|
||||
info_.name = "CameraService";
|
||||
info_.priority = ServicePriority::Camera;
|
||||
info_.enabled = true;
|
||||
}
|
||||
|
||||
CameraService::CameraService(float left, float right, float bottom, float top)
|
||||
: camera_(left, right, bottom, top) {
|
||||
info_.name = "CameraService";
|
||||
info_.priority = ServicePriority::Camera;
|
||||
info_.enabled = true;
|
||||
}
|
||||
|
||||
ServiceInfo CameraService::getServiceInfo() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
bool CameraService::initialize() {
|
||||
camera_.setViewportAdapter(&viewportAdapter_);
|
||||
setState(ServiceState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CameraService::shutdown() {
|
||||
setState(ServiceState::Stopped);
|
||||
}
|
||||
|
||||
void CameraService::setPosition(const Vec2& position) {
|
||||
camera_.setPos(position);
|
||||
}
|
||||
|
||||
void CameraService::setPosition(float x, float y) {
|
||||
camera_.setPos(x, y);
|
||||
}
|
||||
|
||||
Vec2 CameraService::getPosition() const {
|
||||
return camera_.getPosition();
|
||||
}
|
||||
|
||||
void CameraService::setRotation(float degrees) {
|
||||
camera_.setRotation(degrees);
|
||||
}
|
||||
|
||||
float CameraService::getRotation() const {
|
||||
return camera_.getRotation();
|
||||
}
|
||||
|
||||
void CameraService::setZoom(float zoom) {
|
||||
camera_.setZoom(zoom);
|
||||
}
|
||||
|
||||
float CameraService::getZoom() const {
|
||||
return camera_.getZoom();
|
||||
}
|
||||
|
||||
void CameraService::setViewport(float left, float right, float bottom, float top) {
|
||||
camera_.setViewport(left, right, bottom, top);
|
||||
}
|
||||
|
||||
Rect CameraService::getViewport() const {
|
||||
return camera_.getViewport();
|
||||
}
|
||||
|
||||
glm::mat4 CameraService::getViewMatrix() const {
|
||||
return camera_.getViewMatrix();
|
||||
}
|
||||
|
||||
glm::mat4 CameraService::getProjectionMatrix() const {
|
||||
return camera_.getProjectionMatrix();
|
||||
}
|
||||
|
||||
glm::mat4 CameraService::getViewProjectionMatrix() const {
|
||||
return camera_.getViewProjectionMatrix();
|
||||
}
|
||||
|
||||
Vec2 CameraService::screenToWorld(const Vec2& screenPos) const {
|
||||
return camera_.screenToWorld(screenPos);
|
||||
}
|
||||
|
||||
Vec2 CameraService::worldToScreen(const Vec2& worldPos) const {
|
||||
return camera_.worldToScreen(worldPos);
|
||||
}
|
||||
|
||||
void CameraService::move(const Vec2& offset) {
|
||||
camera_.move(offset);
|
||||
}
|
||||
|
||||
void CameraService::move(float x, float y) {
|
||||
camera_.move(x, y);
|
||||
}
|
||||
|
||||
void CameraService::setBounds(const Rect& bounds) {
|
||||
camera_.setBounds(bounds);
|
||||
}
|
||||
|
||||
void CameraService::clearBounds() {
|
||||
camera_.clearBounds();
|
||||
}
|
||||
|
||||
void CameraService::lookAt(const Vec2& target) {
|
||||
camera_.lookAt(target);
|
||||
}
|
||||
|
||||
void CameraService::setViewportConfig(const ViewportConfig& config) {
|
||||
viewportAdapter_.setConfig(config);
|
||||
}
|
||||
|
||||
const ViewportConfig& CameraService::getViewportConfig() const {
|
||||
return viewportAdapter_.getConfig();
|
||||
}
|
||||
|
||||
void CameraService::updateViewport(int screenWidth, int screenHeight) {
|
||||
viewportAdapter_.update(screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
const ViewportResult& CameraService::getViewportResult() const {
|
||||
return viewportAdapter_.getResult();
|
||||
}
|
||||
|
||||
void CameraService::applyViewportAdapter() {
|
||||
camera_.applyViewportAdapter();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
#include <extra2d/services/event_service.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
EventService::EventService() {
|
||||
info_.name = "EventService";
|
||||
info_.priority = ServicePriority::Event;
|
||||
info_.enabled = true;
|
||||
}
|
||||
|
||||
ServiceInfo EventService::getServiceInfo() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
bool EventService::initialize() {
|
||||
setState(ServiceState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventService::shutdown() {
|
||||
queue_.clear();
|
||||
dispatcher_.removeAllListeners();
|
||||
setState(ServiceState::Stopped);
|
||||
}
|
||||
|
||||
void EventService::update(float deltaTime) {
|
||||
if (getState() == ServiceState::Running) {
|
||||
processQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void EventService::pushEvent(const Event& event) {
|
||||
queue_.push(event);
|
||||
}
|
||||
|
||||
void EventService::pushEvent(Event&& event) {
|
||||
queue_.push(std::move(event));
|
||||
}
|
||||
|
||||
bool EventService::pollEvent(Event& event) {
|
||||
return queue_.poll(event);
|
||||
}
|
||||
|
||||
ListenerId EventService::addListener(EventType type, EventDispatcher::EventCallback callback) {
|
||||
return dispatcher_.addListener(type, callback);
|
||||
}
|
||||
|
||||
void EventService::removeListener(ListenerId id) {
|
||||
dispatcher_.removeListener(id);
|
||||
}
|
||||
|
||||
void EventService::removeAllListeners(EventType type) {
|
||||
dispatcher_.removeAllListeners(type);
|
||||
}
|
||||
|
||||
void EventService::removeAllListeners() {
|
||||
dispatcher_.removeAllListeners();
|
||||
}
|
||||
|
||||
void EventService::dispatch(Event& event) {
|
||||
dispatcher_.dispatch(event);
|
||||
}
|
||||
|
||||
void EventService::processQueue() {
|
||||
dispatcher_.processQueue(queue_);
|
||||
}
|
||||
|
||||
size_t EventService::getListenerCount(EventType type) const {
|
||||
return dispatcher_.getListenerCount(type);
|
||||
}
|
||||
|
||||
size_t EventService::getTotalListenerCount() const {
|
||||
return dispatcher_.getTotalListenerCount();
|
||||
}
|
||||
|
||||
size_t EventService::getQueueSize() const {
|
||||
return queue_.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#include <extra2d/services/scene_service.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
SceneService::SceneService() {
|
||||
info_.name = "SceneService";
|
||||
info_.priority = ServicePriority::Scene;
|
||||
info_.enabled = true;
|
||||
}
|
||||
|
||||
ServiceInfo SceneService::getServiceInfo() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
bool SceneService::initialize() {
|
||||
setState(ServiceState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SceneService::shutdown() {
|
||||
manager_.end();
|
||||
setState(ServiceState::Stopped);
|
||||
}
|
||||
|
||||
void SceneService::update(float deltaTime) {
|
||||
if (getState() == ServiceState::Running) {
|
||||
manager_.update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneService::runWithScene(Ptr<Scene> scene) {
|
||||
manager_.runWithScene(scene);
|
||||
}
|
||||
|
||||
void SceneService::replaceScene(Ptr<Scene> scene) {
|
||||
manager_.replaceScene(scene);
|
||||
}
|
||||
|
||||
void SceneService::pushScene(Ptr<Scene> scene) {
|
||||
manager_.pushScene(scene);
|
||||
}
|
||||
|
||||
void SceneService::popScene() {
|
||||
manager_.popScene();
|
||||
}
|
||||
|
||||
void SceneService::popToRootScene() {
|
||||
manager_.popToRootScene();
|
||||
}
|
||||
|
||||
void SceneService::popToScene(const std::string& name) {
|
||||
manager_.popToScene(name);
|
||||
}
|
||||
|
||||
Ptr<Scene> SceneService::getCurrentScene() const {
|
||||
return manager_.getCurrentScene();
|
||||
}
|
||||
|
||||
Ptr<Scene> SceneService::getPreviousScene() const {
|
||||
return manager_.getPreviousScene();
|
||||
}
|
||||
|
||||
Ptr<Scene> SceneService::getRootScene() const {
|
||||
return manager_.getRootScene();
|
||||
}
|
||||
|
||||
Ptr<Scene> SceneService::getSceneByName(const std::string& name) const {
|
||||
return manager_.getSceneByName(name);
|
||||
}
|
||||
|
||||
size_t SceneService::getSceneCount() const {
|
||||
return manager_.getSceneCount();
|
||||
}
|
||||
|
||||
bool SceneService::isEmpty() const {
|
||||
return manager_.isEmpty();
|
||||
}
|
||||
|
||||
bool SceneService::hasScene(const std::string& name) const {
|
||||
return manager_.hasScene(name);
|
||||
}
|
||||
|
||||
void SceneService::render(RenderBackend& renderer) {
|
||||
manager_.render(renderer);
|
||||
}
|
||||
|
||||
void SceneService::collectRenderCommands(std::vector<RenderCommand>& commands) {
|
||||
manager_.collectRenderCommands(commands);
|
||||
}
|
||||
|
||||
bool SceneService::isTransitioning() const {
|
||||
return manager_.isTransitioning();
|
||||
}
|
||||
|
||||
void SceneService::setTransitionCallback(SceneManager::TransitionCallback callback) {
|
||||
manager_.setTransitionCallback(callback);
|
||||
}
|
||||
|
||||
void SceneService::end() {
|
||||
manager_.end();
|
||||
}
|
||||
|
||||
void SceneService::purgeCachedScenes() {
|
||||
manager_.purgeCachedScenes();
|
||||
}
|
||||
|
||||
void SceneService::enterScene(Ptr<Scene> scene) {
|
||||
manager_.enterScene(scene);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#include <extra2d/services/timer_service.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
TimerService::TimerService() {
|
||||
info_.name = "TimerService";
|
||||
info_.priority = ServicePriority::Timer;
|
||||
info_.enabled = true;
|
||||
}
|
||||
|
||||
ServiceInfo TimerService::getServiceInfo() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
bool TimerService::initialize() {
|
||||
setState(ServiceState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimerService::shutdown() {
|
||||
manager_.clear();
|
||||
setState(ServiceState::Stopped);
|
||||
}
|
||||
|
||||
void TimerService::update(float deltaTime) {
|
||||
if (getState() == ServiceState::Running) {
|
||||
manager_.update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 TimerService::addTimer(float delay, Timer::Callback callback) {
|
||||
return manager_.addTimer(delay, callback);
|
||||
}
|
||||
|
||||
uint32 TimerService::addRepeatingTimer(float interval, Timer::Callback callback) {
|
||||
return manager_.addRepeatingTimer(interval, callback);
|
||||
}
|
||||
|
||||
void TimerService::cancelTimer(uint32 timerId) {
|
||||
manager_.cancelTimer(timerId);
|
||||
}
|
||||
|
||||
void TimerService::pauseTimer(uint32 timerId) {
|
||||
manager_.pauseTimer(timerId);
|
||||
}
|
||||
|
||||
void TimerService::resumeTimer(uint32 timerId) {
|
||||
manager_.resumeTimer(timerId);
|
||||
}
|
||||
|
||||
void TimerService::clear() {
|
||||
manager_.clear();
|
||||
}
|
||||
|
||||
size_t TimerService::getTimerCount() const {
|
||||
return manager_.getTimerCount();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue