ezEngine  Milestone 9
RTTI.h
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <Foundation/Basics.h>
9 
10 
11 // *****************************************
12 // ***** Runtime Type Information Data *****
13 
14 struct ezRTTIAllocator;
15 class ezAbstractProperty;
18 struct ezMessageSenderInfo;
20 class ezMessage;
21 typedef ezUInt16 ezMessageId;
22 
30 class EZ_FOUNDATION_DLL ezRTTI : public ezEnumerable<ezRTTI>
31 {
33 
34 public:
36  ezRTTI(const char* szName, const ezRTTI* pParentType, ezUInt32 uiTypeSize, ezUInt32 uiTypeVersion, ezUInt32 uiVariantType,
40  const ezRTTI* (*fnVerifyParent)());
41 
42 
43  ~ezRTTI();
44 
46  void VerifyCorrectness() const;
47 
49  static void VerifyCorrectnessForAllTypes();
50 
52  EZ_ALWAYS_INLINE const char* GetTypeName() const { return m_szTypeName; } // [tested]
53 
55  EZ_ALWAYS_INLINE ezUInt32 GetTypeNameHash() const { return m_uiTypeNameHash; } // [tested]
56 
58  EZ_ALWAYS_INLINE const ezRTTI* GetParentType() const { return m_pParentType; } // [tested]
59 
61  EZ_ALWAYS_INLINE ezVariant::Type::Enum GetVariantType() const { return static_cast<ezVariant::Type::Enum>(m_uiVariantType); }
62 
64  bool IsDerivedFrom(const ezRTTI* pBaseType) const; // [tested]
65 
67  template <typename BASE>
68  EZ_ALWAYS_INLINE bool IsDerivedFrom() const
69  {
70  return IsDerivedFrom(ezGetStaticRTTI<BASE>());
71  } // [tested]
72 
74  EZ_ALWAYS_INLINE ezRTTIAllocator* GetAllocator() const { return m_pAllocator; } // [tested]
75 
77  EZ_ALWAYS_INLINE const ezArrayPtr<ezAbstractProperty*>& GetProperties() const { return m_Properties; } // [tested]
78 
79  EZ_ALWAYS_INLINE const ezArrayPtr<ezAbstractFunctionProperty*>& GetFunctions() const { return m_Functions; }
80 
81  EZ_ALWAYS_INLINE const ezArrayPtr<ezPropertyAttribute*>& GetAttributes() const { return m_Attributes; }
82 
84  template <typename Type>
85  const Type* GetAttributeByType() const;
86 
88  void GetAllProperties(ezHybridArray<ezAbstractProperty*, 32>& out_Properties) const; // [tested]
89 
91  EZ_ALWAYS_INLINE ezUInt32 GetTypeSize() const { return m_uiTypeSize; } // [tested]
92 
94  EZ_ALWAYS_INLINE ezUInt32 GetTypeVersion() const { return m_uiTypeVersion; }
95 
97  EZ_ALWAYS_INLINE const ezBitflags<ezTypeFlags>& GetTypeFlags() const { return m_TypeFlags; } // [tested]
98 
100  static ezRTTI* FindTypeByName(const char* szName); // [tested]
101 
103  ezAbstractProperty* FindPropertyByName(const char* szName, bool bSearchBaseTypes = true) const; // [tested]
104 
106  EZ_ALWAYS_INLINE const char* GetPluginName() const { return m_szPluginName; } // [tested]
107 
109  EZ_ALWAYS_INLINE const ezArrayPtr<ezAbstractMessageHandler*>& GetMessageHandlers() const { return m_MessageHandlers; }
110 
113  bool DispatchMessage(void* pInstance, ezMessage& msg) const;
114 
117  bool DispatchMessage(const void* pInstance, ezMessage& msg) const;
118 
120  template <typename MessageType>
121  EZ_ALWAYS_INLINE bool CanHandleMessage() const
122  {
123  return CanHandleMessage(MessageType::GetTypeMsgId());
124  }
125 
127  inline bool CanHandleMessage(ezMessageId id) const
128  {
129  EZ_ASSERT_DEBUG(m_bGatheredDynamicMessageHandlers, "Message handler table should have been gathered at this point");
130 
131  const ezUInt32 uiIndex = id - m_uiMsgIdOffset;
132  return uiIndex < m_DynamicMessageHandlers.GetCount() && m_DynamicMessageHandlers[uiIndex] != nullptr;
133  }
134 
135  EZ_ALWAYS_INLINE const ezArrayPtr<ezMessageSenderInfo>& GetMessageSender() const { return m_MessageSenders; }
136 
139 
140 protected:
141  const char* m_szPluginName;
142  const char* m_szTypeName;
143  ezArrayPtr<ezAbstractProperty*> m_Properties;
146  void UpdateType(const ezRTTI* pParentType, ezUInt32 uiTypeSize, ezUInt32 uiTypeVersion, ezUInt32 uiVariantType,
148  void RegisterType(ezRTTI* pType);
149  void UnregisterType(ezRTTI* pType);
150 
151  void GatherDynamicMessageHandlers();
155  static void* GetTypeHashTable();
156 
157  const ezRTTI* m_pParentType;
158  ezRTTIAllocator* m_pAllocator;
159 
160  ezUInt32 m_uiVariantType;
161  ezUInt32 m_uiTypeSize;
162  ezUInt32 m_uiTypeVersion = 0;
163  ezUInt32 m_uiTypeNameHash = 0;
164  ezBitflags<ezTypeFlags> m_TypeFlags;
165  ezUInt32 m_uiMsgIdOffset;
166 
167  bool m_bGatheredDynamicMessageHandlers;
168  const ezRTTI* (*m_fnVerifyParent)();
169 
170  ezArrayPtr<ezAbstractMessageHandler*> m_MessageHandlers;
172  m_DynamicMessageHandlers; // do not track this data, it won't be deallocated before shutdown
173 
174  ezArrayPtr<ezMessageSenderInfo> m_MessageSenders;
175 
176 private:
177  EZ_MAKE_SUBSYSTEM_STARTUP_FRIEND(Foundation, Reflection);
178 
180  static void AssignPlugin(const char* szPluginName);
181 
182  static void SanityCheckType(ezRTTI* pType);
183 
185  static void PluginEventHandler(const ezPlugin::PluginEvent& EventData);
186 };
187 
188 
189 // ***********************************
190 // ***** Object Allocator Struct *****
191 
192 
194 struct EZ_FOUNDATION_DLL ezRTTIAllocator
195 {
197  virtual bool CanAllocate() const { return true; } // [tested]
198 
200  template <typename T>
202  {
203  return AllocateInternal(pAllocator).Cast<T>();
204  }
205 
207  template <typename T>
208  ezInternal::NewInstance<T> Clone(const void* pObject, ezAllocatorBase* pAllocator = nullptr)
209  {
210  return CloneInternal(pObject, pAllocator).Cast<T>();
211  }
212 
214  virtual void Deallocate(void* pObject, ezAllocatorBase* pAllocator = nullptr) = 0; // [tested]
215 
216 private:
217  virtual ezInternal::NewInstance<void> AllocateInternal(ezAllocatorBase* pAllocator) = 0;
218  virtual ezInternal::NewInstance<void> CloneInternal(const void* pObject, ezAllocatorBase* pAllocator)
219  {
220  EZ_REPORT_FAILURE("Cloning is not supported by this allocator.");
221  return ezInternal::NewInstance<void>(nullptr, pAllocator);
222  }
223 };
224 
226 struct EZ_FOUNDATION_DLL ezRTTINoAllocator : public ezRTTIAllocator
227 {
229  virtual bool CanAllocate() const override { return false; } // [tested]
230 
232  virtual ezInternal::NewInstance<void> AllocateInternal(ezAllocatorBase* pAllocator) override // [tested]
233  {
234  EZ_REPORT_FAILURE("This function should never be called.");
235  return ezInternal::NewInstance<void>(nullptr, pAllocator);
236  }
237 
239  virtual void Deallocate(void* pObject, ezAllocatorBase* pAllocator) override // [tested]
240  {
241  EZ_REPORT_FAILURE("This function should never be called.");
242  }
243 };
244 
246 template <typename CLASS, typename AllocatorWrapper = ezDefaultAllocatorWrapper>
248 {
250  virtual ezInternal::NewInstance<void> AllocateInternal(ezAllocatorBase* pAllocator) override // [tested]
251  {
252  if (pAllocator == nullptr)
253  {
254  pAllocator = AllocatorWrapper::GetAllocator();
255  }
256 
257  return EZ_NEW(pAllocator, CLASS);
258  }
259 
261  virtual ezInternal::NewInstance<void> CloneInternal(const void* pObject, ezAllocatorBase* pAllocator) override // [tested]
262  {
263  if (pAllocator == nullptr)
264  {
265  pAllocator = AllocatorWrapper::GetAllocator();
266  }
267 
268  return CloneImpl(pObject, pAllocator, ezTraitInt<std::is_copy_constructible<CLASS>::value>());
269  }
270 
272  virtual void Deallocate(void* pObject, ezAllocatorBase* pAllocator) override // [tested]
273  {
274  if (pAllocator == nullptr)
275  {
276  pAllocator = AllocatorWrapper::GetAllocator();
277  }
278 
279  CLASS* pPointer = static_cast<CLASS*>(pObject);
280  EZ_DELETE(pAllocator, pPointer);
281  }
282 
283 private:
284  ezInternal::NewInstance<void> CloneImpl(const void* pObject, ezAllocatorBase* pAllocator, ezTraitInt<0>)
285  {
286  EZ_REPORT_FAILURE("Clone failed since the type is not copy constructible");
287  return ezInternal::NewInstance<void>(nullptr, pAllocator);
288  }
289 
290  ezInternal::NewInstance<void> CloneImpl(const void* pObject, ezAllocatorBase* pAllocator, ezTraitInt<1>)
291  {
292  return EZ_NEW(pAllocator, CLASS, *static_cast<const CLASS*>(pObject));
293  }
294 };
295 
EZ_ALWAYS_INLINE ezUInt32 GetTypeVersion() const
Returns the version number of this type.
Definition: RTTI.h:94
EZ_ALWAYS_INLINE const ezBitflags< ezTypeFlags > & GetTypeFlags() const
Returns the type flags.
Definition: RTTI.h:97
EZ_ALWAYS_INLINE bool IsDerivedFrom() const
Returns true if this type is derived from the given type.
Definition: RTTI.h:68
Base class for all memory allocators.
Definition: AllocatorBase.h:21
ezInternal::NewInstance< T > Allocate(ezAllocatorBase *pAllocator=nullptr)
Allocates one instance.
Definition: RTTI.h:201
#define EZ_DECLARE_ENUMERABLE_CLASS(self)
Insert this macro in a class that is supposed to be enumerable, and pass the class name as the parame...
Definition: EnumerableClass.h:75
Base class for all message types. Each message type has it&#39;s own id which is used to dispatch message...
Definition: Message.h:21
EZ_ALWAYS_INLINE const char * GetPluginName() const
Returns the name of the plugin which this type is declared in.
Definition: RTTI.h:106
#define EZ_ASSERT_DEBUG(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met.
Definition: Assert.h:88
Base class of all attributes can be used to decorate a RTTI property.
Definition: PropertyAttributes.h:10
#define EZ_REPORT_FAILURE(szErrorMsg,...)
Macro to report a failure when that code is reached. This will ALWAYS be executed, even in release builds, therefore might crash the application (or trigger a debug break).
Definition: Assert.h:52
Enum
This enum describes the type of data that is currently stored inside the variant. Note that changes t...
Definition: Variant.h:38
The data that is broadcast whenever a plugin is (un-) loaded.
Definition: Plugin.h:87
#define EZ_DELETE(allocator, ptr)
deletes the instance stored in ptr using the given allocator and sets ptr to nullptr ...
Definition: AllocatorBase.h:60
EZ_ALWAYS_INLINE ezUInt32 GetTypeSize() const
Returns the size (in bytes) of an instance of this type.
Definition: RTTI.h:91
Definition: HybridArray.h:79
This enumerable class holds information about reflected types. Each instance represents one type that...
Definition: RTTI.h:30
Definition: AllocatorBase_inl.h:13
Definition: Event.h:136
virtual bool CanAllocate() const
Returns whether the type that is represented by this allocator, can be dynamically allocated at runti...
Definition: RTTI.h:197
Type traits.
Definition: TypeTraits.h:9
EZ_ALWAYS_INLINE ezVariant::Type::Enum GetVariantType() const
Returns the corresponding variant type for this type or Invalid if there is none. ...
Definition: RTTI.h:61
EZ_ALWAYS_INLINE const ezRTTI * GetParentType() const
Returns the type that is the base class of this type. May be nullptr if this type has no base class...
Definition: RTTI.h:58
EZ_ALWAYS_INLINE const ezArrayPtr< ezAbstractProperty * > & GetProperties() const
Returns the array of properties that this type has. Does NOT include properties from base classes...
Definition: RTTI.h:77
EZ_ALWAYS_INLINE ezUInt32 GetTypeNameHash() const
Returns the hash of the name of this type.
Definition: RTTI.h:55
EZ_ALWAYS_INLINE ezRTTIAllocator * GetAllocator() const
Returns the object through which instances of this type can be allocated.
Definition: RTTI.h:74
Base class to add the ability to another class to enumerate all active instance of it...
Definition: EnumerableClass.h:27
EZ_ALWAYS_INLINE const ezArrayPtr< ezAbstractMessageHandler * > & GetMessageHandlers() const
Returns the array of message handlers that this type has.
Definition: RTTI.h:109
Definition: MessageHandler.h:38
The interface for an allocator that creates instances of reflected types.
Definition: RTTI.h:194
#define EZ_MAKE_SUBSYSTEM_STARTUP_FRIEND(GroupName, SubsystemName)
This inserts a friend declaration into a class, such that the given group/subsystem can access privat...
Definition: StaticSubSystem.h:107
virtual ezInternal::NewInstance< void > CloneInternal(const void *pObject, ezAllocatorBase *pAllocator) override
Clones the given instance with the given allocator.
Definition: RTTI.h:261
virtual ezInternal::NewInstance< void > AllocateInternal(ezAllocatorBase *pAllocator) override
Returns a new instance that was allocated with the given allocator.
Definition: RTTI.h:250
Dummy Allocator for types that should not be allocatable through the reflection system.
Definition: RTTI.h:226
EZ_ALWAYS_INLINE bool CanHandleMessage() const
Returns whether this type can handle the given message type.
Definition: RTTI.h:121
Default implementation of ezRTTIAllocator that allocates instances via the given allocator.
Definition: RTTI.h:247
The base class for all message handlers that a type provides.
Definition: MessageHandler.h:11
virtual void Deallocate(void *pObject, ezAllocatorBase *pAllocator) override
Deletes the given instance with the given allocator.
Definition: RTTI.h:272
EZ_ALWAYS_INLINE const char * GetTypeName() const
Returns the name of this type.
Definition: RTTI.h:52
This is the base interface for all properties in the reflection system. It provides enough informatio...
Definition: AbstractProperty.h:146
bool CanHandleMessage(ezMessageId id) const
Returns whether this type can handle the message type with the given id.
Definition: RTTI.h:127
virtual bool CanAllocate() const override
Returns false, because this type of allocator is used for classes that shall not be allocated dynamic...
Definition: RTTI.h:229
virtual ezInternal::NewInstance< void > AllocateInternal(ezAllocatorBase *pAllocator) override
Will trigger an assert.
Definition: RTTI.h:232
ezInternal::NewInstance< T > Clone(const void *pObject, ezAllocatorBase *pAllocator=nullptr)
Clones the given instance.
Definition: RTTI.h:208
The base class for a property that represents a function.
Definition: AbstractProperty.h:518
#define EZ_NEW(allocator, type,...)
creates a new instance of type using the given allocator
Definition: AllocatorBase.h:54
static ezEvent< const ezRTTI * > s_TypeUpdatedEvent
Fire this if a type was dynamically added or changed outside of plugin registration.
Definition: RTTI.h:138
virtual void Deallocate(void *pObject, ezAllocatorBase *pAllocator) override
Will trigger an assert.
Definition: RTTI.h:239
This class encapsulates an array and it&#39;s size. It is recommended to use this class instead of plain ...
Definition: ArrayPtr.h:82