BsRTTIType.h 52 KB

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