BsRTTIType.h 54 KB

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