More foundation for more reflection.
This commit is contained in:
parent
433c3b4633
commit
cd886cefff
1
LibConf
1
LibConf
@ -55,6 +55,7 @@ src_files = Split("""
|
|||||||
source/shader_module.cpp
|
source/shader_module.cpp
|
||||||
source/swapchain.cpp
|
source/swapchain.cpp
|
||||||
source/texture.cpp
|
source/texture.cpp
|
||||||
|
source/type_meta.cpp
|
||||||
source/window.cpp
|
source/window.cpp
|
||||||
|
|
||||||
source/app/vulkan_application.cpp
|
source/app/vulkan_application.cpp
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if !defined(IWA_CLASS_HPP_INCLUDED)
|
|
||||||
#define IWA_CLASS_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace iwa
|
|
||||||
{
|
|
||||||
struct Function
|
|
||||||
{
|
|
||||||
const char* name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClassCreationArgs
|
|
||||||
{
|
|
||||||
const class Class* parent = nullptr;
|
|
||||||
std::string name;
|
|
||||||
std::vector<Function> functions;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Class
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const Class* mParent;
|
|
||||||
std::string mName;
|
|
||||||
std::vector<Function> mFunctions;
|
|
||||||
public:
|
|
||||||
explicit Class(ClassCreationArgs args) noexcept : mParent(args.parent), mName(std::move(args.name)) {}
|
|
||||||
|
|
||||||
[[nodiscard]] const std::string& getName() const noexcept { return mName; }
|
|
||||||
[[nodiscard]] const Class* getParent() const noexcept { return mParent; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClassBuilder
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const Class* mParent = nullptr;
|
|
||||||
std::string mName;
|
|
||||||
std::vector<Function> mFunctions;
|
|
||||||
public:
|
|
||||||
explicit ClassBuilder(std::string name) noexcept : mName(std::move(name)) {}
|
|
||||||
|
|
||||||
ClassBuilder& setParent(const Class* parent) noexcept
|
|
||||||
{
|
|
||||||
mParent = parent;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class make() noexcept
|
|
||||||
{
|
|
||||||
return Class({
|
|
||||||
.parent = mParent,
|
|
||||||
.name = std::move(mName),
|
|
||||||
.functions = std::move(mFunctions)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TFunction>
|
|
||||||
ClassBuilder& addFunction(const char* name, TFunction func)
|
|
||||||
{
|
|
||||||
(void) func;
|
|
||||||
mFunctions.push_back({.name = name});
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !defined(IWA_CLASS_HPP_INCLUDED)
|
|
@ -112,7 +112,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reflection
|
// reflection
|
||||||
static inline void buildClass(ClassBuilder& builder) noexcept;
|
static inline void buildClass(ClassBuilder<Instance>& builder) noexcept;
|
||||||
private:
|
private:
|
||||||
void runDeleters(bool runAll = false);
|
void runDeleters(bool runAll = false);
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ mijin::FuturePtr<std::invoke_result_t<TFunction>> Instance::runOnMainThread(TFun
|
|||||||
}(std::forward<TFunction>(function)));
|
}(std::forward<TFunction>(function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::buildClass(ClassBuilder& builder) noexcept
|
void Instance::buildClass(ClassBuilder<Instance>& builder) noexcept
|
||||||
{
|
{
|
||||||
super_t::buildClass(builder);
|
super_t::buildClass(builder);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mijin/detect.hpp>
|
#include <mijin/detect.hpp>
|
||||||
#include <mijin/debug/assert.hpp>
|
#include <mijin/debug/assert.hpp>
|
||||||
#include "iwa/class.hpp"
|
#include "iwa/type_meta.hpp"
|
||||||
|
|
||||||
#if !defined(IWA_OBJECTPTR_TRACKING)
|
#if !defined(IWA_OBJECTPTR_TRACKING)
|
||||||
# if !defined(KAZAN_RELEASE)
|
# if !defined(KAZAN_RELEASE)
|
||||||
@ -427,14 +427,14 @@ public:
|
|||||||
{
|
{
|
||||||
static const Class myClass = [](std::string&& name)
|
static const Class myClass = [](std::string&& name)
|
||||||
{
|
{
|
||||||
ClassBuilder builder(std::move(name));
|
ClassBuilder<TConcrete> builder(std::move(name));
|
||||||
TConcrete::buildClass(builder);
|
TConcrete::buildClass(builder);
|
||||||
return builder.make();
|
return builder.make();
|
||||||
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
||||||
return myClass;
|
return myClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buildClass(ClassBuilder& builder) noexcept
|
static void buildClass(ClassBuilder<TConcrete>& builder) noexcept
|
||||||
{
|
{
|
||||||
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
||||||
{
|
{
|
||||||
@ -469,14 +469,14 @@ public:
|
|||||||
{
|
{
|
||||||
static const Class myClass = [](std::string&& name)
|
static const Class myClass = [](std::string&& name)
|
||||||
{
|
{
|
||||||
ClassBuilder builder(std::move(name));
|
ClassBuilder<TConcrete> builder(std::move(name));
|
||||||
TConcrete::buildClass(builder);
|
TConcrete::buildClass(builder);
|
||||||
return builder.make();
|
return builder.make();
|
||||||
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
}(impl::getClassNameFromSourceLocation(std::source_location::current()));
|
||||||
return myClass;
|
return myClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buildClass(ClassBuilder& builder) noexcept
|
static void buildClass(ClassBuilder<TConcrete>& builder) noexcept
|
||||||
{
|
{
|
||||||
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
if constexpr (!std::is_same_v<TBase, BaseObject>)
|
||||||
{
|
{
|
||||||
|
186
include/iwa/type_meta.hpp
Normal file
186
include/iwa/type_meta.hpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(IWA_CLASS_HPP_INCLUDED)
|
||||||
|
#define IWA_CLASS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <source_location>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <mijin/util/traits.hpp>
|
||||||
|
|
||||||
|
namespace iwa
|
||||||
|
{
|
||||||
|
struct Function
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Property
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClassCreationArgs
|
||||||
|
{
|
||||||
|
const class Class* parent = nullptr;
|
||||||
|
std::string name;
|
||||||
|
std::vector<Function> functions;
|
||||||
|
std::vector<Property> properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Class
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const Class* mParent;
|
||||||
|
std::string mName;
|
||||||
|
std::vector<Function> mFunctions;
|
||||||
|
std::vector<Property> mProperties;
|
||||||
|
public:
|
||||||
|
explicit Class(ClassCreationArgs args) noexcept : mParent(args.parent), mName(std::move(args.name)),
|
||||||
|
mFunctions(std::move(args.functions)), mProperties(std::move(args.properties)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] const Class* getParent() const noexcept { return mParent; }
|
||||||
|
[[nodiscard]] const std::string& getName() const noexcept { return mName; }
|
||||||
|
[[nodiscard]] const std::vector<Function>& getFunctions() const noexcept { return mFunctions; }
|
||||||
|
[[nodiscard]] const std::vector<Property>& getProperties() const noexcept { return mProperties; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TObject>
|
||||||
|
class ClassBuilder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const Class* mParent = nullptr;
|
||||||
|
std::string mName;
|
||||||
|
std::vector<Function> mFunctions;
|
||||||
|
std::vector<Property> mProperties;
|
||||||
|
public:
|
||||||
|
explicit ClassBuilder(std::string name) noexcept : mName(std::move(name)) {}
|
||||||
|
|
||||||
|
ClassBuilder& setParent(const Class* parent) noexcept
|
||||||
|
{
|
||||||
|
mParent = parent;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Class make() noexcept
|
||||||
|
{
|
||||||
|
return Class({
|
||||||
|
.parent = mParent,
|
||||||
|
.name = std::move(mName),
|
||||||
|
.functions = std::move(mFunctions),
|
||||||
|
.properties = std::move(mProperties)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TFunction>
|
||||||
|
ClassBuilder& addFunction(const char* name, TFunction func)
|
||||||
|
{
|
||||||
|
(void) func;
|
||||||
|
mFunctions.push_back({.name = name});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TField>
|
||||||
|
ClassBuilder& addProperty(const char* name, TField TObject::* field)
|
||||||
|
{
|
||||||
|
(void) field;
|
||||||
|
mProperties.push_back({.name = name});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TObject>
|
||||||
|
class ClassRegisterer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClassRegisterer() noexcept {
|
||||||
|
registerClass(&TObject::getClassObject());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#define IWA_REGISTER_CLASS(clazz) \
|
||||||
|
namespace \
|
||||||
|
{ \
|
||||||
|
[[maybe_unused]] ClassRegisterer<clazz> gRegisterer; \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StructCreationArgs
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Struct
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string mName;
|
||||||
|
public:
|
||||||
|
explicit Struct(StructCreationArgs args) noexcept : mName(std::move(args.name)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& getName() const noexcept { return mName; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TStruct>
|
||||||
|
class StructBuilder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string mName;
|
||||||
|
public:
|
||||||
|
explicit StructBuilder(std::string name) noexcept : mName(std::move(name)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] Struct make() noexcept
|
||||||
|
{
|
||||||
|
return Struct({
|
||||||
|
.name = std::move(mName)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void registerClass(const Class* clazz) noexcept;
|
||||||
|
[[nodiscard]] std::span<const Class*> getRegisteredClasses() noexcept;
|
||||||
|
|
||||||
|
template<typename TStruct>
|
||||||
|
void buildStruct(StructBuilder<TStruct>& /* builder */) noexcept
|
||||||
|
{
|
||||||
|
static_assert(mijin::always_false_v<TStruct>, "Missing buildStruct() function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
[[nodiscard]] constexpr std::string getStructNameFromSourceLocation(const std::source_location& sourceLocation) noexcept
|
||||||
|
{
|
||||||
|
const char* ERROR_NAME = "<error detecting struct name>";
|
||||||
|
#if MIJIN_COMPILER == MIJIN_COMPILER_GCC || MIJIN_COMPILER == MIJIN_COMPILER_CLANG
|
||||||
|
const std::string_view functionName = sourceLocation.function_name();
|
||||||
|
const std::size_t pos = functionName.find("TStruct = ");
|
||||||
|
if (pos == std::string_view::npos)
|
||||||
|
{
|
||||||
|
return ERROR_NAME;
|
||||||
|
}
|
||||||
|
const std::size_t begin = pos + 10;
|
||||||
|
const std::size_t end = functionName.find(']', begin);
|
||||||
|
if (end == std::string_view::npos)
|
||||||
|
{
|
||||||
|
return ERROR_NAME;
|
||||||
|
}
|
||||||
|
return std::string(functionName.substr(begin, end - begin));
|
||||||
|
#else
|
||||||
|
return "<unsupported compiler family>";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TStruct>
|
||||||
|
const Struct& reflectStruct() noexcept
|
||||||
|
{
|
||||||
|
static const Struct theStruct = [](std::string&& name)
|
||||||
|
{
|
||||||
|
StructBuilder<TStruct> builder(std::move(name));
|
||||||
|
buildStruct(builder);
|
||||||
|
return builder.make();
|
||||||
|
}(impl::getStructNameFromSourceLocation(std::source_location::current()));
|
||||||
|
return theStruct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(IWA_CLASS_HPP_INCLUDED)
|
@ -81,6 +81,13 @@ public:
|
|||||||
mijin::Signal<> mouseLeft;
|
mijin::Signal<> mouseLeft;
|
||||||
mijin::Signal<> closeRequested;
|
mijin::Signal<> closeRequested;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// reflection
|
||||||
|
template<>
|
||||||
|
inline void buildStruct<WindowCreationArgs>(StructBuilder<WindowCreationArgs>& builder) noexcept
|
||||||
|
{
|
||||||
|
(void) builder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //IWA_WINDOW_HPP_INCLUDED
|
#endif //IWA_WINDOW_HPP_INCLUDED
|
||||||
|
@ -13,6 +13,8 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
|||||||
|
|
||||||
namespace iwa
|
namespace iwa
|
||||||
{
|
{
|
||||||
|
IWA_REGISTER_CLASS(Instance)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void buildDefaultInstanceExtensionList(std::vector<ExtensionInfo>& outExtensions) noexcept
|
void buildDefaultInstanceExtensionList(std::vector<ExtensionInfo>& outExtensions) noexcept
|
||||||
|
18
source/type_meta.cpp
Normal file
18
source/type_meta.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "iwa/type_meta.hpp"
|
||||||
|
|
||||||
|
namespace iwa
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::vector<const Class*> gClassRegistry;
|
||||||
|
}
|
||||||
|
void registerClass(const Class* clazz) noexcept
|
||||||
|
{
|
||||||
|
gClassRegistry.push_back(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const Class*> getRegisteredClasses() noexcept
|
||||||
|
{
|
||||||
|
return gClassRegistry;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,8 @@ namespace iwa
|
|||||||
{
|
{
|
||||||
inline constexpr const char* WINDOW_DATA_NAME = "iwa_window";
|
inline constexpr const char* WINDOW_DATA_NAME = "iwa_window";
|
||||||
|
|
||||||
|
IWA_REGISTER_CLASS(Window)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
Window* gLastEventWindow = nullptr;
|
Window* gLastEventWindow = nullptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user