BsRTTIType.h 41 KB

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