rizhi
This commit is contained in:
parent
2e8213c1a1
commit
702b15225c
@ -0,0 +1,6 @@
|
||||
namespace api {
|
||||
constexpr const char* CFileResourcePath = "/work/assets/file_resource.meta";
|
||||
constexpr const char* CFileFlagName = "/work/assets/file_flag.meta";
|
||||
constexpr const char* CFileMapName = "/work/assets/file_map.meta";
|
||||
constexpr const char* CFileMountName = "/work/assets/file_mount.meta";
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
static_component("app","engine")
|
||||
add_headerfiles("include/**.h", "include/**.inl","impl/*.inl")
|
||||
add_headerfiles("include/**.h", "include/**.inl")
|
||||
add_files("src/**.cpp")
|
||||
add_deps("core", "asset", "zlib", "render")
|
||||
@ -3,6 +3,7 @@
|
||||
#include "os/file_manager.h"
|
||||
#include "os/file_handle.h"
|
||||
#include "archive/json.h"
|
||||
#include "data/global.h"
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(ResourceSystem)
|
||||
using GenericPtr = ResourceSystem::GenericPtr;
|
||||
@ -15,9 +16,9 @@ namespace api {
|
||||
array<GenericPtr, ResourceCount> mResourceTable;
|
||||
table<Guid, FileBlock*> mResourceFile;
|
||||
table<Name, IFileLoader*> mFileLoader;
|
||||
table<Name, std::pair<std::string, uint32_t>> mFileFlags;
|
||||
table<Name, ResourceFileBlock> mFileBlock;
|
||||
vector<ResourceFileBlock*> mDirtyBlock;
|
||||
table<Name, uint32_t> mFileFlags;
|
||||
table<Name, ResourceFileBlock> mFileBlock;
|
||||
vector<ResourceFileBlock*> mDirtyBlock;
|
||||
public:
|
||||
ResourceSystemImpl(ResourceSystem* owner);
|
||||
void Initialize();
|
||||
@ -159,11 +160,28 @@ namespace api {
|
||||
}
|
||||
void ResourceSystemImpl::LoadFileFlags()
|
||||
{
|
||||
|
||||
FileHandle handle(CFileFlagName);
|
||||
handle.Open(FILE_OP::READ);
|
||||
if (handle) {
|
||||
pmr::string text = handle.ReadAll<pmr::string>();
|
||||
auto res = JsonDeserialize<table<Name, uint32_t>>(text);
|
||||
if (res) {
|
||||
mFileFlags = *res;
|
||||
}
|
||||
}
|
||||
SetFileFlag(".hello", 1);
|
||||
SaveFileFlags();
|
||||
}
|
||||
void ResourceSystemImpl::SaveFileFlags()
|
||||
{
|
||||
FileHandle handle(CFileFlagName);
|
||||
handle.Open(FILE_OP::WRITE, mFileFlag & FileFlag::File_Binary);
|
||||
if (mFileFlag & FileFlag::File_Binary) {
|
||||
|
||||
}
|
||||
else {
|
||||
handle.Write(JsonSerialize(mFileFlags));
|
||||
}
|
||||
}
|
||||
void ResourceSystemImpl::LoadResourceFile()
|
||||
{
|
||||
@ -179,16 +197,16 @@ namespace api {
|
||||
if (it == mFileFlags.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->second.second;
|
||||
return it->second;
|
||||
}
|
||||
inline void ResourceSystemImpl::SetFileFlag(Name name, uint32_t flag)
|
||||
{
|
||||
auto it = mFileFlags.find(name);
|
||||
if (it == mFileFlags.end()) {
|
||||
mFileFlags.emplace(name, std::make_pair(std::string(name.ToStringView()), flag));
|
||||
mFileFlags.emplace(name, flag);
|
||||
}
|
||||
else {
|
||||
it->second.second = flag;
|
||||
it->second = flag;
|
||||
}
|
||||
}
|
||||
inline ResourceSystem::ResourceFileBlock& ResourceSystemImpl::GetFileBlock(PackagePath path) {
|
||||
|
||||
@ -15,7 +15,7 @@ namespace api {
|
||||
{
|
||||
if (h)
|
||||
{
|
||||
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), type_name<Asset>().View(), h->Meta()});
|
||||
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), meta_name<Asset>().View(), h->Meta()});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,8 @@
|
||||
#include <string>
|
||||
namespace api
|
||||
{
|
||||
using refl::type_info;
|
||||
using refl::type_name;
|
||||
using refl::meta_info;
|
||||
using refl::meta_name;
|
||||
using pmr::Name;
|
||||
using std::string_view;
|
||||
using std::span;
|
||||
|
||||
@ -4,7 +4,7 @@ namespace api
|
||||
template<typename T>
|
||||
inline const SerializedMeta* MetaBundle::FetchMeta() const
|
||||
{
|
||||
string_view name = type_name<typename T::BaseResource>().View();
|
||||
string_view name = meta_name<typename T::BaseResource>().View();
|
||||
for (auto& elem : metadatas)
|
||||
{
|
||||
if (elem.t_hash == name)
|
||||
@ -15,7 +15,7 @@ namespace api
|
||||
template<typename T>
|
||||
inline const SerializedMeta* MetaBundle::FetchMeta(string_view asset_name) const
|
||||
{
|
||||
string_view name = type_name<typename T::BaseResource>().View();
|
||||
string_view name = meta_name<typename T::BaseResource>().View();
|
||||
for (auto& elem : metadatas)
|
||||
{
|
||||
if (elem.t_hash == name && asset_name == elem.name)
|
||||
@ -28,7 +28,7 @@ namespace api
|
||||
{
|
||||
if (h)
|
||||
{
|
||||
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), type_name<T>().View() });
|
||||
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), meta_name<T>().View() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ namespace api{
|
||||
using Base::operator=;
|
||||
template<typename T>
|
||||
GenericResourceHandle(RscHandle<T> handle) : Base(RscHandle<typename T::BaseResource>{handle}) {}
|
||||
GenericResourceHandle(string_view type_name, Guid guid);
|
||||
GenericResourceHandle(string_view meta_name, Guid guid);
|
||||
template<typename T> RscHandle<T> AsHandle() const {
|
||||
return std::get<ResourceID<T>>(*this);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "asset/res/resource_handle.h"
|
||||
namespace api
|
||||
{
|
||||
GenericResourceHandle::GenericResourceHandle(string_view type_name, Guid guid)
|
||||
GenericResourceHandle::GenericResourceHandle(string_view meta_name, Guid guid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,6 @@ static_component("asset","engine")
|
||||
add_rules("c++.codegen",{
|
||||
files = {"include/asset/res/*.h"}
|
||||
})
|
||||
add_headerfiles("include/**.h","include/**.inl", "impl/*.inl")
|
||||
add_headerfiles("include/**.h","include/**.inl")
|
||||
add_files("src/**.cpp")
|
||||
add_deps("core", "zlib")
|
||||
@ -30,12 +30,46 @@ namespace gen {
|
||||
template<typename T>
|
||||
struct JsonSerde<T, std::enable_if_t<refl::is_container_v<T>>> {
|
||||
inline static bool Read(yyjson_val* val, const void* ptr) {
|
||||
using value_type_t = typename T::value_type;
|
||||
T& docker = *(T*)ptr;
|
||||
size_t length = yyjson_arr_size(val);
|
||||
char data[sizeof(value_type_t)];
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
yyjson_val* obj_i = yyjson_arr_get(val, i);
|
||||
if constexpr (refl::is_map_v<T>) {
|
||||
using key_type = refl::detail::is_pair<value_type_t>::key_type;
|
||||
using value_type = refl::detail::is_pair<value_type_t>::value_type;
|
||||
key_type& key = *(key_type*)data;
|
||||
value_type& value = *(value_type*)(data + sizeof(key_type));
|
||||
JsonRead(yyjson_obj_get(obj_i, "#k"), key);
|
||||
JsonRead(yyjson_obj_get(obj_i, "#v"), value);
|
||||
docker[key] = value;
|
||||
}
|
||||
else {
|
||||
value_type_t& obj = (value_type_t*)data;
|
||||
JsonRead(obj_i, obj);
|
||||
docker.push_back(obj);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) {
|
||||
T& v = *(T*)ptr;
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(doc);
|
||||
return obj;
|
||||
T& docker = *(T*)ptr;
|
||||
if constexpr (refl::is_map_v<T>) {
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(doc);
|
||||
for (auto& it : docker) {
|
||||
yyjson_mut_obj_add_val(doc, obj, "#k", JsonWrite(doc, it.first));
|
||||
yyjson_mut_obj_add_val(doc, obj, "#v", JsonWrite(doc, it.second));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
else {
|
||||
yyjson_mut_val* arr = yyjson_mut_arr(doc);
|
||||
for (auto& it : docker) {
|
||||
yyjson_mut_arr_add_val(doc, JsonWrite(doc, it));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
namespace api {
|
||||
using refl::Any;
|
||||
using refl::UClass;
|
||||
using refl::type_info;
|
||||
using refl::meta_info;
|
||||
struct JsonVTable {
|
||||
using Read = bool(*)(yyjson_val*, const void*);
|
||||
using Write = yyjson_mut_val*(*)(yyjson_mut_doc*, const void*);
|
||||
|
||||
@ -43,7 +43,7 @@ namespace api {
|
||||
template<typename T>
|
||||
inline void JsonArchive::Register()
|
||||
{
|
||||
auto uclass = type_info<T>();
|
||||
auto uclass = meta_info<T>();
|
||||
auto [bfind, it] = uclass->vtable.FindLast(VJsonSerdeRead());
|
||||
if (!bfind && it) {
|
||||
it = it->Insert(VJsonSerdeRead(), (void*) &gen::JsonSerde<T>::Read);
|
||||
@ -70,6 +70,21 @@ namespace api {
|
||||
if (it) {
|
||||
return it(res, any.ptr);
|
||||
}
|
||||
if (any.IsContainer()) {
|
||||
bool isMap = any.IsMap();
|
||||
refl::Container docker = any;
|
||||
auto fieldList = docker.GetFields();
|
||||
for (auto obj : docker) {
|
||||
if (isMap) {
|
||||
Any first = obj.Member(fieldList[0]);
|
||||
Any second = obj.Member(fieldList[1]);
|
||||
//result[Serialize(first)] = Serialize(second);
|
||||
}
|
||||
else {
|
||||
//result.push_back(Serialize(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ static_component("core","engine")
|
||||
files = {"include/module/module.h"}
|
||||
})
|
||||
add_includedirs("3rdparty", {public = true})
|
||||
add_headerfiles("include/**.h","include/**.inl", "impl/*.inl","3rdparty/**.h")
|
||||
add_headerfiles("include/**.h","include/**.inl","3rdparty/**.h")
|
||||
add_files("src/**.cpp")
|
||||
add_deps("zlib")
|
||||
add_packages("spdlog", {public = true})
|
||||
@ -34,7 +34,7 @@ namespace api {
|
||||
};
|
||||
template<Vertexs T>
|
||||
inline Mesh::Mesh(vector<T>& vertices, vector<uint32_t>& indices)
|
||||
: Asset(type_info<Mesh>()), mVertices(vertices), mIndices(indices)
|
||||
: Asset(meta_info<Mesh>()), mVertices(vertices), mIndices(indices)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
#include "render/asset/material.h"
|
||||
namespace api {
|
||||
Material::Material() : Asset(type_info<Material>())
|
||||
Material::Material() : Asset(meta_info<Material>())
|
||||
{
|
||||
}
|
||||
Material::~Material()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "render/asset/mesh.h"
|
||||
namespace api {
|
||||
Mesh::Mesh() : Asset(type_info<Mesh>())
|
||||
Mesh::Mesh() : Asset(meta_info<Mesh>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "render/asset/shader.h"
|
||||
namespace api {
|
||||
Shader::Shader() : Asset(type_info<Shader>())
|
||||
Shader::Shader() : Asset(meta_info<Shader>())
|
||||
{
|
||||
}
|
||||
Shader::~Shader()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
static_component("render","engine")
|
||||
add_includedirs("3rdparty", {public = true})
|
||||
add_headerfiles("include/**.h", "include/**.inl", "impl/*.inl")
|
||||
add_headerfiles("include/**.h", "include/**.inl")
|
||||
add_files("src/**.cpp")
|
||||
add_deps("asset", "zlib", "core","shaderc")
|
||||
add_syslinks("user32", {public = true})
|
||||
|
||||
@ -6,6 +6,8 @@ namespace singleapi {
|
||||
using std::pmr::unsynchronized_pool_resource;
|
||||
using std::pmr::unordered_map;
|
||||
};
|
||||
template <class T>
|
||||
concept is_unique_wrap_t = requires(T* t) { typename T::UniqueType; { t->Ptr() } -> std::same_as<typename T::UniqueType*>; };
|
||||
struct MemoryInfo {
|
||||
void* data;
|
||||
bool isAlive;
|
||||
@ -84,6 +86,48 @@ public:
|
||||
return ms_Singleton;
|
||||
}
|
||||
};
|
||||
template <singleapi::is_unique_wrap_t T, size_t hash>
|
||||
class UniquePtr<T, hash> {
|
||||
protected:
|
||||
using U = T::UniqueType;
|
||||
inline static T* ms_Singleton = nullptr;
|
||||
public:
|
||||
template<typename... Args>
|
||||
UniquePtr(Args&&... args) {
|
||||
using namespace singleapi;
|
||||
MemoryInfo info{};
|
||||
if constexpr (hash == 0) {
|
||||
size_t tHash = typeid(T).hash_code();
|
||||
info = GlobalManager::Ptr()->GetInstance(tHash, sizeof(T));
|
||||
}
|
||||
else {
|
||||
info = GlobalManager::Ptr()->GetInstance(hash, sizeof(T));
|
||||
}
|
||||
if (info.isAlive) {
|
||||
ms_Singleton = (T*)info.data;
|
||||
}
|
||||
else {
|
||||
ms_Singleton = new(info.data)T(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
~UniquePtr() {
|
||||
using namespace singleapi;
|
||||
bool isAlive = false;
|
||||
if constexpr (hash == 0) {
|
||||
size_t tHash = typeid(T).hash_code();
|
||||
isAlive = GlobalManager::Ptr()->KillInstance(tHash);
|
||||
}
|
||||
else {
|
||||
isAlive = GlobalManager::Ptr()->KillInstance(hash);
|
||||
}
|
||||
if (ms_Singleton && isAlive) {
|
||||
ms_Singleton->~T();
|
||||
}
|
||||
}
|
||||
static U* Ptr(void) {
|
||||
return ms_Singleton->Ptr();
|
||||
}
|
||||
};
|
||||
constexpr inline size_t string_hash(std::string_view str) noexcept
|
||||
{
|
||||
constexpr size_t fnv_offset_basis = 0xcbf29ce484222325;
|
||||
@ -110,6 +154,7 @@ public:\
|
||||
|
||||
#define SINGLETON_PTR() ms_Singleton = this;
|
||||
|
||||
#define UNIQUER_INLINE_STATIC(cls, name, hash) inline static UniquePtr<cls, string_hash(hash)> name##Ptr;
|
||||
#define UNIQUER_INLINE(cls, name, hash) inline UniquePtr<cls, string_hash(hash)> name##Ptr;
|
||||
#define UNIQUER_STATIC(cls, name, hash) static UniquePtr<cls, string_hash(hash)> name##Ptr;
|
||||
#define UNIQUER_VAL(name) (*name##Ptr.Ptr())
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "singleton.h"
|
||||
//全局生命周期,不回收内存
|
||||
//局部生命周期,每帧回收内存
|
||||
ZLIB_API extern pmr::FrameAllocatorPool* MetaGlobalPool();
|
||||
ZLIB_API extern pmr::FrameAllocatorPool* GlobalPool();
|
||||
ZLIB_API extern pmr::FrameAllocatorPool* FramePool();
|
||||
extern void* operator new(std::size_t size);
|
||||
@ -9,6 +10,10 @@ extern void operator delete(void* ptr) noexcept;
|
||||
extern void operator delete[](void* ptr) noexcept;
|
||||
extern void* operator new(std::size_t size, std::align_val_t align);
|
||||
#ifdef ZLIB_API_VAL
|
||||
ZLIB_API inline pmr::FrameAllocatorPool* MetaGlobalPool() {
|
||||
static pmr::FrameAllocatorPool* globalPool = new pmr::FrameAllocatorPool();
|
||||
return globalPool;
|
||||
}
|
||||
ZLIB_API inline pmr::FrameAllocatorPool* GlobalPool() {
|
||||
static pmr::FrameAllocatorPool* globalPool = new pmr::FrameAllocatorPool();
|
||||
return globalPool;
|
||||
|
||||
@ -43,7 +43,7 @@ namespace pmr
|
||||
constexpr size_t Hash() const noexcept { return hash; }
|
||||
constexpr std::string_view Value() const noexcept { return value; }
|
||||
constexpr bool Valid() const noexcept { return hash != InvalidValue(); }
|
||||
|
||||
operator Name() {return Name(value);}
|
||||
explicit constexpr operator bool() const noexcept { return Valid(); }
|
||||
|
||||
constexpr auto operator<=>(const CName& rhs) const noexcept { return hash <=> rhs.hash; };
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include "type.h"
|
||||
namespace refl {
|
||||
class UClass;
|
||||
class Container;
|
||||
class FieldPtr;
|
||||
struct Any;
|
||||
template<typename T>
|
||||
concept is_not_any_v = !std::is_same_v<args_type_t<T>, Any>;
|
||||
@ -13,9 +15,9 @@ namespace refl {
|
||||
constexpr Any() noexcept: ptr(nullptr), cls(nullptr) {}
|
||||
constexpr Any(const void* ptr, const UClass* cls) noexcept : ptr(ptr), cls(cls) {}
|
||||
template<is_not_any_v T>
|
||||
constexpr Any(T&& v) noexcept : ptr(&v), cls(type_info<T>()) {}
|
||||
constexpr Any(T&& v) noexcept : ptr(&v), cls(meta_info<T>()) {}
|
||||
template<is_not_any_v T>
|
||||
constexpr Any(T* v) noexcept : ptr(v), cls(type_info<T>()) {}
|
||||
constexpr Any(T* v) noexcept : ptr(v), cls(meta_info<T>()) {}
|
||||
template<typename T>//参数 T* => T*
|
||||
constexpr inline T CastTo() const {
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
@ -30,9 +32,24 @@ namespace refl {
|
||||
}
|
||||
}
|
||||
public:
|
||||
operator span<Any>() const {
|
||||
return span<Any>{(Any*)this, 1};
|
||||
}
|
||||
operator Container()const;
|
||||
operator bool()const { return cls && ptr; }
|
||||
bool Check(const UClass* parent) const;
|
||||
template<typename T>
|
||||
T FindVtable(size_t name)const;
|
||||
bool Construct(span<Any> ArgsList) const;
|
||||
Any New(pmr::memory_resource* pool)const;
|
||||
|
||||
Any Member(const FieldPtr& field)const;
|
||||
Any Member(int i)const;
|
||||
|
||||
bool IsArray()const;
|
||||
bool IsObject()const;
|
||||
bool IsContainer()const;
|
||||
bool IsSequence()const;
|
||||
bool IsMap()const;
|
||||
};
|
||||
}
|
||||
@ -1,6 +1,27 @@
|
||||
#include "any.h"
|
||||
#include "uclass.h"
|
||||
#include "convert.h"
|
||||
namespace refl{
|
||||
inline bool Any::IsArray() const
|
||||
{
|
||||
return cls->flag & CLASS_ARRAY_FLAG;
|
||||
}
|
||||
inline bool Any::IsObject() const
|
||||
{
|
||||
return !(cls->flag & CLASS_ARRAY_FLAG) && !(cls->flag & CLASS_POINTER_FLAG);
|
||||
}
|
||||
inline bool Any::IsContainer() const
|
||||
{
|
||||
return cls->flag & CLASS_CONTAINER_FLAG;
|
||||
}
|
||||
inline bool Any::IsSequence() const
|
||||
{
|
||||
return cls->flag & CLASS_SEQUENCE_FLAG;
|
||||
}
|
||||
inline bool Any::IsMap() const
|
||||
{
|
||||
return cls->flag & CLASS_MAP_FLAG;
|
||||
}
|
||||
inline bool Any::Check(const UClass* parent)const
|
||||
{
|
||||
if (cls == parent) {
|
||||
@ -11,9 +32,72 @@ namespace refl{
|
||||
}
|
||||
return cls->IsChildOf(parent);
|
||||
}
|
||||
inline bool Any::Construct(span<Any> ArgsList) const
|
||||
{
|
||||
return cls->Construct((void*)ptr, ArgsList);
|
||||
}
|
||||
inline Any Any::New(pmr::memory_resource* pool) const
|
||||
{
|
||||
void* data = pool->allocate(cls->size);
|
||||
Any any{ data, cls };
|
||||
Convert::Construct(any, this);
|
||||
return any;
|
||||
}
|
||||
template<typename T>
|
||||
inline T Any::FindVtable(size_t name) const
|
||||
{
|
||||
return (T)cls->vtable.Find(name);
|
||||
}
|
||||
inline Any Any::Member(const FieldPtr& field)const
|
||||
{
|
||||
if (field.flag & FIELD_MEMBER_FLAG) {
|
||||
return { (const char*)ptr + field.data.member.offset, field.type };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
inline Any Any::Member(int i) const
|
||||
{
|
||||
if (cls->flag & CLASS_ARRAY_FLAG) {
|
||||
int offset = i * cls->parent->size;
|
||||
if (offset < cls->size)
|
||||
return { (const char*)ptr + offset, cls->parent };
|
||||
}
|
||||
return Any();
|
||||
}
|
||||
|
||||
inline bool UClass::Construct(void* ptr, span<Any> ArgsList) const
|
||||
{
|
||||
auto construct = vtable.Construct();
|
||||
if (construct) {
|
||||
if (construct(ptr, this, ArgsList)) {
|
||||
return true;
|
||||
}
|
||||
auto fieldList = GetFields(EFieldFind::FIND_CTOR, Name("Ctor"));
|
||||
if (fieldList.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::array<Any, MAX_ARGS_LENGTH> ArgsArray = { Any{} , Any{ptr} };
|
||||
int i = 2;
|
||||
for (auto& arg : ArgsList) {
|
||||
ArgsArray[i++] = arg;
|
||||
}
|
||||
span<Any> FieldArgs(&ArgsArray[0], 2 + ArgsList.size());
|
||||
if (fieldList.size() == 1) {
|
||||
return fieldList[0].Invoke<true>(FieldArgs);
|
||||
}
|
||||
//todo: 函数重载需要更精确的处理吗?
|
||||
for (auto& field : fieldList) {
|
||||
if (field.Invoke<true>(FieldArgs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!ArgsList.empty() && ArgsList[0].Check(this)) {
|
||||
memcpy(ptr, ArgsList[0].ptr, size);
|
||||
return true;
|
||||
}
|
||||
memset(ptr, 0, size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
84
engine/modules/engine/zlib/include/refl/detail/container.inl
Normal file
84
engine/modules/engine/zlib/include/refl/detail/container.inl
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
#include "any.h"
|
||||
#include "uclass.inl"
|
||||
#include <iostream>
|
||||
namespace refl {
|
||||
class Container {
|
||||
const void* ptr;
|
||||
const UClass_Container_Impl* cls;
|
||||
friend class Any;
|
||||
Container(const void* ptr, const UClass_Container_Impl* cls) :ptr(ptr), cls(cls) {}
|
||||
public:
|
||||
operator Any()const{
|
||||
return Any{ ptr, cls };
|
||||
}
|
||||
span<const FieldPtr> GetFields() {
|
||||
return cls->parent->GetFields(EFieldFind::FIND_ALL_MEMBER, Name(""));
|
||||
}
|
||||
void construct() {
|
||||
cls->Construct((void*)ptr);
|
||||
}
|
||||
void destruct() {
|
||||
cls->Destruct((void*)ptr);
|
||||
}
|
||||
void insert(const Any& any) {
|
||||
if (any.cls == cls->parent)
|
||||
cls->vinsert(ptr, any.ptr);
|
||||
}
|
||||
int size() {
|
||||
return cls->vsize(ptr);
|
||||
}
|
||||
auto begin() {
|
||||
Container::iterator it(cls);
|
||||
cls->vbegin(it, ptr);
|
||||
return it;
|
||||
}
|
||||
auto end() {
|
||||
Container::iterator it(cls);
|
||||
cls->vend(it, ptr);
|
||||
return it;
|
||||
}
|
||||
// Iterator class
|
||||
class iterator : public UClass_Container_Impl::iterator {
|
||||
private:
|
||||
const UClass_Container_Impl* cls;
|
||||
public:
|
||||
iterator(const UClass_Container_Impl* cls)
|
||||
: cls(cls) {}
|
||||
iterator& operator++() noexcept {
|
||||
cls->viterator_add(this);
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) noexcept {
|
||||
iterator tmp = *this;
|
||||
cls->viterator_add(this);
|
||||
return tmp;
|
||||
}
|
||||
iterator& operator--() noexcept {
|
||||
cls->viterator_sub(this);
|
||||
return *this;
|
||||
}
|
||||
iterator operator--(int) noexcept {
|
||||
iterator tmp = *this;
|
||||
cls->viterator_sub(this);
|
||||
return tmp;
|
||||
}
|
||||
Any operator->() noexcept {
|
||||
return { val , cls->parent };
|
||||
}
|
||||
Any operator*() noexcept {
|
||||
return { val , cls->parent };
|
||||
}
|
||||
constexpr bool operator!=(const iterator& other) const noexcept {
|
||||
return cls != other.cls || ptr != other.ptr;
|
||||
}
|
||||
constexpr bool operator==(const iterator& other) const noexcept {
|
||||
return ptr == other.ptr && cls == other.cls;
|
||||
}
|
||||
};
|
||||
};
|
||||
inline Any::operator Container() const
|
||||
{
|
||||
return Container{ ptr, (const UClass_Container_Impl*)cls };
|
||||
}
|
||||
}
|
||||
38
engine/modules/engine/zlib/include/refl/detail/convert.h
Normal file
38
engine/modules/engine/zlib/include/refl/detail/convert.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "any.h"
|
||||
#include "singleton.h"
|
||||
namespace refl {
|
||||
using UClassPair = std::pair<const UClass*, const UClass*>;
|
||||
// 自定义哈希函数
|
||||
struct UClassPairHash {
|
||||
std::size_t operator()(const UClassPair& pair) const {
|
||||
std::hash<const UClass*> ptr_hash;
|
||||
return ptr_hash(pair.first) ^ (ptr_hash(pair.second) << 1);
|
||||
}
|
||||
};
|
||||
struct UClassPairEqual {
|
||||
bool operator()(const UClassPair& lhs, const UClassPair& rhs) const {
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
};
|
||||
using ConvertFunc = bool (*)(Any& to, const Any& from);
|
||||
using ConvertMap = std::unordered_map<UClassPair, ConvertFunc, UClassPairHash, UClassPairEqual>;
|
||||
struct ConvertMapWrap {
|
||||
using UniqueType = ConvertMap;
|
||||
UniqueType table;
|
||||
ConvertMapWrap();
|
||||
UniqueType* Ptr() {
|
||||
return &table;
|
||||
}
|
||||
};
|
||||
class Convert {
|
||||
protected:
|
||||
friend class ConvertMapWrap;
|
||||
static ConvertMap BuildConvertMap();
|
||||
template<typename From, typename To>
|
||||
static bool ConvertTo(Any& to, const Any& from);
|
||||
static ConvertMap& GetConvertMap();
|
||||
public:
|
||||
static bool Construct(Any& to, const Any& from);
|
||||
};
|
||||
}
|
||||
55
engine/modules/engine/zlib/include/refl/detail/convert.inl
Normal file
55
engine/modules/engine/zlib/include/refl/detail/convert.inl
Normal file
@ -0,0 +1,55 @@
|
||||
#include "convert.h"
|
||||
namespace refl {
|
||||
ConvertMapWrap::ConvertMapWrap() : table(Convert::BuildConvertMap()){}
|
||||
template<typename From, typename To>
|
||||
inline bool refl::Convert::ConvertTo(Any& to, const Any& from)
|
||||
{
|
||||
if constexpr (std::is_same_v<To, std::string>) {
|
||||
if constexpr (std::is_same_v<From, char>) {
|
||||
std::construct_at(to.CastTo<To*>(), from.CastTo<From*>());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_arithmetic_v<To>) {
|
||||
if constexpr (std::is_arithmetic_v<From>) {
|
||||
*to.CastTo<To*>() = (To)*from.CastTo<From*>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline ConvertMap Convert::BuildConvertMap()
|
||||
{
|
||||
ConvertMap convertMap;
|
||||
#define RegisterToFrom(To, From) convertMap.emplace(std::make_pair(meta_info<To>(), meta_info<From>()), &Convert::ConvertTo<To, From>);\
|
||||
convertMap.emplace(std::make_pair(meta_info<From>(), meta_info<To>()), &Convert::ConvertTo<From, To>)
|
||||
|
||||
RegisterToFrom(int, uint32_t);
|
||||
RegisterToFrom(int, uint16_t);
|
||||
RegisterToFrom(int, float);
|
||||
RegisterToFrom(int, double);
|
||||
RegisterToFrom(float, uint32_t);
|
||||
RegisterToFrom(float, double);
|
||||
RegisterToFrom(std::string, char);
|
||||
#undef RegisterToFrom
|
||||
return convertMap;
|
||||
}
|
||||
inline ConvertMap& Convert::GetConvertMap()
|
||||
{
|
||||
UNIQUER_STATIC(ConvertMapWrap, ConvertMap, "refl::convert.ConvertMap")
|
||||
return UNIQUER_VAL(ConvertMap);
|
||||
}
|
||||
inline bool Convert::Construct(Any& to, const Any& from)
|
||||
{
|
||||
if (to.Construct(from))
|
||||
return true;
|
||||
auto& ConvertMap = GetConvertMap();
|
||||
auto it = ConvertMap.find(std::make_pair(to.cls, from.cls));
|
||||
if (it != ConvertMap.end()) {
|
||||
return it->second(to, from);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,6 @@
|
||||
#pragma once
|
||||
#include "pmr/name.h"
|
||||
#include "any.h"
|
||||
#include <span>
|
||||
namespace refl {
|
||||
using pmr::Name;
|
||||
using pmr::CName;
|
||||
using pmr::FName;
|
||||
using pmr::table;
|
||||
using std::span;
|
||||
using Offset = uint32_t;
|
||||
using Method = void*;
|
||||
struct MemberData {
|
||||
@ -27,13 +20,13 @@ namespace refl {
|
||||
constexpr MethodData(Method fptr, span<Any> value, const Any& meta) : fptr(fptr), value(value), meta(meta) {}
|
||||
};
|
||||
enum FieldFlag :uint32_t {
|
||||
FIELD_NONE_FLAG = 0,
|
||||
FIELD_MEMBER_FLAG = 1 << 0,
|
||||
FIELD_METHOD_FLAG = 1 << 1,
|
||||
FIELD_CTOR_FLAG = 1 << 2,
|
||||
FIELD_VALUE_FLAG = 1 << 3,
|
||||
FIELD_NONE_FLAG = 0,
|
||||
FIELD_MEMBER_FLAG = 1 << 0,
|
||||
FIELD_ATTRIBUTE_FLAG = 1 << 1,
|
||||
FIELD_METHOD_FLAG = 1 << 2,
|
||||
FIELD_METHOD_VALUE_FLAG = 1 << 3,
|
||||
FIELD_CTOR_FLAG = 1 << 4,
|
||||
};
|
||||
using enum FieldFlag;
|
||||
struct FieldPtr {
|
||||
union Data
|
||||
{
|
||||
@ -50,5 +43,10 @@ namespace refl {
|
||||
const UClass* type{};
|
||||
Data data{};
|
||||
uint32_t flag{};
|
||||
|
||||
template<typename Func, typename... Args>
|
||||
auto Call(Func func, Args&&... args)const;
|
||||
template<bool IsSafeMemory = false>
|
||||
bool Invoke(span<Any> ArgsList)const;
|
||||
};
|
||||
}
|
||||
@ -1,4 +1,74 @@
|
||||
#include "field.h"
|
||||
namespace refl{
|
||||
|
||||
template<typename T, typename R, typename ...Args>
|
||||
consteval auto fetch_method_t(R(T::*)(Args...)) {
|
||||
using MethodType = R(*)(const void*, Args...);
|
||||
return MethodType{ nullptr };
|
||||
}
|
||||
template<typename R, typename ...Args>
|
||||
consteval auto fetch_method_t(R(*)(Args...)) {
|
||||
using MethodType = R(*)(Args...);
|
||||
return MethodType{ nullptr };
|
||||
}
|
||||
template<typename Func, typename ...Args>
|
||||
inline auto FieldPtr::Call(Func func, Args && ...args) const
|
||||
{
|
||||
using MemberFunc = decltype(fetch_method_t(func));
|
||||
MemberFunc fptr = (MemberFunc)data.method.fptr;
|
||||
return fptr(std::forward<Args>(args)...);
|
||||
}
|
||||
template<bool IsSafeMemory>
|
||||
inline bool FieldPtr::Invoke(span<Any> ArgsList) const
|
||||
{
|
||||
auto Call = type->vtable.Call();
|
||||
if (Call) {
|
||||
span<const UClass*> params = type->GetParams();
|
||||
size_t paramsSize = params.size();
|
||||
size_t argsSize = ArgsList.size();
|
||||
if (argsSize > paramsSize) {
|
||||
ArgsList = span<Any>{ ArgsList.data(), paramsSize };
|
||||
}
|
||||
if constexpr (IsSafeMemory) {
|
||||
if (argsSize < paramsSize && flag & FIELD_METHOD_VALUE_FLAG) {
|
||||
auto value = data.method.value;
|
||||
if (argsSize + value.size() >= paramsSize) {
|
||||
ArgsList = span<Any>{ ArgsList.data(), paramsSize };
|
||||
std::copy(value.begin(), value.end(), &ArgsList[argsSize]);
|
||||
argsSize = paramsSize;
|
||||
}
|
||||
}
|
||||
if (argsSize < paramsSize) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 1; i < paramsSize; i++) {
|
||||
if (ArgsList[i].cls != params[i] && ArgsList[i].Check(params[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Call(this, ArgsList);
|
||||
}
|
||||
else {
|
||||
std::array<Any, MAX_ARGS_LENGTH> ArgsArray{};
|
||||
if (argsSize < paramsSize && flag & FIELD_METHOD_VALUE_FLAG) {
|
||||
auto value = data.method.value;
|
||||
if (argsSize + value.size() >= paramsSize) {
|
||||
std::copy(ArgsList.begin(), ArgsList.end(), ArgsArray.data());
|
||||
ArgsList = span<Any>{ ArgsArray.data(), paramsSize };
|
||||
std::copy(value.begin(), value.end(), &ArgsList[argsSize]);
|
||||
argsSize = paramsSize;
|
||||
}
|
||||
}
|
||||
if (argsSize < paramsSize) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 1; i < paramsSize; i++) {
|
||||
if (ArgsList[i].cls != params[i] && ArgsList[i].Check(params[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Call(this, ArgsList);
|
||||
}
|
||||
}
|
||||
return Call;
|
||||
}
|
||||
}
|
||||
@ -26,6 +26,11 @@ namespace gen {
|
||||
}
|
||||
namespace refl {
|
||||
struct MetaHelp{
|
||||
template<typename T, typename R, typename ...Args>
|
||||
static constexpr auto remove_const(R(T::* ptr)(Args...) const) {
|
||||
using MethodType = R(T::*)(Args...);
|
||||
return (MethodType)ptr;
|
||||
}
|
||||
template<typename T, typename... Args>
|
||||
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
|
||||
|
||||
@ -39,6 +44,8 @@ namespace refl {
|
||||
static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {});
|
||||
|
||||
template<typename T, typename R, typename ...Args>
|
||||
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {});
|
||||
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {}) {
|
||||
return MethodField(remove_const(ptr), name, data);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1 +1,91 @@
|
||||
#include "meta.h"
|
||||
#include "meta.h"
|
||||
#include "uclass.h"
|
||||
namespace refl {
|
||||
span<Any> MakeAnyArgs(span<Any> args, span<const UClass*> params, pmr::memory_resource* alloc = MetaGlobalPool()) {
|
||||
size_t clsIndex = params.size() - args.size();
|
||||
assert(clsIndex > 0);
|
||||
span<const UClass*> subParams = params.subspan(clsIndex);
|
||||
clsIndex = subParams.size();
|
||||
int size = clsIndex * sizeof(Any);
|
||||
for (auto cls : subParams) {
|
||||
size += cls->size;//数据大小
|
||||
}
|
||||
void* memory = (char*)alloc->allocate(size);
|
||||
Any* any = (Any*)memory;
|
||||
char* pData = (char*)memory + clsIndex * sizeof(Any);
|
||||
for (size_t i = 0; i < clsIndex; i++) {
|
||||
any->cls = subParams[i];
|
||||
any->ptr = pData;
|
||||
assert(Convert::Construct(*any, args[i]));
|
||||
any++;
|
||||
pData += any->cls->size;
|
||||
}
|
||||
return span<Any>{(Any*)memory, clsIndex};
|
||||
}
|
||||
template<typename T, typename ...Args>
|
||||
static void NewCtor(void* mem, Args... args) {
|
||||
new (mem) T(std::forward<Args>(args)...);
|
||||
}
|
||||
template<typename T, typename ...Args>
|
||||
inline FieldPtr MetaHelp::CtorField(T(*ptr)(Args...), const MethodData& data)
|
||||
{
|
||||
const UClass* cls = meta_info<void(*)(const void*, real_type_t<Args>...)>();
|
||||
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
|
||||
MethodData method;
|
||||
if (!data.value.empty()) {
|
||||
flag |= FIELD_METHOD_VALUE_FLAG;
|
||||
method.value = MakeAnyArgs(data.value, cls->GetParams());
|
||||
}
|
||||
if (data.meta) {
|
||||
method.meta = data.meta.New(MetaGlobalPool());
|
||||
}
|
||||
method.fptr = (Method)&NewCtor<T, Args...>;
|
||||
return FieldPtr{Name("Ctor"), cls, method, flag};
|
||||
}
|
||||
template<typename T, typename Obj>
|
||||
inline FieldPtr MetaHelp::MemberField(T Obj::* ptr, CName name, const MemberData& data)
|
||||
{
|
||||
const UClass* cls = meta_info<T>();
|
||||
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
|
||||
MemberData member;
|
||||
member.offset = reinterpret_cast<std::size_t>(&(reinterpret_cast<const Obj*>(0)->*ptr));
|
||||
if (data.value) {
|
||||
member.value = data.value.New(MetaGlobalPool());
|
||||
}
|
||||
if (data.meta) {
|
||||
member.meta = data.meta.New(MetaGlobalPool());
|
||||
}
|
||||
return FieldPtr{ name, cls, member, flag };
|
||||
}
|
||||
template<typename R, typename ...Args>
|
||||
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), CName name, const MethodData& data)
|
||||
{
|
||||
MethodData method;
|
||||
uint32_t flag = FIELD_METHOD_FLAG;
|
||||
const UClass* cls = meta_info<real_type_t<R>(*)(real_type_t<Args>...)>();
|
||||
if (!data.value.empty()) {
|
||||
flag |= FIELD_METHOD_VALUE_FLAG;
|
||||
method.value = MakeAnyArgs(data.value, cls->GetParams());
|
||||
}
|
||||
if (data.meta) {
|
||||
method.meta = data.meta.New(MetaGlobalPool());
|
||||
}
|
||||
method.fptr = { *(Method*)&ptr };
|
||||
return { name, cls, method,flag };
|
||||
}
|
||||
template<typename T, typename R, typename ...Args>
|
||||
inline FieldPtr MetaHelp::MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data) {
|
||||
MethodData method;
|
||||
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
|
||||
const UClass* cls = meta_info<real_type_t<R>(*)(const void*, real_type_t<Args>...)>();
|
||||
if (!data.value.empty()) {
|
||||
flag |= FIELD_METHOD_VALUE_FLAG;
|
||||
method.value = MakeAnyArgs(data.value, cls->GetParams());
|
||||
}
|
||||
if (data.meta) {
|
||||
method.meta = data.meta.New(MetaGlobalPool());
|
||||
}
|
||||
method.fptr = { *(Method*)&ptr };
|
||||
return { name, cls, method,flag };
|
||||
}
|
||||
}
|
||||
@ -26,5 +26,5 @@ namespace refl {
|
||||
template<auto v>
|
||||
constexpr auto value_name() noexcept;
|
||||
template<typename T>
|
||||
constexpr auto type_name() noexcept;
|
||||
constexpr auto meta_name() noexcept;
|
||||
}
|
||||
@ -15,7 +15,7 @@ namespace refl {
|
||||
# endif
|
||||
}
|
||||
template<typename T>
|
||||
constexpr auto raw_type_name() noexcept {
|
||||
constexpr auto raw_meta_name() noexcept {
|
||||
constexpr std::string_view sign = func_signature<T>();
|
||||
constexpr size_t size = sign.size();
|
||||
return TStr<size>{ sign };
|
||||
@ -86,7 +86,7 @@ namespace refl {
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
constexpr auto type_name() noexcept {
|
||||
constexpr auto meta_name() noexcept {
|
||||
if constexpr (std::is_same_v<T, void>) {
|
||||
return TStr{ "void" };
|
||||
}
|
||||
@ -96,7 +96,7 @@ namespace refl {
|
||||
return detail::concat(prefix, bit);
|
||||
}
|
||||
else {
|
||||
return detail::raw_type_name<T>();
|
||||
return detail::raw_meta_name<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,15 @@
|
||||
#pragma once
|
||||
#include "pmr/name.h"
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <span>
|
||||
namespace refl {
|
||||
using std::span;
|
||||
using pmr::Name;
|
||||
using pmr::CName;
|
||||
using pmr::FName;
|
||||
using pmr::table;
|
||||
namespace detail {
|
||||
// 定义一个模板结构体用于检测是否为 数组
|
||||
template<typename T>
|
||||
@ -24,7 +32,10 @@ namespace refl {
|
||||
struct is_pair : std::false_type {};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct is_pair<std::pair<T1, T2>> : std::true_type {};
|
||||
struct is_pair<std::pair<T1, T2>> : std::true_type {
|
||||
using key_type = T1;
|
||||
using value_type = T2;
|
||||
};
|
||||
|
||||
// 定义一个模板结构体用于检测是否为 std::pair
|
||||
template<typename T>
|
||||
@ -112,5 +123,6 @@ namespace refl {
|
||||
//类型接口
|
||||
struct UClass;
|
||||
template<typename Type>
|
||||
const UClass* type_info();
|
||||
const UClass* meta_info();
|
||||
constexpr uint32_t MAX_ARGS_LENGTH = 10;
|
||||
}
|
||||
@ -76,12 +76,30 @@ namespace refl {
|
||||
//class meta
|
||||
using GetMeta_t = const UClass* (*)(Name);
|
||||
//function
|
||||
using GetParams_t = span<const UClass>(*)(const UClass*);
|
||||
using GetParams_t = span<const UClass*>(*)(const UClass*);
|
||||
//function args
|
||||
using Call_t = void (*)(const FieldPtr*, span<Any> ArgsList);
|
||||
using Call_t = void (*)(const FieldPtr*,span<Any> ArgsList);
|
||||
//object
|
||||
using Construct_t = bool (*)(void* ptr, const UClass* cls, span<Any> ArgsList);
|
||||
using Construct_t = bool (*)(void* ptr, const UClass* cls,span<Any> ArgsList);
|
||||
using Destruct_t = void (*)(void*);
|
||||
void AddGetFields(GetFields_t func) {
|
||||
Add(string_hash("GetFields"), (void*)func);
|
||||
}
|
||||
void AddGetMeta(GetMeta_t func) {
|
||||
Add(string_hash("GetMeta"), (void*)func);
|
||||
}
|
||||
void AddGetParams(GetParams_t func) {
|
||||
Add(string_hash("GetParams"), (void*)func);
|
||||
}
|
||||
void AddCall(Call_t func) {
|
||||
Add(string_hash("Call"), (void*)func);
|
||||
}
|
||||
void AddConstruct(Construct_t func) {
|
||||
Add(string_hash("Construct"), (void*)func);
|
||||
}
|
||||
void AddDestruct(Destruct_t func) {
|
||||
Add(string_hash("Destruct"), (void*)func);
|
||||
}
|
||||
GetFields_t GetFields() const { return (GetFields_t) Find(string_hash("GetFields")); }
|
||||
GetMeta_t GetMeta() const { return (GetMeta_t) Find(string_hash("GetMeta")); }
|
||||
GetParams_t GetParams() const { return (GetParams_t) Find(string_hash("GetParams")); }
|
||||
@ -101,6 +119,32 @@ namespace refl {
|
||||
public:
|
||||
UClass(std::string_view name, uint32_t size, const UClass* parent = nullptr)
|
||||
:name(name), size(size), parent(parent) {}
|
||||
Any New(pmr::memory_resource* pool, span<Any> ArgsList = {}) const {
|
||||
void* ptr = pool->allocate(size);
|
||||
Construct(ptr, ArgsList);
|
||||
return { ptr , this };
|
||||
}
|
||||
bool Construct(void* ptr, span<Any> ArgsList = {})const;
|
||||
void Destruct(void* ptr)const {
|
||||
auto func = vtable.Destruct();
|
||||
if (func) {
|
||||
func(ptr);
|
||||
}
|
||||
}
|
||||
span<const FieldPtr> GetFields(EFieldFind find, const Name& name)const {
|
||||
auto func = vtable.GetFields();
|
||||
if (func) {
|
||||
return func(this, find, name);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
span<const UClass*> GetParams()const {
|
||||
auto func = vtable.GetParams();
|
||||
if (func) {
|
||||
return func(this);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
bool IsChildOf(const UClass* cls, bool bthis = false) const {
|
||||
const UClass* _parent = bthis ? this : parent;
|
||||
while (_parent != nullptr) {
|
||||
@ -113,7 +157,7 @@ namespace refl {
|
||||
}
|
||||
template<typename T>
|
||||
bool IsChildOf(bool bthis = false) const {
|
||||
return IsChildOf(type_info<T>(), bthis);
|
||||
return IsChildOf(meta_info<T>(), bthis);
|
||||
}
|
||||
public:
|
||||
template<typename T>
|
||||
|
||||
@ -7,12 +7,12 @@ namespace refl {
|
||||
template<typename T>
|
||||
class UClass_Auto : public UClass {
|
||||
public:
|
||||
UClass_Auto() : UClass(type_name<T>().View(), sizeof(T)) {
|
||||
UClass_Auto() : UClass(meta_name<T>().View(), sizeof(T)) {
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
using RT = std::remove_pointer_t<T>;
|
||||
flag |= CLASS_POINTER_FLAG;
|
||||
if constexpr (!std::is_same_v<RT, void>) {
|
||||
parent = type_info<RT>();
|
||||
parent = meta_info<RT>();
|
||||
}
|
||||
}
|
||||
else if constexpr (is_array_v<T>) {
|
||||
@ -21,23 +21,233 @@ namespace refl {
|
||||
if constexpr (std::is_pointer_v<RT>) {
|
||||
flag |= CLASS_POINTER_FLAG;
|
||||
}
|
||||
parent = type_info<RT>();
|
||||
parent = meta_info<RT>();
|
||||
}
|
||||
else {
|
||||
vtable.Add(string_hash("Construct"), (void*)&UClass::Construct<T>);
|
||||
vtable.Add(string_hash("Destruct"), (void*)&UClass::Destruct<T>);
|
||||
vtable.AddConstruct(&UClass::Construct<T>);
|
||||
vtable.AddDestruct(&UClass::Destruct<T>);
|
||||
}
|
||||
}
|
||||
};
|
||||
/*
|
||||
* 模板优化
|
||||
* 成员参数转化为const void*
|
||||
* 引用参数转化为指针
|
||||
* 返回引用转化为指针
|
||||
*/
|
||||
template<typename R, typename... Args>
|
||||
class UMethod_Auto : public UClass {
|
||||
using MethodType = R(*)(Args...);
|
||||
public:
|
||||
std::array<const UClass*, sizeof...(Args) + 1> UList{};
|
||||
UMethod_Auto() : UClass(meta_name<MethodType>().View(), sizeof(MethodType)) {
|
||||
flag = CLASS_TRIVIAL_FLAG;
|
||||
vtable.AddGetParams(&UMethod_Auto::GetParams);
|
||||
vtable.AddCall(&UMethod_Auto::Call);
|
||||
if constexpr (!std::is_same_v<R, void>) {
|
||||
UList[0] = meta_info<R>();
|
||||
}
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
auto ptr = &UList[1];
|
||||
(..., (*ptr = meta_info<Args>(), ptr++));
|
||||
}
|
||||
}
|
||||
//这里顺序似乎是不确定的,但是我实际运用是对的
|
||||
//如果使用make_index_sequence,会多一次函数调用
|
||||
//为什么包裹一层迭代器,就不会出现警告了
|
||||
static void Call(const FieldPtr* field, span<Any> ArgsList) {
|
||||
assert(sizeof...(Args) < ArgsList.size());
|
||||
auto param = ArgsList.end() - 1;
|
||||
if constexpr (std::is_same_v<R, void>) {
|
||||
MethodType fptr = (MethodType)field->data.method.fptr;
|
||||
fptr((param--->CastTo<Args>())...);
|
||||
}
|
||||
else {
|
||||
MethodType fptr = (MethodType)field->data.method.fptr;
|
||||
auto ret = ArgsList.front();
|
||||
if (ret.cls == meta_info<R>()) {
|
||||
*(R*)ret.ptr = fptr((param--->CastTo<Args>())...);
|
||||
}
|
||||
else {
|
||||
fptr((param--->CastTo<Args>())...);
|
||||
}
|
||||
}
|
||||
}
|
||||
static span<const UClass*> GetParams(const UClass* cls) {
|
||||
auto& UList = ((UMethod_Auto*)cls)->UList;
|
||||
return span<const UClass*>{UList};
|
||||
}
|
||||
};
|
||||
class UClass_Container_Impl : public UClass {
|
||||
public:
|
||||
using UClass::UClass;
|
||||
struct iterator {
|
||||
void* ptr;
|
||||
void* val;
|
||||
};
|
||||
//container
|
||||
using size_impl = size_t(*)(const void*);
|
||||
using to_iterator_impl = void(*)(iterator&, const void*);
|
||||
using insert_impl = void (*)(const void*, const void*);
|
||||
//iterator
|
||||
using iterator_impl = void (*)(iterator*);
|
||||
public:
|
||||
size_impl vsize;
|
||||
to_iterator_impl vbegin;
|
||||
to_iterator_impl vend;
|
||||
insert_impl vinsert;
|
||||
iterator_impl viterator_add;
|
||||
iterator_impl viterator_sub;
|
||||
template<typename T>
|
||||
static void insert(const void* ptr, const void* obj) {
|
||||
using value_type = typename T::value_type;
|
||||
if constexpr (is_sequence_v<T>) {
|
||||
((T*)ptr)->push_back(*(value_type*)obj);
|
||||
}
|
||||
else if constexpr (is_map_v<T>) {
|
||||
((T*)ptr)->insert(*(value_type*)obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
template<is_container_v T, typename value_type>
|
||||
class UClass_Container : public UClass_Container_Impl {
|
||||
public:
|
||||
static bool construct(void* ptr, const UClass* cls, span<Any> ArgsList) {
|
||||
new(ptr)T();
|
||||
return true;
|
||||
}
|
||||
static void destruct(void* ptr) {
|
||||
((T*)ptr)->~T();
|
||||
}
|
||||
static void begin(iterator& pit, const void* ptr) {
|
||||
auto it = ((T*)ptr)->begin();
|
||||
memcpy(&pit, &it, sizeof(it));
|
||||
pit.val = &*it;
|
||||
}
|
||||
static void end(iterator& pit, const void* ptr) {
|
||||
auto it = ((T*)ptr)->end();
|
||||
memcpy(&pit, &it, sizeof(it));
|
||||
pit.val = &*it;
|
||||
}
|
||||
static void add(iterator* pit) {
|
||||
auto it = ++(*(typename T::iterator*)pit);
|
||||
memcpy(pit, &it, sizeof(it));
|
||||
pit->val = &*it;
|
||||
}
|
||||
static void sub(iterator* pit) {
|
||||
auto it = --(*(typename T::iterator*)pit);
|
||||
memcpy(pit, &it, sizeof(it));
|
||||
pit->val = &*it;
|
||||
}
|
||||
UClass_Container() : UClass_Container_Impl(meta_name<T>().View(), sizeof(T)) {
|
||||
parent = meta_info<value_type>();
|
||||
flag = CLASS_CONTAINER_FLAG;
|
||||
vtable.AddConstruct(&UClass_Container::construct);
|
||||
vtable.AddDestruct(&UClass_Container::destruct);
|
||||
if constexpr (is_sequence_v<T>) {
|
||||
flag |= CLASS_SEQUENCE_FLAG;
|
||||
}
|
||||
else if constexpr (is_map_v<T>)
|
||||
{
|
||||
flag |= CLASS_MAP_FLAG;
|
||||
}
|
||||
auto p_size = &T::size;
|
||||
vsize = *(size_impl*)&p_size;
|
||||
vbegin = &UClass_Container::begin;
|
||||
vend = &UClass_Container::end;
|
||||
vinsert = &UClass_Container::insert<T>;
|
||||
|
||||
viterator_add = &UClass_Container::add;
|
||||
viterator_sub = &UClass_Container::sub;
|
||||
};
|
||||
};
|
||||
template<typename T, typename MetaImpl>
|
||||
class UClass_Meta : public UClass {
|
||||
using FieldsType = decltype(MetaImpl::MakeFields());
|
||||
public:
|
||||
FieldsType Fields{ MetaImpl::MakeFields() };
|
||||
UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)) {
|
||||
UClass_Meta() : UClass(meta_name<T>().View(), sizeof(T)) {
|
||||
if constexpr (has_parent_v<T>) {
|
||||
parent = type_info<parent_t<T>>();
|
||||
parent = meta_info<parent_t<T>>();
|
||||
}
|
||||
|
||||
vtable.AddGetFields(&UClass_Meta::GetFields);
|
||||
vtable.AddConstruct(&UClass::Construct<T>);
|
||||
}
|
||||
span<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
|
||||
constexpr int length = std::tuple_size<FieldsType>::value;
|
||||
constexpr int MemberCount = MetaImpl::MemberCount();
|
||||
constexpr int CtorCount = MetaImpl::CtorCount();
|
||||
switch (find) {
|
||||
case EFieldFind::FIND_ALL_FIELD:
|
||||
return span<const FieldPtr>(&Fields[0], length);
|
||||
case EFieldFind::FIND_ALL_MEMBER:
|
||||
return span<const FieldPtr>(&Fields[0], MemberCount);
|
||||
case EFieldFind::FIND_ALL_METHOD:
|
||||
return span<const FieldPtr>(&Fields[MemberCount + CtorCount], length - MemberCount - CtorCount);
|
||||
case EFieldFind::FIND_CTOR:
|
||||
return span<const FieldPtr>(&Fields[MemberCount], CtorCount);
|
||||
case EFieldFind::FIND_FIELD:
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (name == Fields[i].name) {
|
||||
return span<const FieldPtr>(&Fields[i], 1);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
case EFieldFind::FIND_MEMBER:
|
||||
for (int i = 0; i < MemberCount; i++) {
|
||||
if (name == Fields[i].name) {
|
||||
return span<const FieldPtr>(&Fields[i], 1);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
case EFieldFind::FIND_METHOD:
|
||||
for (int i = MemberCount + CtorCount; i < length; i++) {
|
||||
if (name == Fields[i].name) {
|
||||
return span<const FieldPtr>(&Fields[i], 1);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
case EFieldFind::FIND_METHODS:
|
||||
{
|
||||
int first = 0, count = 0;
|
||||
for (int i = MemberCount + CtorCount; i < length; i++) {
|
||||
if (name == Fields[i].name) {
|
||||
if (!count) {
|
||||
first = i;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
else if (count) {
|
||||
return span<const FieldPtr>(&Fields[first], count);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
static span<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, Name name) {
|
||||
auto cls = static_cast<const UClass_Meta*>(_cls);
|
||||
return cls->GetFields(find, name);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct meta_info_impl {
|
||||
static UClass* create() {
|
||||
return new(MetaGlobalPool()) UClass_Auto<T>{};
|
||||
}
|
||||
};
|
||||
template<typename R, typename... Args>
|
||||
struct meta_info_impl<R(*)(Args...)> {
|
||||
static UClass* create() {
|
||||
return new(MetaGlobalPool()) UMethod_Auto<R, Args...>{};
|
||||
}
|
||||
};
|
||||
template<is_container_v T>
|
||||
struct meta_info_impl<T> {
|
||||
static UClass* create() {
|
||||
return new(MetaGlobalPool()) UClass_Container<T, typename T::value_type>{};
|
||||
}
|
||||
};
|
||||
using __tClassTable = table<Name, const UClass*>;
|
||||
@ -50,22 +260,22 @@ namespace refl {
|
||||
return nullptr;
|
||||
}
|
||||
template<typename Type>
|
||||
inline const UClass* type_info()
|
||||
inline const UClass* meta_info()
|
||||
{
|
||||
using T = real_type_t<Type>;
|
||||
constexpr auto name = type_name<T>();
|
||||
constexpr auto name = meta_name<T>();
|
||||
if (auto cls = find_info(name.View())) {
|
||||
return cls;
|
||||
}
|
||||
UClass* cls;
|
||||
if constexpr (is_meta_v<T>){
|
||||
cls = new(GlobalPool()) UClass_Meta<T, meta_t<T>>{};
|
||||
cls = new(MetaGlobalPool()) UClass_Meta<T, meta_t<T>>{};
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, void>) {
|
||||
cls = new(GlobalPool()) UClass{ name.View(), 0 };
|
||||
cls = new(MetaGlobalPool()) UClass{ name.View(), 0 };
|
||||
}
|
||||
else {
|
||||
cls = new(GlobalPool()) UClass_Auto<T>{};
|
||||
cls = meta_info_impl<T>::create();
|
||||
}
|
||||
auto& ClassTable = UNIQUER_VAL(ClassTable);
|
||||
ClassTable[name.View()] = cls;
|
||||
|
||||
@ -2,5 +2,7 @@
|
||||
#include "detail/name.inl"
|
||||
#include "detail/any.inl"
|
||||
#include "detail/meta.inl"
|
||||
#include "detail/uclass.inl"
|
||||
#include "detail/field.inl"
|
||||
#include "detail/convert.inl"
|
||||
#include "detail/container.inl"
|
||||
#include "macro.h"
|
||||
@ -10,7 +10,7 @@ namespace refl {
|
||||
parray(): m_cls(nullptr), m_ptr(nullptr),m_count(0) {}
|
||||
template<typename C>
|
||||
requires std::is_base_of_v<T, C>
|
||||
parray(std::vector<C>& vec) : m_cls(type_info<C>()), m_ptr(nullptr){
|
||||
parray(std::vector<C>& vec) : m_cls(meta_info<C>()), m_ptr(nullptr){
|
||||
m_count = vec.size();
|
||||
if (m_count > 0) {
|
||||
C* ptr = new C[m_count];
|
||||
|
||||
@ -12,13 +12,14 @@ end
|
||||
function static_component(name, owner, opt)
|
||||
target(owner)
|
||||
add_deps(name)
|
||||
add_includedirs("impl")
|
||||
add_headerfiles("impl/*.inl")
|
||||
target_end()
|
||||
target(name)
|
||||
set_kind("static")
|
||||
set_group("Engine/"..owner.."__comp")
|
||||
add_rules("engine.api")
|
||||
add_includedirs("include", {public = true})
|
||||
add_includedirs("impl")
|
||||
add_deps("singleton")
|
||||
end
|
||||
function shared_module(name, owner, opt)
|
||||
|
||||
25
game/zworld/editor/test_refl.h
Normal file
25
game/zworld/editor/test_refl.h
Normal file
@ -0,0 +1,25 @@
|
||||
#include "refl/pch.h"
|
||||
#include <iostream>
|
||||
using namespace refl;
|
||||
using namespace std;
|
||||
namespace api {
|
||||
struct Guid {
|
||||
UPROPERTY()
|
||||
int a;
|
||||
UPROPERTY()
|
||||
float b;
|
||||
UPROPERTY()
|
||||
string view;
|
||||
USING_OVERLOAD_CTOR(Guid, int , float)
|
||||
UFUNCTION({}, ref = USING_CTOR_NAME)
|
||||
Guid(int aa, float bb) :a(aa), b(bb), view("default") {
|
||||
cout << view << endl;
|
||||
}
|
||||
UFUNCTION({})
|
||||
int Multy(int c)const {
|
||||
int d = a * b;
|
||||
return d * c;
|
||||
}
|
||||
};
|
||||
}
|
||||
#include ".zworld-editor/test_refl_gen.inl"
|
||||
@ -1,22 +1,26 @@
|
||||
#define ZLIB_API
|
||||
#define ZLIB_API_VAL
|
||||
#include "refl/pch.h"
|
||||
#include <iostream>
|
||||
using namespace refl;
|
||||
namespace api {
|
||||
struct api_t {
|
||||
|
||||
};
|
||||
}
|
||||
struct test {
|
||||
|
||||
};
|
||||
void (*testfn)(test);
|
||||
using testfn_t = decltype(testfn);
|
||||
#define CORE_API
|
||||
#define CORE_API_VAL
|
||||
#include "archive/json.h"
|
||||
#include "test_refl.h"
|
||||
#include <os/file_handle.h>
|
||||
using namespace api;
|
||||
int main() {
|
||||
auto r1 = type_name<testfn_t>();
|
||||
auto r2 = type_name<api::api_t>();
|
||||
auto t1 = r1.View();
|
||||
auto t2 = r2.View();
|
||||
table<uint32_t, string> t1, t2;
|
||||
t1[1] = "hello";
|
||||
t1[2] = "world";
|
||||
auto text = JsonSerialize(t1);
|
||||
FileHandle handle("test.txt");
|
||||
handle.Open(FILE_OP::WRITE, false);
|
||||
handle.Write(text);
|
||||
auto res = JsonDeserialize<table<uint32_t, string>>(text);
|
||||
if (res) {
|
||||
t2 = *res;
|
||||
}
|
||||
auto cls = meta_info<api::Guid>();
|
||||
Any args[3] = { Any{ (int)2 }, Any{ (float)3 }, Any{false} };
|
||||
Any obj = cls->New(FramePool(), span<Any>{args});
|
||||
auto ptr = &api::Guid::Multy;
|
||||
std::cout << "hello world" << std::endl;
|
||||
}
|
||||
0
game/zworld/logs/zengine.log
Normal file
0
game/zworld/logs/zengine.log
Normal file
@ -4,6 +4,9 @@ target("zworld")
|
||||
add_headerfiles("src/*.h")
|
||||
add_dependency("engine", "editor", "vulkan", {public = true})
|
||||
target("zworld-editor")
|
||||
add_rules("c++.codegen",{
|
||||
files = {"editor/test_refl.h"}
|
||||
})
|
||||
add_files("editor/*.cpp")
|
||||
add_headerfiles("editor/*.h")
|
||||
add_deps("zlib")
|
||||
add_deps("zlib", "core")
|
||||
Loading…
Reference in New Issue
Block a user