BsRTTIType.h 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. #pragma once
  2. #include <string>
  3. #include <algorithm>
  4. #include <unordered_map>
  5. #include "BsPrerequisitesUtil.h"
  6. #include "BsManagedDataBlock.h"
  7. #include "BsRTTIField.h"
  8. #include "BsRTTIPlainField.h"
  9. #include "BsRTTIReflectableField.h"
  10. #include "BsRTTIReflectablePtrField.h"
  11. #include "BsRTTIManagedDataBlockField.h"
  12. #include "BsIReflectable.h"
  13. #include "BsBinaryDiff.h"
  14. /** @addtogroup RTTI
  15. * @{
  16. */
  17. namespace BansheeEngine
  18. {
  19. #define BS_PLAIN_MEMBER(name) \
  20. decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; } \
  21. void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; }
  22. #define BS_REFL_MEMBER(name) \
  23. decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; } \
  24. void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; }
  25. #define BS_REFLPTR_MEMBER(name) \
  26. decltype(OwnerType::##name) get##name(OwnerType* obj) { return obj->##name; } \
  27. void set##name(OwnerType* obj, decltype(OwnerType::##name) val) { obj->##name = val; }
  28. #define BS_ADD_PLAIN_FIELD(name, id) \
  29. addPlainField(#name, id##, &MyType::get##name, &MyType::set##name);
  30. #define BS_ADD_REFL_FIELD(name, id) \
  31. addReflectableField(#name, id##, &MyType::get##name, &MyType::set##name);
  32. #define BS_ADD_REFLPTR_FIELD(name, id) \
  33. addReflectablePtrField(#name, id##, &MyType::get##name, &MyType::set##name);
  34. #define BS_PLAIN_MEMBER_VEC(name) \
  35. std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; } \
  36. void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; } \
  37. UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); } \
  38. void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
  39. #define BS_REFL_MEMBER_VEC(name) \
  40. std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; } \
  41. void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; } \
  42. UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); } \
  43. void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
  44. #define BS_REFLPTR_MEMBER_VEC(name) \
  45. std::common_type<decltype(OwnerType::##name)>::type::value_type get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; } \
  46. void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type val) { obj->##name[idx] = val; } \
  47. UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); } \
  48. void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
  49. #define BS_ADD_PLAIN_FIELD_ARR(name, id) \
  50. addPlainArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
  51. &MyType::set##name, &MyType::setSize##name);
  52. #define BS_ADD_REFL_FIELD_ARR(name, id) \
  53. addReflectableArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
  54. &MyType::set##name, &MyType::setSize##name);
  55. #define BS_ADD_REFLPTR_FIELD_ARR(name, id) \
  56. addReflectablePtrArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
  57. &MyType::set##name, &MyType::setSize##name);
  58. /** @cond INTERNAL */
  59. /**
  60. * Provides an interface for accessing fields of a certain class.
  61. * Data can be easily accessed by getter and setter methods.
  62. *
  63. * Supported data types:
  64. * - Plain types - All types defined in BsRTTIField.h, mostly native types and POD (plain old data) structs. Data is parsed byte by byte.
  65. * No pointers to plain types are supported. Data is passed around by value.
  66. * - Reflectable types - Any class deriving from IReflectable. Data is parsed based on fields in its RTTI class. Can be pointer or value type.
  67. * - Arrays of both plain and reflectable types are supported
  68. * - Data blocks - A managed or unmanaged block of data. See ManagedDataBlock.
  69. */
  70. class BS_UTILITY_EXPORT RTTITypeBase
  71. {
  72. public:
  73. RTTITypeBase();
  74. virtual ~RTTITypeBase();
  75. /** Returns RTTI type information for all classes that derive from the class that owns this RTTI type. */
  76. virtual Vector<RTTITypeBase*>& getDerivedClasses() = 0;
  77. /**
  78. * Returns RTTI type information for the class that owns this RTTI type. If the class has not base type, null is
  79. * returned instead.
  80. */
  81. virtual RTTITypeBase* getBaseClass() = 0;
  82. /** Returns true if current RTTI class is derived from @p base. (Or if it is the same type as base) */
  83. virtual bool isDerivedFrom(RTTITypeBase* base) = 0;
  84. /**
  85. * Called by the RTTI system when a class is first found in order to form child/parent class hierarchy.
  86. *
  87. * @note Internal method.
  88. */
  89. virtual void _registerDerivedClass(RTTITypeBase* derivedClass) = 0;
  90. /** Creates a new instance of the class owning this RTTI type. */
  91. virtual std::shared_ptr<IReflectable> newRTTIObject() = 0;
  92. /** Returns the name of the class owning this RTTI type. */
  93. virtual const String& getRTTIName() = 0;
  94. /** Returns an RTTI id that uniquely represents each class in the RTTI system. */
  95. virtual UINT32 getRTTIId() = 0;
  96. /**
  97. * Called by the serializers when serialization for this object has started. Use this to do any preprocessing on
  98. * data you might need during serialization itself.
  99. */
  100. virtual void onSerializationStarted(IReflectable* obj) {}
  101. /**
  102. * Called by the serializers when serialization for this object has ended. After serialization has ended you can
  103. * be sure that the type has been fully serialized, and you may clean up any temporary data.
  104. */
  105. virtual void onSerializationEnded(IReflectable* obj) {}
  106. /**
  107. * Called by the serializers when deserialization for this object has started. Use this to do any preprocessing
  108. * on data you might need during deserialization itself.
  109. */
  110. virtual void onDeserializationStarted(IReflectable* obj) {}
  111. /**
  112. * Called by the serializers when deserialization for this object has ended. At this point you can be sure the
  113. * instance has been fully deserialized and you may safely use it.
  114. *
  115. * One exception being are fields you marked with RTTI_Flag_WeakRef, as they might be resolved only after
  116. * deserialization has fully completed for all objects.
  117. */
  118. virtual void onDeserializationEnded(IReflectable* obj) {}
  119. /**
  120. * Returns a handler that determines how are "diffs" generated and applied when it comes to objects of this RTTI
  121. * type. A "diff" is a list of differences between two objects that may be saved, viewed or applied to another
  122. * object to transform it.
  123. */
  124. virtual IDiff& getDiffHandler() const
  125. {
  126. static BinaryDiff diffHandler;
  127. return diffHandler;
  128. }
  129. /**
  130. * Allows you to assign a value to a plain field with the specified name on the provided instance.
  131. *
  132. * @note Caller must ensure instance and value types are valid for this field.
  133. */
  134. template <class ObjectType, class DataType>
  135. void setPlainValue(ObjectType* object, const String& name, DataType& value)
  136. {
  137. RTTIField* genericField = findField(name);
  138. genericField->checkIsPlain(false);
  139. RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
  140. UINT32 typeSize = 0;
  141. if(RTTIPlainType<DataType>::hasDynamicSize)
  142. typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
  143. else
  144. typeSize = sizeof(DataType);
  145. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  146. RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
  147. field->fromBuffer(object, tempBuffer);
  148. bs_stack_free(tempBuffer);
  149. }
  150. /**
  151. * Allows you to assign a value to a plain field array element with the specified name and index on the provided instance.
  152. *
  153. * @note Caller must ensure instance and value types are valid for this field.
  154. */
  155. template <class ObjectType, class DataType>
  156. void setPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
  157. {
  158. RTTIField* genericField = findField(name);
  159. genericField->checkIsPlain(true);
  160. RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
  161. UINT32 typeSize = 0;
  162. if(RTTIPlainType<DataType>::hasDynamicSize)
  163. typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
  164. else
  165. typeSize = sizeof(DataType);
  166. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  167. RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
  168. field->arrayElemFromBuffer(object, index, tempBuffer);
  169. bs_stack_free(tempBuffer);
  170. }
  171. /**
  172. * Allows you to assign a value to a reflectable field with the specified name on the provided instance.
  173. *
  174. * @note Caller must ensure instance and value types are valid for this field.
  175. */
  176. template <class ObjectType, class DataType>
  177. void setReflectableValue(ObjectType* object, const String& name, DataType& value)
  178. {
  179. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  180. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  181. RTTIField* genericField = findField(name);
  182. genericField->checkIsComplex(false);
  183. RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
  184. field->setValue(object, value);
  185. }
  186. /**
  187. * Allows you to assign a value to a reflectable field array element with the specified name and index on the
  188. * provided instance.
  189. *
  190. * @note Caller must ensure instance and value types are valid for this field.
  191. */
  192. template <class ObjectType, class DataType>
  193. void setReflectableArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
  194. {
  195. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  196. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  197. RTTIField* genericField = findField(name);
  198. genericField->checkIsComplex(true);
  199. RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
  200. field->setArrayValue(object, index, value);
  201. }
  202. /**
  203. * Allows you to assign a value to a managed data block field with the specified name on the provided instance.
  204. *
  205. * @note Caller must ensure instance type is valid for this field.
  206. */
  207. template <class ObjectType>
  208. void setDataBlockValue(ObjectType* object, const String& name, ManagedDataBlock value)
  209. {
  210. RTTIField* genericField = findField(name);
  211. genericField->checkIsDataBlock();
  212. RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
  213. field->setValue(object, value);
  214. }
  215. /**
  216. * Allows you to assign a value to a reflectable pointer field with the specified name on the provided instance.
  217. *
  218. * @note Caller must ensure instance and value types are valid for this field.
  219. */
  220. template <class ObjectType, class DataType>
  221. void setReflectablePtrValue(ObjectType* object, const String& name, std::shared_ptr<DataType> value)
  222. {
  223. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  224. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  225. RTTIField* genericField = findField(name);
  226. genericField->checkIsComplexPtr(false);
  227. RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
  228. field->setValue(object, value);
  229. }
  230. /**
  231. * Allows you to assign a value to a reflectable pointer field array element with the specified name and index on
  232. * the provided instance.
  233. *
  234. * @note Caller must ensure instance and value types are valid for this field.
  235. */
  236. template <class ObjectType, class DataType>
  237. void setReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index, std::shared_ptr<DataType> value)
  238. {
  239. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  240. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  241. RTTIField* genericField = findField(name);
  242. genericField->checkIsComplexPtr(true);
  243. RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
  244. field->setArrayValue(object, index, value);
  245. }
  246. /**
  247. * Reads a value from a plain field with the specified name from the provided instance.
  248. *
  249. * @note Caller must ensure instance and value types are valid for this field.
  250. */
  251. template <class ObjectType, class DataType>
  252. void getPlainValue(ObjectType* object, const String& name, DataType& value)
  253. {
  254. RTTIField* genericField = findField(name);
  255. genericField->checkIsPlain(false);
  256. RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
  257. UINT32 typeSize = 0;
  258. if(field->hasDynamicSize())
  259. typeSize = field->getDynamicSize(object);
  260. else
  261. typeSize = field->getTypeSize();
  262. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  263. field->toBuffer(object, tempBuffer);
  264. RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
  265. bs_stack_free(tempBuffer);
  266. }
  267. /**
  268. * Reads a value from a plain array field with the specified name and index from the provided instance.
  269. *
  270. * @note Caller must ensure instance and value types are valid for this field.
  271. */
  272. template <class ObjectType, class DataType>
  273. void getPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
  274. {
  275. RTTIField* genericField = findField(name);
  276. genericField->checkIsPlain(true);
  277. RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
  278. UINT32 typeSize = 0;
  279. if(field->hasDynamicSize())
  280. typeSize = field->getArrayElemDynamicSize(object, arrIdx);
  281. else
  282. typeSize = field->getTypeSize();
  283. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  284. field->arrayElemToBuffer(object, index, tempBuffer);
  285. RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
  286. bs_stack_free(tempBuffer);
  287. }
  288. /**
  289. * Reads a value from a reflectable object field with the specified name from the provided instance.
  290. *
  291. * @note Caller must ensure instance and value types are valid for this field.
  292. */
  293. template <class ObjectType>
  294. IReflectable& getReflectableValue(ObjectType* object, const String& name)
  295. {
  296. RTTIField* genericField = findField(name);
  297. genericField->checkIsComplex(false);
  298. RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
  299. return field->getValue(object);
  300. }
  301. /**
  302. * Reads a value from a reflectable object array field with the specified name and index from the provided instance.
  303. *
  304. * @note Caller must ensure instance and value types are valid for this field.
  305. */
  306. template <class ObjectType>
  307. IReflectable& getReflectableArrayValue(ObjectType* object, const String& name, UINT32 index)
  308. {
  309. RTTIField* genericField = findField(name);
  310. genericField->checkIsComplex(true);
  311. RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
  312. return field->getArrayValue(object, index);
  313. }
  314. /**
  315. * Reads a managed data block field with the specified name from the provided instance.
  316. *
  317. * @note Caller must ensure instance type is valid for this field.
  318. */
  319. template <class ObjectType>
  320. ManagedDataBlock getDataBlockValue(ObjectType* object, const String& name)
  321. {
  322. RTTIField* genericField = findField(name);
  323. genericField->checkIsDataBlock();
  324. RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
  325. return field->getValue(object);
  326. }
  327. /**
  328. * Reads a value from a reflectable object pointer field with the specified name from the provided instance.
  329. *
  330. * @note Caller must ensure instance and value types are valid for this field.
  331. */
  332. template <class ObjectType>
  333. std::shared_ptr<IReflectable> getReflectablePtrValue(ObjectType* object, const String& name)
  334. {
  335. RTTIField* genericField = findField(name);
  336. genericField->checkIsComplexPtr(false);
  337. RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
  338. return field->getValue(object);
  339. }
  340. /**
  341. * Reads a value from a reflectable pointer array field with the specified name and index from the provided instance.
  342. *
  343. * @note Caller must ensure instance and value types are valid for this field.
  344. */
  345. template <class ObjectType>
  346. std::shared_ptr<IReflectable> getReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index)
  347. {
  348. RTTIField* genericField = findField(name);
  349. genericField->checkIsComplexPtr(true);
  350. RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
  351. return field->getArrayValue(object, index);
  352. }
  353. /**
  354. * Returns the size of the array of the field with the specified name on the provided instance.
  355. *
  356. * @note Caller must ensure instance type is valid and that the field as an array.
  357. */
  358. template <class ObjectType>
  359. UINT32 getArraySize(ObjectType* object, const String& name)
  360. {
  361. RTTIField* field = findField(name);
  362. return field->getArraySize(object);
  363. }
  364. /**
  365. * Sets the size of the array of the field with the specified name on the provided instance.
  366. *
  367. * @note
  368. * Caller must ensure instance type is valid and that the field as an array. This might clear any existing data
  369. * from the array.
  370. */
  371. template <class ObjectType>
  372. void setArraySize(ObjectType* object, const String& name, UINT32 size)
  373. {
  374. RTTIField* field = findField(name);
  375. field->setArraySize(object, size);
  376. }
  377. /** Returns the total number of fields in this RTTI type. */
  378. UINT32 getNumFields() const { return (UINT32)mFields.size(); }
  379. /** Returns a field based on the field index. Use getNumFields() to get total number of fields available. */
  380. RTTIField* getField(UINT32 idx) { return mFields.at(idx); }
  381. /**
  382. * Tries to find a field with the specified name. Throws an exception if it can't.
  383. *
  384. * @param name The name of the field.
  385. */
  386. RTTIField* findField(const String& name);
  387. /**
  388. * Tries to find a field with the specified unique ID. Doesn't throw an exception if it can't find the field
  389. * (Unlike findField(const String&)).
  390. *
  391. * @param uniqueFieldId Unique identifier for the field.
  392. *
  393. * @return nullptr if it can't find the field.
  394. */
  395. RTTIField* findField(int uniqueFieldId);
  396. protected:
  397. /**
  398. * Tries to add a new field to the fields array, and throws an exception if a field with the same name or id
  399. * already exists.
  400. *
  401. * @param[in] field Field, must be non-null.
  402. */
  403. void addNewField(RTTIField* field);
  404. private:
  405. Vector<RTTIField*> mFields;
  406. };
  407. /** Used for initializing a certain type as soon as the program is loaded. */
  408. template<typename Type, typename BaseType>
  409. struct InitRTTIOnStart
  410. {
  411. public:
  412. InitRTTIOnStart()
  413. {
  414. BaseType::getRTTIStatic()->_registerDerivedClass(Type::getRTTIStatic());
  415. }
  416. void makeSureIAmInstantiated() { }
  417. };
  418. /** Specialization for root class of RTTI hierarchy - IReflectable */
  419. template<typename Type>
  420. struct InitRTTIOnStart<Type, IReflectable>
  421. {
  422. public:
  423. InitRTTIOnStart()
  424. {
  425. IReflectable::_registerDerivedClass(Type::getRTTIStatic());
  426. }
  427. void makeSureIAmInstantiated() { }
  428. };
  429. /**
  430. * Template that returns RTTI type of the specified type, unless the specified type is IReflectable in which case it
  431. * returns a null.
  432. */
  433. template<typename Type>
  434. struct GetRTTIType
  435. {
  436. RTTITypeBase* operator()() { return Type::getRTTIStatic(); }
  437. };
  438. /** Specialization for root class of RTTI hierarchy - IReflectable. */
  439. template<>
  440. struct GetRTTIType<IReflectable>
  441. {
  442. RTTITypeBase* operator()() { return nullptr; }
  443. };
  444. /** @endcond */
  445. /**
  446. * Allows you to provide a run-time type information for a specific class, along with support for
  447. * serialization/deserialization.
  448. *
  449. * Derive from this class and return the that class from IReflectable::getRTTI. This way you can separate serialization
  450. * logic from the actual class you're serializing.
  451. *
  452. * This class will provide a way to register individual fields in the class, together with ways to read and write them,
  453. * as well a providing information about class hierarchy, and run-time type checking.
  454. */
  455. template <typename Type, typename BaseType, typename MyRTTIType>
  456. class RTTIType : public RTTITypeBase
  457. {
  458. protected:
  459. /************************************************************************/
  460. /* RTTI CLASS META DATA */
  461. /************************************************************************/
  462. static InitRTTIOnStart<Type, BaseType> initOnStart;
  463. public:
  464. RTTIType()
  465. {
  466. // Compiler will only generate code for stuff that is directly used, including static data members,
  467. // so we fool it here like we're using the class directly. Otherwise compiler won't generate the code for the member
  468. // and our type won't get initialized on start (Actual behavior is a bit more random)
  469. initOnStart.makeSureIAmInstantiated();
  470. }
  471. virtual ~RTTIType() {}
  472. /** Returns a singleton of this RTTI type. */
  473. static MyRTTIType* instance()
  474. {
  475. static MyRTTIType inst;
  476. return &inst;
  477. }
  478. /** @copydoc RTTITypeBase::getDerivedClasses */
  479. Vector<RTTITypeBase*>& getDerivedClasses() override
  480. {
  481. static Vector<RTTITypeBase*> mRTTIDerivedClasses;
  482. return mRTTIDerivedClasses;
  483. }
  484. /** @copydoc RTTITypeBase::getBaseClass */
  485. RTTITypeBase* getBaseClass() override
  486. {
  487. return GetRTTIType<BaseType>()();
  488. }
  489. /** @copydoc RTTITypeBase::isDerivedFrom */
  490. bool isDerivedFrom(RTTITypeBase* base) override
  491. {
  492. assert(base != nullptr);
  493. Stack<RTTITypeBase*> todo;
  494. todo.push(base);
  495. while (!todo.empty())
  496. {
  497. RTTITypeBase* currentType = todo.top();
  498. todo.pop();
  499. if (currentType->getRTTIId() == getRTTIId())
  500. return true;
  501. const Vector<RTTITypeBase*>& derivedClasses = currentType->getDerivedClasses();
  502. for (auto iter = derivedClasses.begin(); iter != derivedClasses.end(); ++iter)
  503. todo.push(*iter);
  504. }
  505. return false;
  506. }
  507. /** @copydoc RTTITypeBase::_registerDerivedClass */
  508. void _registerDerivedClass(RTTITypeBase* derivedClass) override
  509. {
  510. if(IReflectable::_isTypeIdDuplicate(derivedClass->getRTTIId()))
  511. {
  512. BS_EXCEPT(InternalErrorException, "RTTI type \"" + derivedClass->getRTTIName() +
  513. "\" has a duplicate ID: " + toString(derivedClass->getRTTIId()));
  514. }
  515. getDerivedClasses().push_back(derivedClass);
  516. }
  517. /************************************************************************/
  518. /* FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT */
  519. /************************************************************************/
  520. /**
  521. * Registers a new plain field. This field can then be accessed dynamically from the RTTI system and used for
  522. * automatic serialization. See RTTIField for more information about field types.
  523. *
  524. * @param[in] name Name of the field.
  525. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  526. * small data type that can be used for efficiently serializing data to disk and similar.
  527. * It is primarily used for compatibility between different versions of serialized data.
  528. * @param[in] getter Method used for retrieving the value of this field.
  529. * @param[in] setter Method used for setting the value of this field.
  530. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  531. */
  532. template<class ObjectType, class DataType>
  533. void addPlainField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(),
  534. void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
  535. {
  536. addPlainField<ObjectType, DataType>(name, uniqueId,
  537. std::function<DataType&(ObjectType*)>(getter),
  538. std::function<void(ObjectType*, DataType&)>(setter), flags);
  539. }
  540. /**
  541. * Registers a new reflectable object field. This field can then be accessed dynamically from the RTTI system and
  542. * used for automatic serialization. See RTTIField for more information about field types.
  543. *
  544. * @param[in] name Name of the field.
  545. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  546. * small data type that can be used for efficiently serializing data to disk and similar.
  547. * It is primarily used for compatibility between different versions of serialized data.
  548. * @param[in] getter Method used for retrieving the value of this field.
  549. * @param[in] setter Method used for setting the value of this field.
  550. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  551. */
  552. template<class ObjectType, class DataType>
  553. void addReflectableField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(),
  554. void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
  555. {
  556. addReflectableField<ObjectType, DataType>(name, uniqueId,
  557. std::function<DataType&(ObjectType*)>(getter),
  558. std::function<void(ObjectType*, DataType&)>(setter), flags);
  559. }
  560. /**
  561. * Registers a new reflectable object pointer field. This field can then be accessed dynamically from the RTTI
  562. * system and used for automatic serialization. See RTTIField for more information about field types.
  563. *
  564. * @param[in] name Name of the field.
  565. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  566. * small data type that can be used for efficiently serializing data to disk and similar.
  567. * It is primarily used for compatibility between different versions of serialized data.
  568. * @param[in] getter Method used for retrieving the value of this field.
  569. * @param[in] setter Method used for setting the value of this field.
  570. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  571. */
  572. template<class ObjectType, class DataType>
  573. void addReflectablePtrField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(),
  574. void (ObjectType::*setter)(std::shared_ptr<DataType>) = nullptr, UINT64 flags = 0)
  575. {
  576. addReflectablePtrField<ObjectType, DataType>(name, uniqueId,
  577. std::function<std::shared_ptr<DataType>(ObjectType*)>(getter),
  578. std::function<void(ObjectType*, std::shared_ptr<DataType>)>(setter), flags);
  579. }
  580. /**
  581. * Registers a new field containg an array of plain values. This field can then be accessed dynamically from the
  582. * RTTI system and used for automatic serialization. See RTTIField for more information about field types.
  583. *
  584. * @param[in] name Name of the field.
  585. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  586. * small data type that can be used for efficiently serializing data to disk and similar.
  587. * It is primarily used for compatibility between different versions of serialized data.
  588. * @param[in] getter Method used for retrieving a single element of the array.
  589. * @param[in] getSize Getter method that returns the size of the array.
  590. * @param[in] setter Method used for setting the a single element of the field.
  591. * @param[in] setSize Setter method that allows you to resize the array.
  592. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  593. */
  594. template<class ObjectType, class DataType>
  595. void addPlainArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(),
  596. void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
  597. {
  598. addPlainArrayField<ObjectType, DataType>(name, uniqueId,
  599. std::function<DataType&(ObjectType*, UINT32)>(getter),
  600. std::function<UINT32(ObjectType*)>(getSize),
  601. std::function<void(ObjectType*, UINT32, DataType&)>(setter),
  602. std::function<void(ObjectType*, UINT32)>(setSize), flags);
  603. }
  604. /**
  605. * Registers a new field containg an array of reflectable object values. This field can then be accessed dynamically
  606. * from the RTTI system and used for automatic serialization. See RTTIField for more information about field types.
  607. *
  608. * @param[in] name Name of the field.
  609. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  610. * small data type that can be used for efficiently serializing data to disk and similar.
  611. * It is primarily used for compatibility between different versions of serialized data.
  612. * @param[in] getter Method used for retrieving a single element of the array.
  613. * @param[in] getSize Getter method that returns the size of the array.
  614. * @param[in] setter Method used for setting the a single element of the field.
  615. * @param[in] setSize Setter method that allows you to resize the array.
  616. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  617. */
  618. template<class ObjectType, class DataType>
  619. void addReflectableArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(),
  620. void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
  621. {
  622. addReflectableArrayField<ObjectType, DataType>(name, uniqueId,
  623. std::function<DataType&(ObjectType*, UINT32)>(getter),
  624. std::function<UINT32(ObjectType*)>(getSize),
  625. std::function<void(ObjectType*, UINT32, DataType&)>(setter),
  626. std::function<void(ObjectType*, UINT32)>(setSize), flags);
  627. }
  628. /**
  629. * Registers a new field containg an array of reflectable obejct pointers. This field can then be accessed
  630. * dynamically from the RTTI system and used for automatic serialization. See RTTIField for more information
  631. * about field types.
  632. *
  633. * @param[in] name Name of the field.
  634. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  635. * small data type that can be used for efficiently serializing data to disk and similar.
  636. * It is primarily used for compatibility between different versions of serialized data.
  637. * @param[in] getter Method used for retrieving a single element of the array.
  638. * @param[in] getSize Getter method that returns the size of the array.
  639. * @param[in] setter Method used for setting the a single element of the field.
  640. * @param[in] setSize Setter method that allows you to resize the array.
  641. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  642. */
  643. template<class ObjectType, class DataType>
  644. void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(),
  645. void (ObjectType::*setter)(UINT32, std::shared_ptr<DataType>) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
  646. {
  647. addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId,
  648. std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(getter),
  649. std::function<UINT32(ObjectType*)>(getSize),
  650. std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(setter),
  651. std::function<void(ObjectType*, UINT32)>(setSize), flags);
  652. }
  653. /**
  654. * Registers a new managed data block field. This field can then be accessed dynamically from the RTTI system and
  655. * used for automatic serialization. See RTTIField for more information about field types.
  656. *
  657. * @param[in] name Name of the field.
  658. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  659. * small data type that can be used for efficiently serializing data to disk and similar.
  660. * It is primarily used for compatibility between different versions of serialized data.
  661. * @param[in] getter Method used for retrieving the value of this field.
  662. * @param[in] setter Method used for setting the value of this field.
  663. * @param[in] flags Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
  664. */
  665. template<class ObjectType>
  666. void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (ObjectType::*getter)(),
  667. void (ObjectType::*setter)(ManagedDataBlock) = nullptr, UINT64 flags = 0, UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
  668. {
  669. addDataBlockField<ObjectType>(name, uniqueId,
  670. std::function<ManagedDataBlock(ObjectType*)>(getter),
  671. std::function<void(ObjectType*, ManagedDataBlock)>(setter), flags, customAllocator);
  672. }
  673. protected:
  674. typedef Type OwnerType;
  675. typedef MyRTTIType MyType;
  676. virtual void initSerializableFields() {}
  677. /************************************************************************/
  678. /* FIELDS OPERATING ON DERIVED SERIALIZATION INTERFACE */
  679. /* (Needs an extra pointer to the actual object) */
  680. /************************************************************************/
  681. template<class InterfaceType, class ObjectType, class DataType>
  682. void addPlainField(const String& name, UINT32 uniqueId,
  683. DataType& (InterfaceType::*getter)(ObjectType*),
  684. void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
  685. {
  686. using namespace std::placeholders;
  687. static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value),
  688. "Class with the get/set methods must derive from BansheeEngine::RTTIType.");
  689. static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  690. "Data type derives from IReflectable but it is being added as a plain field.");
  691. addPlainField<ObjectType, DataType>(name, uniqueId,
  692. std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),
  693. std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
  694. }
  695. template<class InterfaceType, class ObjectType, class DataType>
  696. void addReflectableField(const String& name, UINT32 uniqueId,
  697. DataType& (InterfaceType::*getter)(ObjectType*),
  698. void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
  699. {
  700. using namespace std::placeholders;
  701. addReflectableField<ObjectType, DataType>(name, uniqueId,
  702. std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),
  703. std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
  704. }
  705. template<class InterfaceType, class ObjectType, class DataType>
  706. void addReflectablePtrField(const String& name, UINT32 uniqueId,
  707. std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*),
  708. void (InterfaceType::*setter)(ObjectType*, std::shared_ptr<DataType>), UINT64 flags = 0)
  709. {
  710. using namespace std::placeholders;
  711. addReflectablePtrField<ObjectType, DataType>(name, uniqueId,
  712. std::function<std::shared_ptr<DataType>(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),
  713. std::function<void(ObjectType*, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
  714. }
  715. template<class InterfaceType, class ObjectType, class DataType>
  716. void addPlainArrayField(const String& name, UINT32 uniqueId,
  717. DataType& (InterfaceType::*getter)(ObjectType*, UINT32),
  718. UINT32 (InterfaceType::*getSize)(ObjectType*),
  719. void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&),
  720. void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
  721. {
  722. using namespace std::placeholders;
  723. static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value),
  724. "Class with the get/set methods must derive from BansheeEngine::RTTIType.");
  725. static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  726. "Data type derives from IReflectable but it is being added as a plain field.");
  727. addPlainArrayField<ObjectType, DataType>(name, uniqueId,
  728. std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)),
  729. std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)),
  730. std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)),
  731. std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
  732. }
  733. template<class InterfaceType, class ObjectType, class DataType>
  734. void addReflectableArrayField(const String& name, UINT32 uniqueId,
  735. DataType& (InterfaceType::*getter)(ObjectType*, UINT32),
  736. UINT32 (InterfaceType::*getSize)(ObjectType*),
  737. void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&),
  738. void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
  739. {
  740. using namespace std::placeholders;
  741. addReflectableArrayField<ObjectType, DataType>(name, uniqueId,
  742. std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)),
  743. std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)),
  744. std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)),
  745. std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
  746. }
  747. template<class InterfaceType, class ObjectType, class DataType>
  748. void addReflectablePtrArrayField(const String& name, UINT32 uniqueId,
  749. std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*, UINT32),
  750. UINT32 (InterfaceType::*getSize)(ObjectType*),
  751. void (InterfaceType::*setter)(ObjectType*, UINT32, std::shared_ptr<DataType>),
  752. void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
  753. {
  754. using namespace std::placeholders;
  755. addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId,
  756. std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)),
  757. std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)),
  758. std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)),
  759. std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
  760. }
  761. template<class InterfaceType, class ObjectType>
  762. void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (InterfaceType::*getter)(ObjectType*),
  763. void (InterfaceType::*setter)(ObjectType*, ManagedDataBlock), UINT64 flags = 0,
  764. UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
  765. {
  766. using namespace std::placeholders;
  767. if(customAllocator != 0)
  768. {
  769. std::function<UINT8*(ObjectType*, UINT32)> customAllocFunc = std::bind(customAllocator, _1, _2);
  770. addDataBlockField<ObjectType>(name, uniqueId,
  771. std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),
  772. std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags,
  773. customAllocFunc);
  774. }
  775. else
  776. {
  777. addDataBlockField<ObjectType>(name, uniqueId,
  778. std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),
  779. std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
  780. }
  781. }
  782. private:
  783. template<class ObjectType, class DataType>
  784. void addPlainField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
  785. {
  786. RTTIPlainField<DataType, ObjectType>* newField =
  787. bs_new<RTTIPlainField<DataType, ObjectType>>();
  788. newField->initSingle(name, uniqueId, getter, setter, flags);
  789. addNewField(newField);
  790. }
  791. template<class ObjectType, class DataType>
  792. void addReflectableField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
  793. {
  794. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  795. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  796. RTTIReflectableField<DataType, ObjectType>* newField =
  797. bs_new<RTTIReflectableField<DataType, ObjectType>>();
  798. newField->initSingle(name, uniqueId, getter, setter, flags);
  799. addNewField(newField);
  800. }
  801. template<class ObjectType, class DataType>
  802. void addReflectablePtrField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
  803. {
  804. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  805. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  806. RTTIReflectablePtrField<DataType, ObjectType>* newField =
  807. bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
  808. newField->initSingle(name, uniqueId, getter, setter, flags);
  809. addNewField(newField);
  810. }
  811. template<class ObjectType, class DataType>
  812. void addPlainArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
  813. Any setter, Any setSize, UINT64 flags)
  814. {
  815. RTTIPlainField<DataType, ObjectType>* newField =
  816. bs_new<RTTIPlainField<DataType, ObjectType>>();
  817. newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
  818. addNewField(newField);
  819. }
  820. template<class ObjectType, class DataType>
  821. void addReflectableArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
  822. Any setter, Any setSize, UINT64 flags)
  823. {
  824. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  825. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  826. RTTIReflectableField<DataType, ObjectType>* newField =
  827. bs_new<RTTIReflectableField<DataType, ObjectType>>();
  828. newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
  829. addNewField(newField);
  830. }
  831. template<class ObjectType, class DataType>
  832. void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
  833. Any setter, Any setSize, UINT64 flags)
  834. {
  835. static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value),
  836. "Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
  837. RTTIReflectablePtrField<DataType, ObjectType>* newField =
  838. bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
  839. newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
  840. addNewField(newField);
  841. }
  842. template<class ObjectType>
  843. void addDataBlockField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags,
  844. Any customAllocator = Any())
  845. {
  846. RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>* newField =
  847. bs_new<RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>>();
  848. newField->initSingle(name, uniqueId, getter, setter, flags, customAllocator);
  849. addNewField(newField);
  850. }
  851. };
  852. template <typename Type, typename BaseType, typename MyRTTIType>
  853. InitRTTIOnStart<Type, BaseType> RTTIType<Type, BaseType, MyRTTIType>::initOnStart;
  854. /** Returns true if the provided object can be safely cast into type T. */
  855. template<class T>
  856. bool rtti_is_of_type(IReflectable* object)
  857. {
  858. static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value),
  859. "Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
  860. return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
  861. }
  862. /** Returns true if the provided object can be safely cast into type T. */
  863. template<class T>
  864. bool rtti_is_of_type(std::shared_ptr<IReflectable> object)
  865. {
  866. static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value),
  867. "Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
  868. return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
  869. }
  870. /** Creates a new object just from its type ID. */
  871. std::shared_ptr<IReflectable> rtti_create(UINT32 rttiId);
  872. /** Checks is the current object a subclass of some type. */
  873. template<class T>
  874. bool rtti_is_subclass(IReflectable* object)
  875. {
  876. static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value),
  877. "Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
  878. return object->isDerivedFrom(T::getRTTIStatic());
  879. }
  880. /** @} */
  881. }