feat: initial DX12 foundation framework
This commit is contained in:
191
Engine/EngineAPI/GameEntity.h
Normal file
191
Engine/EngineAPI/GameEntity.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @file GameEntity.h
|
||||
* @brief 实体句柄、脚本基类与脚本注册机制定义。
|
||||
* @details
|
||||
* 该文件是引擎 ECS 对外脚本接口的核心入口:
|
||||
* - game_entity::entity 提供实体句柄及常用变换访问;
|
||||
* - script::entity_script 定义脚本生命周期与变换写接口;
|
||||
* - script::detail 提供脚本工厂注册、按名称哈希检索与宏封装。
|
||||
*/
|
||||
#pragma once
|
||||
#include "..\Components\ComponentsCommon.h"
|
||||
#include "TransformComponent.h"
|
||||
#include "ScriptComponent.h"
|
||||
|
||||
namespace XEngine{
|
||||
namespace game_entity {
|
||||
|
||||
/**
|
||||
* @brief 实体强类型标识符。
|
||||
*/
|
||||
DEFINE_TYPED_ID(entity_id);
|
||||
|
||||
/**
|
||||
* @brief 运行时实体句柄封装。
|
||||
*/
|
||||
class entity {
|
||||
public:
|
||||
/**
|
||||
* @brief 由实体 ID 构造句柄。
|
||||
*/
|
||||
constexpr explicit entity(entity_id id) : _id{ id } {}
|
||||
/**
|
||||
* @brief 构造无效实体句柄。
|
||||
*/
|
||||
constexpr entity() : _id{ id::invalid_id } {}
|
||||
/**
|
||||
* @brief 获取实体 ID。
|
||||
*/
|
||||
[[nodiscard]] constexpr entity_id get_id() const { return _id; }
|
||||
/**
|
||||
* @brief 判断实体句柄是否有效。
|
||||
*/
|
||||
[[nodiscard]] constexpr bool is_valid() const { return id::is_valid(_id); }
|
||||
|
||||
/**
|
||||
* @brief 获取实体变换组件句柄。
|
||||
*/
|
||||
[[nodiscard]] transform::component transform() const;
|
||||
/**
|
||||
* @brief 获取实体脚本组件句柄。
|
||||
*/
|
||||
[[nodiscard]] script::component script() const;
|
||||
|
||||
[[nodiscard]] math::v4 rotation() const { return transform().rotation(); }
|
||||
[[nodiscard]] math::v3 orientation() const { return transform().orientation(); }
|
||||
[[nodiscard]] math::v3 position() const { return transform().position(); }
|
||||
[[nodiscard]] math::v3 scale() const { return transform().scale(); }
|
||||
private:
|
||||
entity_id _id;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace script {
|
||||
/**
|
||||
* @brief 实体脚本基类。
|
||||
* @details
|
||||
* 派生类可覆盖 begin_play/update,并通过受保护接口修改实体变换。
|
||||
*/
|
||||
class entity_script : public game_entity::entity {
|
||||
public:
|
||||
/**
|
||||
* @brief 析构脚本实例。
|
||||
*/
|
||||
virtual ~entity_script() = default;
|
||||
/**
|
||||
* @brief 脚本启动回调。
|
||||
*/
|
||||
virtual void begin_play() {}
|
||||
/**
|
||||
* @brief 脚本逐帧更新回调。
|
||||
* @param dt 帧时间步长。
|
||||
*/
|
||||
virtual void update(float) {}
|
||||
|
||||
protected:
|
||||
constexpr explicit entity_script(game_entity::entity entity)
|
||||
: game_entity::entity{ entity.get_id() }{}
|
||||
|
||||
void set_rotation(math::v4 rotation_quaternion) const {set_rotation(this, rotation_quaternion);}
|
||||
void set_orientation(math::v3 orientation_vector) const {set_orientation(this, orientation_vector);}
|
||||
void set_position(math::v3 position) const {set_position(this, position);}
|
||||
void set_scale(math::v3 scale) const { set_scale(this, scale); }
|
||||
|
||||
static void set_rotation(const game_entity::entity *const entity, math::v4 rotation_quaternion);
|
||||
static void set_orientation(const game_entity::entity *const entity, math::v3 orientation_vector);
|
||||
static void set_position(const game_entity::entity *const entity, math::v3 position);
|
||||
static void set_scale(const game_entity::entity *const entity, math::v3 scale);
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* @brief 脚本实例智能指针类型。
|
||||
*/
|
||||
using script_ptr = std::unique_ptr<entity_script>;
|
||||
#ifdef USESTDFUNC
|
||||
/**
|
||||
* @brief 基于 std::function 的脚本工厂签名。
|
||||
*/
|
||||
using script_creator = std::function<script_ptr(game_entity::entity entity)>;
|
||||
#else
|
||||
/**
|
||||
* @brief 基于函数指针的脚本工厂签名。
|
||||
*/
|
||||
using script_creator = script_ptr(*)(game_entity::entity entity);
|
||||
#endif // USESTDFUNC
|
||||
/**
|
||||
* @brief 脚本名哈希器类型。
|
||||
*/
|
||||
using string_hash = std::hash<std::string>;
|
||||
|
||||
/**
|
||||
* @brief 注册脚本工厂到脚本注册表。
|
||||
* @param tag 脚本哈希标签。
|
||||
* @param creator 脚本工厂函数。
|
||||
* @return 注册结果码。
|
||||
*/
|
||||
u8 register_script(size_t tag, script_creator creator);
|
||||
#ifdef USE_WITH_EDITOR
|
||||
extern "C" __declspec(dllexport)
|
||||
#endif
|
||||
/**
|
||||
* @brief 按哈希标签查询脚本工厂。
|
||||
* @param tag 脚本名哈希。
|
||||
* @return 对应脚本工厂函数。
|
||||
*/
|
||||
script_creator get_script_creator(size_t tag);
|
||||
|
||||
/**
|
||||
* @brief 默认脚本工厂模板函数。
|
||||
* @tparam script_class 脚本类型。
|
||||
* @param entity 绑定实体。
|
||||
* @return 新创建脚本实例。
|
||||
*/
|
||||
template<class script_class>
|
||||
script_ptr create_script(game_entity::entity entity)
|
||||
{
|
||||
assert(entity.is_valid());
|
||||
return std::make_unique<script_class>(entity);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_WITH_EDITOR
|
||||
/**
|
||||
* @brief 向编辑器导出脚本名称。
|
||||
* @param name 脚本类名。
|
||||
* @return 写入结果码。
|
||||
*/
|
||||
u8 add_script_name(const char* name);
|
||||
|
||||
#define REGISTER_SCRIPT(TYPE) \
|
||||
namespace { \
|
||||
u8 _reg_##TYPE{ \
|
||||
XEngine::script::detail::register_script( \
|
||||
XEngine::script::detail::string_hash()(#TYPE), \
|
||||
&XEngine::script::detail::create_script<TYPE>) }; \
|
||||
const u8 _name_##TYPE \
|
||||
{ XEngine::script::detail::add_script_name(#TYPE) }; \
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
#define REGISTER_SCRIPT(TYPE) \
|
||||
class TYPE; \
|
||||
namespace { \
|
||||
u8 _reg_##TYPE{ \
|
||||
XEngine::script::detail::register_script( \
|
||||
XEngine::script::detail::string_hash()(#TYPE), \
|
||||
&XEngine::script::detail::create_script<TYPE>) }; \
|
||||
}
|
||||
|
||||
#endif // USE_WITH_EDITOR
|
||||
|
||||
|
||||
}//namespace detail
|
||||
}//namespace script
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user