BsRTTIType.h 46 KB

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