3#include <initializer_list>
11#include <entt/entt.hpp>
22 #undef EE_REGISTRY_LOG
29 template<
typename T,
typename =
void>
32 struct has_super<T, std::void_t<typename T::Super>> : std::true_type {};
34 template<typename T, bool = has_super<T>::value>
36 static std::vector<ComponentField>
Get() {
return {}; }
41 static std::vector<ComponentField>
Get() {
42 using Super =
typename T::Super;
43 if constexpr (!std::is_same_v<Super, void> && std::is_base_of_v<Component, Super>) {
44 return Super::generated_classEntry.ClassFieldStack;
54 #define HideInInspector HideInInspectorTag{}
57 #define Flatten FlattenTag{}
60 #define DisplayName(x) DisplayNameTag{x}
63 #define Tooltip(x) TooltipTag{x}
66 #define ReadOnly ReadOnlyTag{}
69 #define ColorPicker ColorTag{}
75 #define EditorIcon(path) EditorIconTag{path}
114 std::type_index
type{
typeid(void) };
124 static void Register(
const std::string& name,
EECategory category, std::vector<FieldOption>& options);
126 static std::unordered_map<std::type_index, Entry>&
GetEntries() {
127 static std::unordered_map<std::type_index, Entry> entries;
131 static std::string
GetName(
const std::type_info& type);
134 static std::vector<std::string> paths;
139 static std::vector<std::string> stack;
145 static std::vector<ComponentField> stack;
163 static std::map<std::string, std::vector<ComponentField>> m_customComponentFields;
164 return m_customComponentFields;
167 template<
typename Class,
typename FieldType>
168 static void AddProperty(FieldType Class::* member, const std::string& name, std::initializer_list<
FieldOption> options);
172#define EECATEGORY(name) \
174 inline static struct categoryRegistrar { \
175 categoryRegistrar() { \
176 generated_classEntry.Category = EECategory(name); \
178 } generated_categoryRegistrar; \
179 virtual EECategory GetCategory() const override { return generated_classEntry.Category; } \
187#define BEGIN_COMPONENT(T, ...) \
191inline static struct T##ClassEntry { \
193 FieldStartIndex = ::Elevate::ComponentRegistry::CompilationClassFieldStack().size(); \
194 ::Elevate::ComponentRegistry::AddClassToStack(#T); \
195 ClassName = ::Elevate::ComponentRegistry::GetCleanedName(#T); \
196 HasBaseClass = false; \
197 Options = { __VA_ARGS__ }; \
199 std::vector<FieldOption> Options; \
200 EECategory Category; \
201 size_t FieldStartIndex = 0; \
202 std::string ClassName; \
203 std::vector<Elevate::ComponentField> ClassFieldStack; \
204 bool HasBaseClass = false; \
205} generated_classEntry; \
207 virtual bool RemoveFromGameObject() override { \
209 gameObject->RemoveComponent<T>(); \
215#define EXPOSE(param, ...) \
217inline static struct param##PropertyEntry { \
218 param##PropertyEntry() { \
219 using MemberT = decltype(ThisType::param); \
220 ::Elevate::ComponentRegistry::AddProperty<ThisType, MemberT>( \
226} generated_##param##PropertyEntry;
228#define END_COMPONENT() \
230 inline static struct ClassEntryEnd { \
232 ::Elevate::ComponentRegistry::Register<ThisType>( \
233 generated_classEntry.ClassName, \
234 generated_classEntry.Category, \
235 generated_classEntry.Options \
237 ::Elevate::ComponentRegistry::PopClassStack(); \
238 auto& global = ::Elevate::ComponentRegistry::CompilationClassFieldStack(); \
239 size_t start = generated_classEntry.FieldStartIndex; \
240 for (size_t i = start; i < global.size(); ++i) { \
241 generated_classEntry.ClassFieldStack.push_back(global[i]); \
243 if (start < global.size()) { \
244 global.erase(global.begin() + start, global.end()); \
247 } generated_classEntryEnd; \
249 inline virtual std::string GetName() const override { return generated_classEntry.ClassName; } \
250 inline virtual Elevate::ComponentLayout GetLayout() const override { \
251 std::vector<Elevate::ComponentField> instanceFields; \
252 if (generated_classEntry.HasBaseClass) { \
253 auto parentFields = ParentFieldsHelper<ThisType>::Get(); \
254 for (const Elevate::ComponentField& field : parentFields) { \
255 const void* fieldPtr = reinterpret_cast<const char*>(this) + field.offset; \
256 instanceFields.push_back(Elevate::ComponentField( \
261 for (const Elevate::ComponentField& field : generated_classEntry.ClassFieldStack) { \
262 const void* fieldPtr = reinterpret_cast<const char*>(this) + field.offset; \
263 instanceFields.push_back(Elevate::ComponentField(field, fieldPtr)); \
265 return Elevate::ComponentLayout(generated_classEntry.ClassName, instanceFields); \
267 virtual Component* Clone() override { \
268 ThisType* clone = new ThisType(); \
269 for (auto& field : ComponentRegistry::GetCustomComponentFields()[typeid(ThisType).name()]) { \
270 field.CopyValue(this, clone); \
274 virtual void CopyFrom(Component* other) override { \
275 if (auto o = dynamic_cast<ThisType*>(other)) { \
276 if (generated_classEntry.HasBaseClass) { \
277 auto parentFields = ParentFieldsHelper<ThisType>::Get(); \
278 for (const Elevate::ComponentField& field : parentFields) { \
279 field.CopyValue(o, this); \
282 for (const Elevate::ComponentField& field : generated_classEntry.ClassFieldStack) { \
283 field.CopyValue(o, this); \
287 EE_ERROR("Error: Tried setting a %s from a %s component in CopyFrom(Component*)", \
288 this->GetName(), other ? other->GetName() : "null"); \
291 virtual Elevate::GameObjectComponentFactory GetFactory() const override { \
292 auto& entries = ComponentRegistry::GetEntries(); \
293 auto it = entries.find(typeid(ThisType)); \
294 if (it != entries.end()) { \
295 return it->second.factory; \
299 virtual Elevate::GameObjectComponentDestructor GetDestructor() const override { \
300 auto& entries = ComponentRegistry::GetEntries(); \
301 auto it = entries.find(typeid(ThisType)); \
302 if (it != entries.end()) { \
303 return it->second.destructor; \
307 virtual const void* GetEditorIconHandle() const override { \
308 auto& entries = ComponentRegistry::GetEntries(); \
309 auto it = entries.find(typeid(ThisType)); \
310 if (it != entries.end()) { \
311 if(!it->second.editorIconPath.empty()) { \
312 return Texture::CreateFromFile(it->second.editorIconPath)->GetNativeHandle(); \
317 virtual std::type_index GetTypeIndex() const override { return typeid(ThisType); }
319#define DECLARE_BASE(BaseType) \
320using Super = BaseType; \
321inline static struct BaseType##BaseClassDeclaration { \
322 BaseType##BaseClassDeclaration() { \
323 generated_classEntry.HasBaseClass = true; \
325} generated_baseDeclaration;
331#define BEGIN_STRUCT(T) \
333 using ThisType = T; \
334 inline static struct T##StructEntry { \
336 ::Elevate::ComponentRegistry::AddClassToStack(#T); \
337 FieldStartIndex = ::Elevate::ComponentRegistry::CompilationClassFieldStack().size(); \
338 StructName = ::Elevate::ComponentRegistry::GetCleanedName(#T); \
339 StructTypeName = typeid(T).name(); \
341 size_t FieldStartIndex = 0; \
342 std::string StructName; \
343 std::string StructTypeName; \
344 std::vector<Elevate::ComponentField> StructFieldStack; \
345 } generated_structEntry; \
348#define END_STRUCT() \
350 inline static struct StructEntryEnd { \
352 auto& global = ::Elevate::ComponentRegistry::CompilationClassFieldStack(); \
353 size_t start = generated_structEntry.FieldStartIndex; \
354 for (size_t i = start; i < global.size(); ++i) { \
355 generated_structEntry.StructFieldStack.push_back(global[i]); \
357 if (start < global.size()) { \
358 global.erase(global.begin() + start, global.end()); \
360 ::Elevate::ComponentRegistry::GetCustomComponentFields()[generated_structEntry.StructTypeName] = generated_structEntry.StructFieldStack; \
362 } generated_structEntryEnd;
static std::vector< std::string > & ClassPaths()
static std::vector< std::string > & CompilationClassStack()
static void Register(const std::string &name, EECategory category, std::vector< FieldOption > &options)
static void PopClassStack()
static auto GetParentFieldsIfPossible(const T *obj) -> std::vector< ComponentField >
static std::unordered_map< std::type_index, Entry > & GetEntries()
static std::map< std::string, std::vector< ComponentField > > & GetCustomComponentFields()
static std::string GetCleanedName(std::string rawName)
static constexpr EngineDataType DeduceEngineDataType()
static void AddClassToStack(std::string newClass)
static void AddProperty(FieldType Class::*member, const std::string &name, std::initializer_list< FieldOption > options)
static std::string GetName(const std::type_info &type)
static std::vector< ComponentField > & CompilationClassFieldStack()
std::variant< HideInInspectorTag, EditorIconTag, FlattenTag, DisplayNameTag, TooltipTag, ReadOnlyTag, ColorTag > FieldOption
std::function< Component *(std::weak_ptr< GameObject >)> GameObjectComponentFactory
std::function< Component *(std::weak_ptr< GameObject >)> GameObjectComponentGetter
std::function< void(std::weak_ptr< GameObject >)> GameObjectComponentDestructor
GameObjectComponentGetter getter
GameObjectComponentDestructor destructor
GameObjectComponentFactory factory
std::string editorIconPath
static constexpr EngineDataType value
static std::vector< ComponentField > Get()
static std::vector< ComponentField > Get()