consoleObject.h 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  23. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  24. // Copyright (C) 2015 Faust Logic, Inc.
  25. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  26. #ifndef _CONSOLEOBJECT_H_
  27. #define _CONSOLEOBJECT_H_
  28. #ifndef _TVECTOR_H_
  29. #include "core/util/tVector.h"
  30. #endif
  31. #ifndef _STRINGTABLE_H_
  32. #include "core/stringTable.h"
  33. #endif
  34. #ifndef _STRINGFUNCTIONS_H_
  35. #include "core/strings/stringFunctions.h"
  36. #endif
  37. #ifndef _BITSET_H_
  38. #include "core/bitSet.h"
  39. #endif
  40. #ifndef _DYNAMIC_CONSOLETYPES_H_
  41. #include "console/dynamicTypes.h"
  42. #endif
  43. #ifndef _ENGINEOBJECT_H_
  44. #include "console/engineObject.h"
  45. #endif
  46. #ifndef _ENGINEFUNCTIONS_H_
  47. #include "console/engineFunctions.h"
  48. #endif
  49. #ifndef _SIMOBJECTREF_H_
  50. #include "console/simObjectRef.h"
  51. #endif
  52. #ifndef TINYXML_INCLUDED
  53. #include "tinyxml2.h"
  54. #endif
  55. /// @file
  56. /// Legacy console object system.
  57. /// @ingroup console_system Console System
  58. /// @{
  59. class Namespace;
  60. class ConsoleObject;
  61. enum NetClassTypes
  62. {
  63. NetClassTypeObject = 0,
  64. NetClassTypeDataBlock,
  65. NetClassTypeEvent,
  66. NetClassTypesCount,
  67. };
  68. enum NetClassGroups
  69. {
  70. NetClassGroupGame = 0,
  71. NetClassGroupCommunity,
  72. NetClassGroup3,
  73. NetClassGroup4,
  74. NetClassGroupsCount,
  75. };
  76. enum NetClassMasks
  77. {
  78. NetClassGroupGameMask = BIT(NetClassGroupGame),
  79. NetClassGroupCommunityMask = BIT(NetClassGroupCommunity),
  80. };
  81. enum NetDirection
  82. {
  83. NetEventDirAny,
  84. NetEventDirServerToClient,
  85. NetEventDirClientToServer,
  86. };
  87. class SimObject;
  88. class TypeValidator;
  89. class ConsoleClassObject;
  90. DECLARE_SCOPE( ConsoleAPI );
  91. //=============================================================================
  92. // AbstractClassRep.
  93. //=============================================================================
  94. /// Core functionality for class manipulation.
  95. ///
  96. /// @section AbstractClassRep_intro Introduction (or, Why AbstractClassRep?)
  97. ///
  98. /// Many of Torque's subsystems, especially network, console, and sim,
  99. /// require the ability to programatically instantiate classes. For instance,
  100. /// when objects are ghosted, the networking layer needs to be able to create
  101. /// an instance of the object on the client. When the console scripting
  102. /// language runtime encounters the "new" keyword, it has to be able to fill
  103. /// that request.
  104. ///
  105. /// Since standard C++ doesn't provide a function to create a new instance of
  106. /// an arbitrary class at runtime, one must be created. This is what
  107. /// AbstractClassRep and ConcreteClassRep are all about. They allow the registration
  108. /// and instantiation of arbitrary classes at runtime.
  109. ///
  110. /// In addition, ACR keeps track of the fields (registered via addField() and co.) of
  111. /// a class, allowing programmatic access of class fields.
  112. ///
  113. /// @see ConsoleObject
  114. ///
  115. /// @note In general, you will only access the functionality implemented in this class via
  116. /// ConsoleObject::create(). Most of the time, you will only ever need to use this part
  117. /// part of the engine indirectly - ie, you will use the networking system or the console,
  118. /// or ConsoleObject, and they will indirectly use this code. <b>The following discussion
  119. /// is really only relevant for advanced engine users.</b>
  120. ///
  121. /// @section AbstractClassRep_netstuff NetClasses and Class IDs
  122. ///
  123. /// Torque supports a notion of group, type, and direction for objects passed over
  124. /// the network. Class IDs are assigned sequentially per-group, per-type, so that, for instance,
  125. /// the IDs assigned to Datablocks are seperate from the IDs assigned to NetObjects or NetEvents.
  126. /// This can translate into significant bandwidth savings (especially since the size of the fields
  127. /// for transmitting these bits are determined at run-time based on the number of IDs given out.
  128. ///
  129. /// @section AbstractClassRep_details AbstractClassRep Internals
  130. ///
  131. /// Much like ConsoleConstructor, ACR does some preparatory work at runtime before execution
  132. /// is passed to main(). In actual fact, this preparatory work is done by the ConcreteClassRep
  133. /// template. Let's examine this more closely.
  134. ///
  135. /// If we examine ConsoleObject, we see that two macros must be used in the definition of a
  136. /// properly integrated objects. From the ConsoleObject example:
  137. ///
  138. /// @code
  139. /// // This is from inside the class definition...
  140. /// DECLARE_CONOBJECT(TorqueObject);
  141. ///
  142. /// // And this is from outside the class definition...
  143. /// IMPLEMENT_CONOBJECT(TorqueObject);
  144. /// @endcode
  145. ///
  146. /// What do these things actually do?
  147. ///
  148. /// Not all that much, in fact. They expand to code something like this:
  149. ///
  150. /// @code
  151. /// // This is from inside the class definition...
  152. /// static ConcreteClassRep<TorqueObject> dynClassRep;
  153. /// static AbstractClassRep* getParentStaticClassRep();
  154. /// static AbstractClassRep* getStaticClassRep();
  155. /// virtual AbstractClassRep* getClassRep() const;
  156. /// @endcode
  157. ///
  158. /// @code
  159. /// // And this is from outside the class definition...
  160. /// AbstractClassRep* TorqueObject::getClassRep() const { return &TorqueObject::dynClassRep; }
  161. /// AbstractClassRep* TorqueObject::getStaticClassRep() { return &dynClassRep; }
  162. /// AbstractClassRep* TorqueObject::getParentStaticClassRep() { return Parent::getStaticClassRep(); }
  163. /// ConcreteClassRep<TorqueObject> TorqueObject::dynClassRep("TorqueObject", 0, -1, 0);
  164. /// @endcode
  165. ///
  166. /// As you can see, getClassRep(), getStaticClassRep(), and getParentStaticClassRep() are just
  167. /// accessors to allow access to various ConcreteClassRep instances. This is where the Parent
  168. /// typedef comes into play as well - it lets getParentStaticClassRep() get the right
  169. /// class rep.
  170. ///
  171. /// In addition, dynClassRep is declared as a member of TorqueObject, and defined later
  172. /// on. Much like ConsoleConstructor, ConcreteClassReps add themselves to a global linked
  173. /// list in their constructor.
  174. ///
  175. /// Then, when AbstractClassRep::initialize() is called, from Con::init(), we iterate through
  176. /// the list and perform the following tasks:
  177. /// - Sets up a Namespace for each class.
  178. /// - Call the init() method on each ConcreteClassRep. This method:
  179. /// - Links namespaces between parent and child classes, using Con::classLinkNamespaces.
  180. /// - Calls initPersistFields() and consoleInit().
  181. /// - As a result of calling initPersistFields, the field list for the class is populated.
  182. /// - Assigns network IDs for classes based on their NetGroup membership. Determines
  183. /// bit allocations for network ID fields.
  184. ///
  185. /// @nosubgrouping
  186. class AbstractClassRep : public ConsoleBaseType
  187. {
  188. friend class ConsoleObject;
  189. public:
  190. typedef ConsoleBaseType Parent;
  191. /// Allows the writing of a custom TAML schema.
  192. typedef void(*WriteCustomTamlSchema)(const AbstractClassRep* pClassRep, tinyxml2::XMLElement* pParentElement);
  193. /// @name 'Tructors
  194. /// @{
  195. ///
  196. /// @param conIdPtr Pointer to the static S32 console ID.
  197. /// @param conTypeName Console type name.
  198. AbstractClassRep( S32* conIdPtr, const char* typeName )
  199. : Parent( sizeof( void* ), conIdPtr, typeName )
  200. {
  201. VECTOR_SET_ASSOCIATION( mFieldList );
  202. mCategory = StringTable->EmptyString();
  203. mClassGroupMask = 0;
  204. std::fill_n(mClassId, NetClassGroupsCount, -1);
  205. mClassName = StringTable->EmptyString();
  206. mClassSizeof = 0;
  207. mClassType = 0;
  208. mDescription = StringTable->EmptyString();
  209. #ifdef TORQUE_NET_STATS
  210. dMemset(mDirtyMaskFrequency, 0, sizeof(mDirtyMaskFrequency));
  211. dMemset(mDirtyMaskTotal, 0, sizeof(mDirtyMaskTotal));
  212. #endif
  213. mDynamicGroupExpand = false;
  214. mNamespace = NULL;
  215. mNetEventDir = 0;
  216. nextClass = NULL;
  217. parentClass = NULL;
  218. mIsRenderEnabled = true;
  219. mIsSelectionEnabled = true;
  220. }
  221. /// @}
  222. /// @name Representation Interface
  223. /// @{
  224. //TODO: move over to EngineTypeNetInfo
  225. S32 mClassGroupMask; ///< Mask indicating in which NetGroups this object belongs.
  226. S32 mClassType; ///< Stores the NetClass of this class.
  227. S32 mNetEventDir; ///< Stores the NetDirection of this class.
  228. S32 mClassId[ NetClassGroupsCount ]; ///< Stores the IDs assigned to this class for each group.
  229. S32 mClassSizeof; ///< Size of instances in bytes.
  230. //TODO: move over to EngineTypeNetInfo
  231. #ifdef TORQUE_NET_STATS
  232. struct NetStatInstance
  233. {
  234. U32 numEvents;
  235. U32 total;
  236. S32 min;
  237. S32 max;
  238. void reset()
  239. {
  240. numEvents = 0;
  241. total = 0;
  242. min = S32_MAX;
  243. max = S32_MIN;
  244. }
  245. void update(U32 amount)
  246. {
  247. numEvents++;
  248. total += amount;
  249. min = getMin((S32)amount, min);
  250. max = getMax((S32)amount, max);
  251. }
  252. NetStatInstance()
  253. {
  254. reset();
  255. }
  256. };
  257. NetStatInstance mNetStatPack;
  258. NetStatInstance mNetStatUnpack;
  259. NetStatInstance mNetStatWrite;
  260. NetStatInstance mNetStatRead;
  261. U32 mDirtyMaskFrequency[32];
  262. U32 mDirtyMaskTotal[32];
  263. void resetNetStats()
  264. {
  265. mNetStatPack.reset();
  266. mNetStatUnpack.reset();
  267. mNetStatWrite.reset();
  268. mNetStatRead.reset();
  269. for(S32 i=0; i<32; i++)
  270. {
  271. mDirtyMaskFrequency[i] = 0;
  272. mDirtyMaskTotal[i] = 0;
  273. }
  274. }
  275. void updateNetStatPack(U32 dirtyMask, U32 length)
  276. {
  277. mNetStatPack.update(length);
  278. for(S32 i=0; i<32; i++)
  279. if(BIT(i) & dirtyMask)
  280. {
  281. mDirtyMaskFrequency[i]++;
  282. mDirtyMaskTotal[i] += length;
  283. }
  284. }
  285. void updateNetStatUnpack(U32 length)
  286. {
  287. mNetStatUnpack.update(length);
  288. }
  289. void updateNetStatWriteData(U32 length)
  290. {
  291. mNetStatWrite.update(length);
  292. }
  293. void updateNetStatReadData(U32 length)
  294. {
  295. mNetStatRead.update(length);
  296. }
  297. #endif
  298. S32 getClassId (U32 netClassGroup) const { return mClassId[ netClassGroup ]; }
  299. static U32 getClassCRC (U32 netClassGroup) { return classCRC[ netClassGroup ]; }
  300. AbstractClassRep* getCommonParent( const AbstractClassRep *otherClass ) const;
  301. /// Return the name of this class.
  302. StringTableEntry getClassName() const { return mClassName; }
  303. /// Return the namespace that contains the methods of this class.
  304. Namespace* getNameSpace() const { return mNamespace; }
  305. /// Return the AbstractClassRep of the class that this class is derived from.
  306. AbstractClassRep* getParentClass() const { return parentClass; }
  307. virtual AbstractClassRep* getContainerChildClass(const bool recurse) = 0;
  308. virtual WriteCustomTamlSchema getCustomTamlSchema(void) = 0;
  309. /// Return the size of instances of this class in bytes.
  310. S32 getSizeof() const { return mClassSizeof; }
  311. /// Return the next class in the global class list link chain.
  312. AbstractClassRep* getNextClass() const { return nextClass; }
  313. /// Return the head of the global class list.
  314. static AbstractClassRep* getClassList() { return classLinkList; }
  315. /// Helper class to see if we are a given class, or a subclass thereof by
  316. /// comparing AbstractClassRep pointers.
  317. bool isSubclassOf( const AbstractClassRep* klass ) const
  318. {
  319. const AbstractClassRep *walk = this;
  320. // Walk up parents, checking for equivalence.
  321. while ( walk )
  322. {
  323. if ( walk == klass )
  324. return true;
  325. walk = walk->parentClass;
  326. };
  327. return false;
  328. }
  329. /// Helper class to see if we are a given class, or a subclass thereof by
  330. /// comparing the class name strings.
  331. bool isSubclassOf( const char *klass ) const
  332. {
  333. klass = StringTable->insert( klass );
  334. // Walk up parents, checking for equivalence.
  335. const AbstractClassRep *walk = this;
  336. while ( walk )
  337. {
  338. if ( walk->mClassName == klass )
  339. return true;
  340. walk = walk->parentClass;
  341. };
  342. return false;
  343. }
  344. /// @deprecated Use isSubclassOf.
  345. bool isClass( const AbstractClassRep* acr ) const
  346. {
  347. return isSubclassOf( acr );
  348. }
  349. virtual ConsoleObject* create () const = 0;
  350. AbstractClassRep* findFieldRoot(StringTableEntry fieldName);
  351. protected:
  352. virtual void init();
  353. const char * mClassName;
  354. AbstractClassRep * nextClass;
  355. AbstractClassRep * parentClass;
  356. Namespace * mNamespace;
  357. /// @}
  358. public:
  359. bool mIsRenderEnabled;
  360. bool mIsSelectionEnabled;
  361. bool isRenderEnabled() const { return mIsRenderEnabled; }
  362. bool isSelectionEnabled() const { return mIsSelectionEnabled; }
  363. /// @name Categories
  364. /// @{
  365. protected:
  366. const char* mCategory;
  367. const char* mDescription;
  368. public:
  369. /// Return the space separated category path for the class.
  370. const char* getCategory() const { return mCategory; }
  371. /// Return a short description string suitable for displaying in tooltips.
  372. const char* getDescription() const { return mDescription; }
  373. /// @}
  374. /// @name Fields
  375. /// @{
  376. public:
  377. /// This is a function pointer typedef to support get/set callbacks for fields
  378. typedef bool (*SetDataNotify)( void *obj, const char *array, const char *data );
  379. typedef const char *(*GetDataNotify)( void *obj, const char *data );
  380. /// This is a function pointer typedef to support optional writing for fields.
  381. typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName);
  382. /// These are special field type values used to mark
  383. /// groups and arrays in the field list.
  384. /// @see Field::type
  385. /// @see addArray, endArray
  386. /// @see addGroup, endGroup
  387. /// @see addGroup, endGroup
  388. /// @see addDeprecatedField
  389. enum ACRFieldTypes : U32
  390. {
  391. /// The first custom field type... all fields
  392. /// types greater or equal to this one are not
  393. /// console data types.
  394. ARCFirstCustomField = 0xFFFFFFFB,
  395. /// Marks the start of a fixed size array of fields.
  396. /// @see addArray
  397. StartArrayFieldType = 0xFFFFFFFB,
  398. /// Marks the end of a fixed size array of fields.
  399. /// @see endArray
  400. EndArrayFieldType = 0xFFFFFFFC,
  401. /// Marks the beginning of a group of fields.
  402. /// @see addGroup
  403. StartGroupFieldType = 0xFFFFFFFD,
  404. /// Marks the beginning of a group of fields.
  405. /// @see endGroup
  406. EndGroupFieldType = 0xFFFFFFFE,
  407. /// Marks a field that is depreciated and no
  408. /// longer stores a value.
  409. /// @see addDeprecatedField
  410. DeprecatedFieldType = 0xFFFFFFFF
  411. };
  412. enum FieldFlags
  413. {
  414. FIELD_HideInInspectors = BIT( 0 ), ///< Do not show the field in inspectors.
  415. FIELD_ComponentInspectors = BIT(1), ///< Custom fields used by components. They are likely to be non-standard size/configuration, so
  416. ///< They are handled specially
  417. FIELD_CustomInspectors = BIT(2), ///< Display as a button in inspectors.
  418. };
  419. struct Field
  420. {
  421. Field()
  422. : pFieldname( NULL ),
  423. pGroupname( NULL ),
  424. pFieldDocs( NULL ),
  425. groupExpand( false ),
  426. type( 0 ),
  427. offset( 0 ),
  428. elementCount( 0 ),
  429. table( NULL ),
  430. validator( NULL ),
  431. setDataFn( NULL ),
  432. getDataFn( NULL ),
  433. writeDataFn(NULL),
  434. networkMask(0)
  435. {
  436. doNotSubstitute = keepClearSubsOnly = false;
  437. }
  438. StringTableEntry pFieldname; ///< Name of the field.
  439. const char* pGroupname; ///< Optionally filled field containing the group name.
  440. ///
  441. /// This is filled when type is StartField or EndField
  442. const char* pFieldDocs; ///< Documentation about this field; see consoleDoc.cc.
  443. bool groupExpand; ///< Flag to track expanded/not state of this group in the editor.
  444. U32 type; ///< A data type ID or one of the special custom fields. @see ACRFieldTypes
  445. U32 offset; ///< Memory offset from beginning of class for this field.
  446. S32 elementCount; ///< Number of elements, if this is an array.
  447. const EnumTable * table; ///< If this is an enum, this points to the table defining it.
  448. BitSet32 flag; ///< Stores various flags
  449. TypeValidator *validator; ///< Validator, if any.
  450. SetDataNotify setDataFn; ///< Set data notify Fn
  451. GetDataNotify getDataFn; ///< Get data notify Fn
  452. WriteDataNotify writeDataFn; ///< Function to determine whether data should be written or not.
  453. bool doNotSubstitute;
  454. bool keepClearSubsOnly;
  455. U32 networkMask;
  456. };
  457. typedef Vector<Field> FieldList;
  458. FieldList mFieldList;
  459. bool mDynamicGroupExpand;
  460. const Field* findField( StringTableEntry fieldName ) const;
  461. /// @}
  462. /// @name Console Type Interface
  463. /// @{
  464. virtual void* getNativeVariable() { return new ( AbstractClassRep* ); } // Any pointer-sized allocation will do.
  465. virtual void deleteNativeVariable( void* var ) { delete reinterpret_cast< AbstractClassRep** >( var ); }
  466. /// @}
  467. /// @name Abstract Class Database
  468. /// @{
  469. protected:
  470. static AbstractClassRep ** classTable[NetClassGroupsCount][NetClassTypesCount];
  471. static AbstractClassRep * classLinkList;
  472. static U32 classCRC[NetClassGroupsCount];
  473. static bool initialized;
  474. static ConsoleObject* create(const char* in_pClassName);
  475. static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
  476. public:
  477. static U32 NetClassCount [NetClassGroupsCount][NetClassTypesCount];
  478. static U32 NetClassBitSize[NetClassGroupsCount][NetClassTypesCount];
  479. static void registerClassRep(AbstractClassRep*);
  480. static AbstractClassRep* findClassRep(const char* in_pClassName);
  481. static AbstractClassRep* findClassRep( U32 groupId, U32 typeId, U32 classId );
  482. static void removeClassRep(AbstractClassRep*); // This should not be used lightly
  483. static void initialize(); // Called from Con::init once on startup
  484. static void shutdown();
  485. /// @}
  486. };
  487. extern AbstractClassRep::FieldList sg_tempFieldList;
  488. //=============================================================================
  489. // ConcreteClassRep.
  490. //=============================================================================
  491. /// Helper class for AbstractClassRep.
  492. ///
  493. /// @see AbtractClassRep
  494. /// @see ConsoleObject
  495. template< class T >
  496. class ConcreteAbstractClassRep : public AbstractClassRep
  497. {
  498. public:
  499. virtual AbstractClassRep* getContainerChildClass(const bool recurse)
  500. {
  501. // Fetch container children type.
  502. AbstractClassRep* pChildren = T::getContainerChildStaticClassRep();
  503. if (!recurse || pChildren != NULL)
  504. return pChildren;
  505. // Fetch parent type.
  506. AbstractClassRep* pParent = T::getParentStaticClassRep();
  507. if (pParent == NULL)
  508. return NULL;
  509. // Get parent container children.
  510. return pParent->getContainerChildClass(recurse);
  511. }
  512. virtual WriteCustomTamlSchema getCustomTamlSchema(void)
  513. {
  514. return T::getStaticWriteCustomTamlSchema();
  515. }
  516. static EnginePropertyTable _smPropertyTable;
  517. static EnginePropertyTable& smPropertyTable;
  518. ConcreteAbstractClassRep(const char* name,
  519. const char* conTypeName,
  520. S32* conTypeIdPtr,
  521. S32 netClassGroupMask,
  522. S32 netClassType,
  523. S32 netEventDir,
  524. AbstractClassRep* parent,
  525. const char* (*parentDesc)())
  526. : AbstractClassRep(conTypeIdPtr, conTypeName)
  527. {
  528. mClassName = StringTable->insert(name);
  529. mCategory = T::__category();
  530. mTypeInfo = _MAPTYPE< T >();
  531. if (mTypeInfo)
  532. const_cast< EngineTypeInfo* >(mTypeInfo)->mPropertyTable = &smPropertyTable;
  533. if (&T::__description != parentDesc)
  534. mDescription = T::__description();
  535. // Clean up mClassId
  536. for (U32 i = 0; i < NetClassGroupsCount; i++)
  537. mClassId[i] = -1;
  538. // Set properties for this ACR
  539. mClassType = netClassType;
  540. mClassGroupMask = netClassGroupMask;
  541. mNetEventDir = netEventDir;
  542. parentClass = parent;
  543. mClassSizeof = sizeof(T);
  544. // Finally, register ourselves.
  545. registerClassRep(this);
  546. };
  547. /// Wrap constructor.
  548. ConsoleObject* create() const { return NULL; }
  549. /// Perform class specific initialization tasks.
  550. ///
  551. /// Link namespaces, call initPersistFields() and consoleInit().
  552. void init()
  553. {
  554. // Get handle to our parent class, if any, and ourselves (we are our parent's child).
  555. AbstractClassRep *parent = T::getParentStaticClassRep();
  556. AbstractClassRep *child = T::getStaticClassRep();
  557. // If we got reps, then link those namespaces! (To get proper inheritance.)
  558. if (parent && child)
  559. Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
  560. // Finally, do any class specific initialization...
  561. T::initPersistFields();
  562. T::consoleInit();
  563. EnginePropertyTable::Property* props = new EnginePropertyTable::Property[sg_tempFieldList.size()];
  564. for (int i = 0; i < sg_tempFieldList.size(); ++i)
  565. {
  566. EnginePropertyTable::Property prop;
  567. prop.mDocString = sg_tempFieldList[i].pFieldDocs;
  568. prop.mName = sg_tempFieldList[i].pFieldname;
  569. prop.mNumElements = sg_tempFieldList[i].elementCount;
  570. prop.mFlags = 0;
  571. if (sg_tempFieldList[i].type == StartGroupFieldType)
  572. prop.mFlags |= EnginePropertyGroupBegin;
  573. if (sg_tempFieldList[i].type == EndGroupFieldType)
  574. prop.mFlags |= EnginePropertyGroupEnd;
  575. prop.mType = sg_tempFieldList[i].type;
  576. props[i] = prop;
  577. }
  578. _smPropertyTable = EnginePropertyTable(sg_tempFieldList.size(), props);
  579. smPropertyTable = _smPropertyTable;
  580. const_cast<EngineTypeInfo*>(mTypeInfo)->mPropertyTable = &_smPropertyTable;
  581. // Let the base finish up.
  582. AbstractClassRep::init();
  583. }
  584. /// @name Console Type Interface
  585. /// @{
  586. virtual void setData(void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag)
  587. {
  588. if (argc == 1)
  589. {
  590. T** obj = (T**)dptr;
  591. *obj = dynamic_cast< T* >(T::__findObject(argv[0]));
  592. }
  593. else
  594. Con::errorf("Cannot set multiple args to a single ConsoleObject*.");
  595. }
  596. virtual const char* getData(void* dptr, const EnumTable* tbl, BitSet32 flag)
  597. {
  598. T** obj = (T**)dptr;
  599. return Con::getReturnBuffer(T::__getObjectId(*obj));
  600. }
  601. virtual const char* getTypeClassName() { return mClassName; }
  602. virtual const bool isDatablock() { return T::__smIsDatablock; };
  603. /// @}
  604. };
  605. template< class T >
  606. class ConcreteClassRep : public ConcreteAbstractClassRep<T>
  607. {
  608. public:
  609. ConcreteClassRep(const char* name,
  610. const char* conTypeName,
  611. S32* conTypeIdPtr,
  612. S32 netClassGroupMask,
  613. S32 netClassType,
  614. S32 netEventDir,
  615. AbstractClassRep* parent,
  616. const char* (*parentDesc)())
  617. : ConcreteAbstractClassRep<T>(name, conTypeName, conTypeIdPtr, netClassGroupMask, netClassType, netEventDir, parent, parentDesc)
  618. {
  619. }
  620. /// Wrap constructor.
  621. ConsoleObject* create() const { return new T; }
  622. };
  623. template< typename T > EnginePropertyTable ConcreteAbstractClassRep< T >::_smPropertyTable(0, NULL);
  624. template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPropertyTable = ConcreteAbstractClassRep< T >::_smPropertyTable;
  625. //------------------------------------------------------------------------------
  626. // Forward declaration of this function so it can be used in the class
  627. const char *defaultProtectedGetFn( void *obj, const char *data );
  628. bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName);
  629. //=============================================================================
  630. // ConsoleObject.
  631. //=============================================================================
  632. /// Interface class to the console.
  633. ///
  634. /// @section ConsoleObject_basics The Basics
  635. ///
  636. /// Any object which you want to work with the console system should derive from this,
  637. /// and access functionality through the static interface.
  638. ///
  639. /// This class is always used with the DECLARE_CONOBJECT and IMPLEMENT_* macros.
  640. ///
  641. /// @code
  642. /// // A very basic example object. It will do nothing!
  643. /// class TorqueObject : public ConsoleObject {
  644. /// // Must provide a Parent typedef so the console system knows what we inherit from.
  645. /// typedef ConsoleObject Parent;
  646. ///
  647. /// // This does a lot of menial declaration for you.
  648. /// DECLARE_CONOBJECT(TorqueObject);
  649. ///
  650. /// // This is for us to register our fields in.
  651. /// static void initPersistFields();
  652. ///
  653. /// // A sample field.
  654. /// S8 mSample;
  655. /// }
  656. /// @endcode
  657. ///
  658. /// @code
  659. /// // And the accordant implementation...
  660. /// IMPLEMENT_CONOBJECT(TorqueObject);
  661. ///
  662. /// void TorqueObject::initPersistFields()
  663. /// {
  664. /// // If you want to inherit any fields from the parent (you do), do this:
  665. /// Parent::initPersistFields();
  666. ///
  667. /// // Pass the field, the type, the offset, and a usage string.
  668. /// addField("sample", TypeS8, Offset(mSample, TorqueObject), "A test field.");
  669. /// }
  670. /// @endcode
  671. ///
  672. /// That's all you need to do to get a class registered with the console system. At this point,
  673. /// you can instantiate it via script, tie methods to it using ConsoleMethod, register fields,
  674. /// and so forth. You can also register any global variables related to the class by creating
  675. /// a consoleInit() method.
  676. ///
  677. /// You will need to use different IMPLEMENT_ macros in different cases; for instance, if you
  678. /// are making a NetObject (for ghosting), a DataBlock, or a NetEvent.
  679. ///
  680. /// @see AbstractClassRep for gory implementation details.
  681. /// @nosubgrouping
  682. class ConsoleObject : public EngineObject
  683. {
  684. DECLARE_ABSTRACT_CLASS( ConsoleObject, EngineObject );
  685. protected:
  686. /// @deprecated This is disallowed.
  687. ConsoleObject(const ConsoleObject&);
  688. public:
  689. ConsoleObject() {}
  690. /// Get a reference to a field by name.
  691. const AbstractClassRep::Field *findField(StringTableEntry fieldName) const;
  692. /// Gets the ClassRep.
  693. virtual AbstractClassRep* getClassRep() const;
  694. #define DECLARE_ABSTRACT_CONOBJECT( className ) \
  695. DECLARE_ABSTRACT_CLASS( className, Parent ); \
  696. static S32 _smTypeId; \
  697. static ConcreteAbstractClassRep< className > dynClassRep; \
  698. static AbstractClassRep* getParentStaticClassRep(); \
  699. static AbstractClassRep* getStaticClassRep(); \
  700. static SimObjectRefConsoleBaseType< className > ptrRefType; \
  701. virtual AbstractClassRep* getClassRep() const
  702. /// Set the value of a field.
  703. bool setField(const char *fieldName, const char *value);
  704. public:
  705. /// @name Object Creation
  706. /// @{
  707. static ConsoleObject* create(const char* in_pClassName);
  708. static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
  709. /// @}
  710. public:
  711. /// Get the classname from a class tag.
  712. static const char* lookupClassName(const U32 in_classTag);
  713. /// @name Fields
  714. /// @{
  715. /// Mark the beginning of a group of fields.
  716. ///
  717. /// This is used in the consoleDoc system.
  718. /// @see console_autodoc
  719. static void addGroup(const char* in_pGroupname, const char* in_pGroupDocs = NULL);
  720. /// Mark the end of a group of fields.
  721. ///
  722. /// This is used in the consoleDoc system.
  723. /// @see console_autodoc
  724. static void endGroup(const char* in_pGroupname);
  725. /// Marks the start of a fixed size array of fields.
  726. /// @see console_autodoc
  727. static void addArray( const char *arrayName, S32 count );
  728. /// Marks the end of an array of fields.
  729. /// @see console_autodoc
  730. static void endArray( const char *arrayName );
  731. /// Register a complex field.
  732. ///
  733. /// @param in_pFieldname Name of the field.
  734. /// @param in_fieldType Type of the field. @see ConsoleDynamicTypes
  735. /// @param in_fieldOffset Offset to the field from the start of the class; calculated using the Offset() macro.
  736. /// @param in_elementCount Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
  737. /// @param in_pFieldDocs Usage string for this field. @see console_autodoc
  738. static void addField(const char* in_pFieldname,
  739. const U32 in_fieldType,
  740. const dsize_t in_fieldOffset,
  741. const U32 in_elementCount = 1,
  742. const char* in_pFieldDocs = NULL,
  743. U32 flags = 0 );
  744. static void addField(const char* in_pFieldname,
  745. const U32 in_fieldType,
  746. const dsize_t in_fieldOffset,
  747. AbstractClassRep::WriteDataNotify in_writeDataFn,
  748. const U32 in_elementCount = 1,
  749. const char* in_pFieldDocs = NULL,
  750. U32 flags = 0);
  751. /// Register a simple field.
  752. ///
  753. /// @param in_pFieldname Name of the field.
  754. /// @param in_fieldType Type of the field. @see ConsoleDynamicTypes
  755. /// @param in_fieldOffset Offset to the field from the start of the class; calculated using the Offset() macro.
  756. /// @param in_pFieldDocs Usage string for this field. @see console_autodoc
  757. static void addField(const char* in_pFieldname,
  758. const U32 in_fieldType,
  759. const dsize_t in_fieldOffset,
  760. const char* in_pFieldDocs,
  761. U32 flags = 0 );
  762. static void addField(const char* in_pFieldname,
  763. const U32 in_fieldType,
  764. const dsize_t in_fieldOffset,
  765. AbstractClassRep::WriteDataNotify in_writeDataFn,
  766. const char* in_pFieldDocs,
  767. U32 flags = 0);
  768. /// Register a validated field.
  769. ///
  770. /// A validated field is just like a normal field except that you can't
  771. /// have it be an array, and that you give it a pointer to a TypeValidator
  772. /// subclass, which is then used to validate any value placed in it. Invalid
  773. /// values are ignored and an error is printed to the console.
  774. ///
  775. /// @see addField
  776. /// @see typeValidators.h
  777. static void addFieldV(const char* in_pFieldname,
  778. const U32 in_fieldType,
  779. const dsize_t in_fieldOffset,
  780. TypeValidator *v,
  781. const char * in_pFieldDocs = NULL);
  782. /// Register a complex protected field.
  783. ///
  784. /// @param in_pFieldname Name of the field.
  785. /// @param in_fieldType Type of the field. @see ConsoleDynamicTypes
  786. /// @param in_fieldOffset Offset to the field from the start of the class; calculated using the Offset() macro.
  787. /// @param in_setDataFn When this field gets set, it will call the callback provided. @see console_protected
  788. /// @param in_getDataFn When this field is accessed for it's data, it will return the value of this function
  789. /// @param in_elementCount Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
  790. /// @param in_pFieldDocs Usage string for this field. @see console_autodoc
  791. static void addProtectedField(const char* in_pFieldname,
  792. const U32 in_fieldType,
  793. const dsize_t in_fieldOffset,
  794. AbstractClassRep::SetDataNotify in_setDataFn,
  795. AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
  796. AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
  797. const U32 in_elementCount = 1,
  798. const char* in_pFieldDocs = NULL,
  799. U32 flags = 0);
  800. static void addProtectedField(const char* in_pFieldname,
  801. const U32 in_fieldType,
  802. const dsize_t in_fieldOffset,
  803. AbstractClassRep::SetDataNotify in_setDataFn,
  804. AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
  805. const U32 in_elementCount = 1,
  806. const char* in_pFieldDocs = NULL,
  807. U32 flags = 0);
  808. /// Register a simple protected field.
  809. ///
  810. /// @param in_pFieldname Name of the field.
  811. /// @param in_fieldType Type of the field. @see ConsoleDynamicTypes
  812. /// @param in_fieldOffset Offset to the field from the start of the class; calculated using the Offset() macro.
  813. /// @param in_setDataFn When this field gets set, it will call the callback provided. @see console_protected
  814. /// @param in_getDataFn When this field is accessed for it's data, it will return the value of this function
  815. /// @param in_pFieldDocs Usage string for this field. @see console_autodoc
  816. static void addProtectedField(const char* in_pFieldname,
  817. const U32 in_fieldType,
  818. const dsize_t in_fieldOffset,
  819. AbstractClassRep::SetDataNotify in_setDataFn,
  820. AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
  821. AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
  822. const char* in_pFieldDocs = NULL,
  823. U32 flags = 0);
  824. static void addProtectedField(const char* in_pFieldname,
  825. const U32 in_fieldType,
  826. const dsize_t in_fieldOffset,
  827. AbstractClassRep::SetDataNotify in_setDataFn,
  828. AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
  829. const char* in_pFieldDocs = NULL,
  830. U32 flags = 0);
  831. /// Add a deprecated field.
  832. ///
  833. /// A deprecated field will always be undefined, even if you assign a value to it. This
  834. /// is useful when you need to make sure that a field is not being used anymore.
  835. static void addDeprecatedField(const char *fieldName);
  836. /// Remove a field.
  837. ///
  838. /// Sometimes, you just have to remove a field!
  839. /// @returns True on success.
  840. static bool removeField(const char* in_pFieldname);
  841. /// @}
  842. /// @name Logging
  843. /// @{
  844. /// Overload this in subclasses to change the message formatting.
  845. /// @param fmt A printf style format string.
  846. /// @param args A va_list containing the args passed ot a log function.
  847. /// @note It is suggested that you use String::VToString.
  848. virtual String _getLogMessage(const char* fmt, va_list args) const;
  849. /// @}
  850. public:
  851. /// @name Logging
  852. /// These functions will try to print out a message along the lines
  853. /// of "ObjectClass - ObjectName(ObjectId) - formatted message"
  854. /// @{
  855. /// Logs with Con::printf.
  856. void logMessage(const char* fmt, ...) const;
  857. /// Logs with Con::warnf.
  858. void logWarning(const char* fmt, ...) const;
  859. /// Logs with Con::errorf.
  860. void logError(const char* fmt, ...) const;
  861. /// @}
  862. /// Register dynamic fields in a subclass of ConsoleObject.
  863. ///
  864. /// @see addField(), addFieldV(), addDeprecatedField(), addGroup(), endGroup()
  865. static void initPersistFields();
  866. /// Register global constant variables and do other one-time initialization tasks in
  867. /// a subclass of ConsoleObject.
  868. ///
  869. /// @deprecated You should use ConsoleMethod and ConsoleFunction, not this, to
  870. /// register methods or commands.
  871. /// @see console
  872. static void consoleInit();
  873. /// @name Field List
  874. /// @{
  875. /// Get a list of all the fields. This information cannot be modified.
  876. const AbstractClassRep::FieldList& getFieldList() const;
  877. /// Get a list of all the fields, set up so we can modify them.
  878. ///
  879. /// @note This is a bad trick to pull if you aren't very careful,
  880. /// since you can blast field data!
  881. AbstractClassRep::FieldList& getModifiableFieldList();
  882. /// Get a handle to a boolean telling us if we expanded the dynamic group.
  883. ///
  884. /// @see GuiInspector::Inspect()
  885. bool& getDynamicGroupExpand();
  886. /// @}
  887. /// @name ConsoleObject Implementation
  888. ///
  889. /// These functions are implemented in every subclass of
  890. /// ConsoleObject by an IMPLEMENT_CONOBJECT or IMPLEMENT_CO_* macro.
  891. /// @{
  892. /// Get the abstract class information for this class.
  893. static AbstractClassRep *getStaticClassRep() { return NULL; }
  894. /// Get the abstract class information for this class's superclass.
  895. static AbstractClassRep *getParentStaticClassRep() { return NULL; }
  896. /// Get our network-layer class id.
  897. ///
  898. /// @param netClassGroup The net class for which we want our ID.
  899. /// @see
  900. S32 getClassId(U32 netClassGroup) const;
  901. /// Get our compiler and platform independent class name.
  902. ///
  903. /// @note This name can be used to instantiate another instance using create()
  904. StringTableEntry getClassName() const;
  905. /// @}
  906. static const char* __category() { return ""; }
  907. static const char* __description() { return ""; }
  908. /// Subclasses of ConsoleObjects that are datablocks should redefine this static member variable
  909. /// and set it to true.
  910. static const bool __smIsDatablock = false;
  911. /// @name Object IDs and lookup.
  912. /// For a subclass hierarchy based on ConsoleObject to become functional for use as a console object type,
  913. /// the hierarchy must implement a naming scheme and indexing function for looking up objects by name.
  914. /// @{
  915. static ConsoleObject* __findObject( const char* ) { return NULL; }
  916. static const char* __getObjectId( ConsoleObject* ) { return ""; }
  917. protected:
  918. static bool disableFieldSubstitutions(const char* in_pFieldname);
  919. static bool onlyKeepClearSubstitutions(const char* in_pFieldname);
  920. };
  921. #define addNamedField(fieldName,type,className) addField(#fieldName, type, Offset(fieldName,className))
  922. #define addNamedFieldV(fieldName,type,className, validator) addFieldV(#fieldName, type, Offset(fieldName,className), validator)
  923. //------------------------------------------------------------------------------
  924. //-------------------------------------- Inlines
  925. //
  926. inline S32 ConsoleObject::getClassId(U32 netClassGroup) const
  927. {
  928. AssertFatal(getClassRep() != NULL,"Cannot get tag from non-declared dynamic class!");
  929. return getClassRep()->getClassId(netClassGroup);
  930. }
  931. inline StringTableEntry ConsoleObject::getClassName() const
  932. {
  933. AssertFatal(getClassRep() != NULL,
  934. "Cannot get tag from non-declared dynamic class");
  935. return getClassRep()->getClassName();
  936. }
  937. inline const AbstractClassRep::Field * ConsoleObject::findField(StringTableEntry name) const
  938. {
  939. AssertFatal(getClassRep() != NULL,
  940. avar("Cannot get field '%s' from non-declared dynamic class.", name));
  941. return getClassRep()->findField(name);
  942. }
  943. inline bool ConsoleObject::setField(const char *fieldName, const char *value)
  944. {
  945. //sanity check
  946. if ((! fieldName) || (! fieldName[0]) || (! value))
  947. return false;
  948. if (! getClassRep())
  949. return false;
  950. const AbstractClassRep::Field *myField = getClassRep()->findField(StringTable->insert(fieldName));
  951. if (! myField)
  952. return false;
  953. Con::setData(
  954. myField->type,
  955. (void *) (((const char *)(this)) + myField->offset),
  956. 0,
  957. 1,
  958. &value,
  959. myField->table,
  960. myField->flag);
  961. return true;
  962. }
  963. inline ConsoleObject* ConsoleObject::create(const char* in_pClassName)
  964. {
  965. return AbstractClassRep::create(in_pClassName);
  966. }
  967. inline ConsoleObject* ConsoleObject::create(const U32 groupId, const U32 typeId, const U32 in_classId)
  968. {
  969. return AbstractClassRep::create(groupId, typeId, in_classId);
  970. }
  971. inline const AbstractClassRep::FieldList& ConsoleObject::getFieldList() const
  972. {
  973. return getClassRep()->mFieldList;
  974. }
  975. inline AbstractClassRep::FieldList& ConsoleObject::getModifiableFieldList()
  976. {
  977. return getClassRep()->mFieldList;
  978. }
  979. inline bool& ConsoleObject::getDynamicGroupExpand()
  980. {
  981. return getClassRep()->mDynamicGroupExpand;
  982. }
  983. /// @name ConsoleObject Macros
  984. /// @{
  985. #define DECLARE_CONOBJECT( className ) \
  986. DECLARE_CLASS( className, Parent ); \
  987. static S32 _smTypeId; \
  988. static ConcreteClassRep< className > dynClassRep; \
  989. static AbstractClassRep* getParentStaticClassRep(); \
  990. static AbstractClassRep* getStaticClassRep(); \
  991. static SimObjectRefConsoleBaseType< className > ptrRefType; \
  992. static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema(); \
  993. static AbstractClassRep* getContainerChildStaticClassRep(); \
  994. virtual AbstractClassRep* getClassRep() const
  995. #define DECLARE_CATEGORY( string ) \
  996. static const char* __category() { return string; }
  997. #define DECLARE_DESCRIPTION( string ) \
  998. static const char* __description() { return string; }
  999. #define IMPLEMENT_CONOBJECT( className ) \
  1000. IMPLEMENT_CLASS( className, NULL ) \
  1001. END_IMPLEMENT_CLASS; \
  1002. S32 className::_smTypeId; \
  1003. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1004. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1005. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1006. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1007. AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
  1008. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
  1009. ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
  1010. #define IMPLEMENT_CONOBJECT_CHILDREN( className ) \
  1011. IMPLEMENT_CLASS( className, NULL ) \
  1012. END_IMPLEMENT_CLASS; \
  1013. S32 className::_smTypeId; \
  1014. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1015. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1016. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1017. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1018. AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
  1019. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
  1020. ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
  1021. #define IMPLEMENT_CONOBJECT_SCHEMA( className, schema ) \
  1022. IMPLEMENT_CLASS( className, NULL ) \
  1023. END_IMPLEMENT_CLASS; \
  1024. S32 className::_smTypeId; \
  1025. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1026. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1027. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1028. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1029. AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
  1030. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \
  1031. ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
  1032. #define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema ) \
  1033. IMPLEMENT_CLASS( className, NULL ) \
  1034. END_IMPLEMENT_CLASS; \
  1035. S32 className::_smTypeId; \
  1036. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1037. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1038. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1039. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1040. AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
  1041. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \
  1042. ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
  1043. #define IMPLEMENT_ABSTRACT_CONOBJECT( className ) \
  1044. IMPLEMENT_NONINSTANTIABLE_CLASS( className, NULL ) \
  1045. END_IMPLEMENT_CLASS; \
  1046. S32 className::_smTypeId; \
  1047. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1048. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1049. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1050. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1051. ConcreteAbstractClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
  1052. #define IMPLEMENT_CO_NETOBJECT_V1( className ) \
  1053. IMPLEMENT_CLASS( className, NULL ) \
  1054. END_IMPLEMENT_CLASS; \
  1055. S32 className::_smTypeId; \
  1056. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1057. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1058. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1059. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1060. AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
  1061. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
  1062. ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep(), &Parent::__description )
  1063. #define IMPLEMENT_CO_DATABLOCK_V1( className ) \
  1064. IMPLEMENT_CLASS( className, NULL ) \
  1065. END_IMPLEMENT_CLASS; \
  1066. S32 className::_smTypeId; \
  1067. SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
  1068. AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
  1069. AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
  1070. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  1071. AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
  1072. AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
  1073. ConcreteClassRep<className> className::dynClassRep(#className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep(), &Parent::__description )
  1074. // Support for adding properties to classes CONOBJECT style.
  1075. #define PROPERTY_TABLE( className ) \
  1076. namespace { namespace _ ## className { \
  1077. extern EnginePropertyTable _propTable; \
  1078. } } \
  1079. template<> EnginePropertyTable& \
  1080. ConcreteClassRep< className >::smPropertyTable = _ ## className::_propTable; \
  1081. namespace { namespace _ ## className { \
  1082. EnginePropertyTable::Property _props[] = {
  1083. #define END_PROPERTY_TABLE \
  1084. { NULL } \
  1085. }; \
  1086. EnginePropertyTable _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props ); \
  1087. } }
  1088. /// @}
  1089. //------------------------------------------------------------------------------
  1090. // Protected field default get/set functions
  1091. //
  1092. // The reason for these functions is that it will save one branch per console
  1093. // data request and script functions will still execute at the same speed as
  1094. // before the modifications to allow protected static fields. These will just
  1095. // inline and the code should be roughly the same size, and just as fast as
  1096. // before the modifications. -pw
  1097. inline bool defaultProtectedSetFn( void *object, const char *index, const char *data )
  1098. {
  1099. return true;
  1100. }
  1101. inline bool defaultProtectedSetNotEmptyFn( void *object, const char *index, const char *data )
  1102. {
  1103. return data && data[0];
  1104. }
  1105. inline const char *defaultProtectedGetFn( void *obj, const char *data )
  1106. {
  1107. return data;
  1108. }
  1109. inline const char *emptyStringProtectedGetFn( void *obj, const char *data )
  1110. {
  1111. return "";
  1112. }
  1113. inline bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName)
  1114. {
  1115. return true;
  1116. }
  1117. inline bool defaultProtectedNotSetFn(void* obj, const char *array, const char* data)
  1118. {
  1119. return false;
  1120. }
  1121. inline bool defaultProtectedNotWriteFn(void* obj, StringTableEntry pFieldName)
  1122. {
  1123. return false;
  1124. }
  1125. /// @}
  1126. #endif //_CONSOLEOBJECT_H_