feat: initial DX12 foundation framework

This commit is contained in:
SpecialX
2026-03-19 18:27:49 +08:00
commit 60f73b525d
70 changed files with 8993 additions and 0 deletions

View 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
}