157 lines
4.6 KiB
C++
157 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <extra2d/core/export.h>
|
|
#include <extra2d/core/module_meta.h>
|
|
#include <extra2d/core/property.h>
|
|
#include <extra2d/core/types.h>
|
|
|
|
#include <initializer_list>
|
|
|
|
namespace extra2d {
|
|
|
|
/**
|
|
* @brief 模块元数据模板实现
|
|
*/
|
|
template<typename T>
|
|
class ModuleMeta : public ModuleMetaBase {
|
|
public:
|
|
using ModuleType = T;
|
|
|
|
const char* name_ = nullptr;
|
|
int priority_ = 0;
|
|
std::vector<const char*> dependencies_;
|
|
std::function<void(Module*, PropertyBinder&)> bindFunc_;
|
|
|
|
const char* getName() const override { return name_; }
|
|
int getPriority() const override { return priority_; }
|
|
std::vector<const char*> getDependencies() const override { return dependencies_; }
|
|
|
|
T* create() override {
|
|
return new T();
|
|
}
|
|
|
|
void bindProperties(Module* instance, PropertyBinder& binder) override {
|
|
if (bindFunc_) {
|
|
bindFunc_(instance, binder);
|
|
}
|
|
}
|
|
};
|
|
|
|
namespace detail {
|
|
|
|
/**
|
|
* @brief 模块注册辅助类(静态自动注册)
|
|
*/
|
|
template<typename T>
|
|
struct ModuleAutoRegister {
|
|
ModuleMeta<T> meta;
|
|
|
|
ModuleAutoRegister(const char* name, int priority, std::initializer_list<const char*> deps) {
|
|
meta.name_ = name;
|
|
meta.priority_ = priority;
|
|
meta.dependencies_ = std::vector<const char*>(deps);
|
|
ModuleRegistry::instance().registerMeta(&meta);
|
|
}
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace extra2d
|
|
|
|
// ============================================================================
|
|
// 模块定义宏 - 静态自动注册
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief 简化版模块定义(静态自动注册)
|
|
*
|
|
* 用于引擎内部模块,在动态库加载时自动注册
|
|
*/
|
|
#define E2D_MODULE(ModuleClassName, priorityValue, ...) \
|
|
__attribute__((used)) \
|
|
static ::extra2d::detail::ModuleAutoRegister< ::extra2d::ModuleClassName> \
|
|
E2D_CONCAT(_e2d_auto_reg_, ModuleClassName)( \
|
|
#ModuleClassName, priorityValue, { __VA_ARGS__ });
|
|
|
|
/**
|
|
* @brief 外部模块定义(自动生成 force_link 函数)
|
|
*
|
|
* 用于编译为单独 DLL 的自定义模块
|
|
*
|
|
* 使用示例(在模块 cpp 文件末尾):
|
|
* } // namespace extra2d
|
|
* E2D_MODULE_EXPORT(HelloModule, 1000)
|
|
*/
|
|
#define E2D_MODULE_EXPORT(ModuleClassName, priorityValue, ...) \
|
|
E2D_MODULE(ModuleClassName, priorityValue, __VA_ARGS__) \
|
|
extern "C" E2D_API void E2D_CONCAT(e2d_force_link_, ModuleClassName)() {}
|
|
|
|
/**
|
|
* @brief 声明外部模块的 force_link 函数
|
|
*/
|
|
#define E2D_DECLARE_FORCE_LINK(ModuleClassName) \
|
|
extern "C" void E2D_CONCAT(e2d_force_link_, ModuleClassName)()
|
|
|
|
/**
|
|
* @brief 调用 force_link 函数
|
|
*/
|
|
#define E2D_CALL_FORCE_LINK(ModuleClassName) \
|
|
E2D_CONCAT(e2d_force_link_, ModuleClassName)()
|
|
|
|
/**
|
|
* @brief 强制链接外部模块(声明 + 调用)
|
|
*
|
|
* 在 main.cpp 开头调用,触发 DLL 静态初始化
|
|
*/
|
|
#define E2D_FORCE_LINK(ModuleClassName) \
|
|
E2D_DECLARE_FORCE_LINK(ModuleClassName); \
|
|
E2D_CALL_FORCE_LINK(ModuleClassName)
|
|
|
|
/**
|
|
* @brief 带属性的模块定义开始
|
|
*/
|
|
#define E2D_MODULE_BEGIN(ModuleClassName) \
|
|
namespace { \
|
|
static ::extra2d::ModuleMeta< ::extra2d::ModuleClassName>& E2D_CONCAT(_e2d_get_meta_, ModuleClassName)() { \
|
|
static ::extra2d::ModuleMeta< ::extra2d::ModuleClassName> meta; \
|
|
return meta; \
|
|
} \
|
|
struct E2D_CONCAT(_E2D_ModuleCfg_, ModuleClassName) { \
|
|
E2D_CONCAT(_E2D_ModuleCfg_, ModuleClassName)()
|
|
|
|
/**
|
|
* @brief 定义模块优先级
|
|
*/
|
|
#define E2D_PRIORITY(value) \
|
|
{ auto& m = E2D_CONCAT(_e2d_get_meta_, ModuleClassName)(); m.priority_ = value; }
|
|
|
|
/**
|
|
* @brief 定义模块依赖
|
|
*/
|
|
#define E2D_DEPENDENCIES(...) \
|
|
{ \
|
|
auto& m = E2D_CONCAT(_e2d_get_meta_, ModuleClassName)(); \
|
|
m.dependencies_ = { __VA_ARGS__ }; \
|
|
}
|
|
|
|
/**
|
|
* @brief 定义属性
|
|
*/
|
|
#define E2D_PROPERTY(name, type) \
|
|
{ \
|
|
auto& m = E2D_CONCAT(_e2d_get_meta_, ModuleClassName)(); \
|
|
auto oldFunc = m.bindFunc_; \
|
|
m.bindFunc_ = [oldFunc](::extra2d::Module* inst, ::extra2d::PropertyBinder& binder) { \
|
|
if (oldFunc) oldFunc(inst, binder); \
|
|
auto* module = static_cast< ::extra2d::ModuleClassName*>(inst); \
|
|
binder.bind<type>(#name, module->name, #name, ""); \
|
|
}; \
|
|
}
|
|
|
|
/**
|
|
* @brief 结束模块定义
|
|
*/
|
|
#define E2D_MODULE_END() \
|
|
} E2D_CONCAT(_e2d_cfg_inst_, ModuleClassName); \
|
|
}
|