This commit is contained in:
ouczbs 2024-10-25 09:45:49 +08:00
parent 2e8213c1a1
commit 702b15225c
42 changed files with 958 additions and 91 deletions

View File

@ -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";
}

View File

@ -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")

View File

@ -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) {

View File

@ -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()});
}
}
}

View File

@ -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;

View File

@ -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() });
}
}
}

View File

@ -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);
}

View File

@ -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)
{
}

View File

@ -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")

View File

@ -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;
}
}
};
}

View File

@ -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*);

View File

@ -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;
}
}

View File

@ -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})

View File

@ -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)
{
}
};

View File

@ -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()

View File

@ -1,6 +1,6 @@
#include "render/asset/mesh.h"
namespace api {
Mesh::Mesh() : Asset(type_info<Mesh>())
Mesh::Mesh() : Asset(meta_info<Mesh>())
{
}

View File

@ -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()

View File

@ -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})

View File

@ -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())

View File

@ -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;

View File

@ -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; };

View File

@ -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;
};
}

View File

@ -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;
}
}

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

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

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

View File

@ -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;
};
}

View File

@ -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;
}
}

View File

@ -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);
}
};
}

View File

@ -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 };
}
}

View File

@ -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;
}

View File

@ -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>();
}
}
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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;

View File

@ -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"

View File

@ -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];

View File

@ -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)

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

View File

@ -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;
}

View File

View 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")