| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames// Copyright (C) 2015 Faust Logic, Inc.//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//#ifndef _CONSOLEOBJECT_H_#define _CONSOLEOBJECT_H_#ifndef _TVECTOR_H_   #include "core/util/tVector.h"#endif#ifndef _STRINGTABLE_H_   #include "core/stringTable.h"#endif#ifndef _STRINGFUNCTIONS_H_   #include "core/strings/stringFunctions.h"#endif#ifndef _BITSET_H_   #include "core/bitSet.h"#endif#ifndef _DYNAMIC_CONSOLETYPES_H_   #include "console/dynamicTypes.h"#endif#ifndef _ENGINEOBJECT_H_   #include "console/engineObject.h"#endif#ifndef _ENGINEFUNCTIONS_H_   #include "console/engineFunctions.h"#endif#ifndef _SIMOBJECTREF_H_   #include "console/simObjectRef.h"#endif#ifndef TINYXML_INCLUDED   #include "tinyxml2.h"#endif#ifndef _CONSOLFUNCTIONS_H_#include "console/consoleFunctions.h"#endif/// @file/// Legacy console object system./// @ingroup console_system Console System/// @{class Namespace;class ConsoleObject;enum NetClassTypes{   NetClassTypeObject = 0,   NetClassTypeDataBlock,   NetClassTypeEvent,   NetClassTypesCount,};enum NetClassGroups{   NetClassGroupGame = 0,   NetClassGroupCommunity,   NetClassGroup3,   NetClassGroup4,   NetClassGroupsCount,};enum NetClassMasks{   NetClassGroupGameMask      = BIT(NetClassGroupGame),   NetClassGroupCommunityMask = BIT(NetClassGroupCommunity),};enum NetDirection{   NetEventDirAny,   NetEventDirServerToClient,   NetEventDirClientToServer,};class SimObject;class TypeValidator;class ConsoleClassObject;DECLARE_SCOPE( ConsoleAPI );//=============================================================================//    AbstractClassRep.//=============================================================================/// Core functionality for class manipulation.////// @section AbstractClassRep_intro Introduction (or, Why AbstractClassRep?)////// Many of Torque's subsystems, especially network, console, and sim,/// require the ability to programatically instantiate classes. For instance,/// when objects are ghosted, the networking layer needs to be able to create/// an instance of the object on the client. When the console scripting/// language runtime encounters the "new" keyword, it has to be able to fill/// that request.////// Since standard C++ doesn't provide a function to create a new instance of/// an arbitrary class at runtime, one must be created. This is what/// AbstractClassRep and ConcreteClassRep are all about. They allow the registration/// and instantiation of arbitrary classes at runtime.////// In addition, ACR keeps track of the fields (registered via addField() and co.) of/// a class, allowing programmatic access of class fields.////// @see ConsoleObject////// @note In general, you will only access the functionality implemented in this class via///       ConsoleObject::create(). Most of the time, you will only ever need to use this part///       part of the engine indirectly - ie, you will use the networking system or the console,///       or ConsoleObject, and they will indirectly use this code. <b>The following discussion///       is really only relevant for advanced engine users.</b>////// @section AbstractClassRep_netstuff NetClasses and Class IDs////// Torque supports a notion of group, type, and direction for objects passed over/// the network. Class IDs are assigned sequentially per-group, per-type, so that, for instance,/// the IDs assigned to Datablocks are seperate from the IDs assigned to NetObjects or NetEvents./// This can translate into significant bandwidth savings (especially since the size of the fields/// for transmitting these bits are determined at run-time based on the number of IDs given out.////// @section AbstractClassRep_details AbstractClassRep Internals////// Much like ConsoleConstructor, ACR does some preparatory work at runtime before execution/// is passed to main(). In actual fact, this preparatory work is done by the ConcreteClassRep/// template. Let's examine this more closely.////// If we examine ConsoleObject, we see that two macros must be used in the definition of a/// properly integrated objects. From the ConsoleObject example:////// @code///      // This is from inside the class definition...///      DECLARE_CONOBJECT(TorqueObject);////// // And this is from outside the class definition.../// IMPLEMENT_CONOBJECT(TorqueObject);/// @endcode////// What do these things actually do?////// Not all that much, in fact. They expand to code something like this:////// @code///      // This is from inside the class definition...///      static ConcreteClassRep<TorqueObject> dynClassRep;///      static AbstractClassRep* getParentStaticClassRep();///      static AbstractClassRep* getStaticClassRep();///      virtual AbstractClassRep* getClassRep() const;/// @endcode////// @code/// // And this is from outside the class definition.../// AbstractClassRep* TorqueObject::getClassRep() const { return &TorqueObject::dynClassRep; }/// AbstractClassRep* TorqueObject::getStaticClassRep() { return &dynClassRep; }/// AbstractClassRep* TorqueObject::getParentStaticClassRep() { return Parent::getStaticClassRep(); }/// ConcreteClassRep<TorqueObject> TorqueObject::dynClassRep("TorqueObject", 0, -1, 0);/// @endcode////// As you can see, getClassRep(), getStaticClassRep(), and getParentStaticClassRep() are just/// accessors to allow access to various ConcreteClassRep instances. This is where the Parent/// typedef comes into play as well - it lets getParentStaticClassRep() get the right/// class rep.////// In addition, dynClassRep is declared as a member of TorqueObject, and defined later/// on. Much like ConsoleConstructor, ConcreteClassReps add themselves to a global linked/// list in their constructor.////// Then, when AbstractClassRep::initialize() is called, from Con::init(), we iterate through/// the list and perform the following tasks:///      - Sets up a Namespace for each class.///      - Call the init() method on each ConcreteClassRep. This method:///         - Links namespaces between parent and child classes, using Con::classLinkNamespaces.///         - Calls initPersistFields() and consoleInit().///      - As a result of calling initPersistFields, the field list for the class is populated.///      - Assigns network IDs for classes based on their NetGroup membership. Determines///        bit allocations for network ID fields.////// @nosubgroupingclass AbstractClassRep : public ConsoleBaseType{   friend class ConsoleObject;public:   typedef ConsoleBaseType Parent;   /// Allows the writing of a custom TAML schema.   typedef void(*WriteCustomTamlSchema)(const AbstractClassRep* pClassRep, tinyxml2::XMLElement* pParentElement);   /// @name 'Tructors   /// @{   ///   /// @param conIdPtr Pointer to the static S32 console ID.   /// @param conTypeName Console type name.   AbstractClassRep( S32* conIdPtr, const char* typeName )      : Parent( sizeof( void* ), conIdPtr, typeName )   {      VECTOR_SET_ASSOCIATION( mFieldList );      mCategory = StringTable->EmptyString();      mClassGroupMask = 0;      std::fill_n(mClassId, NetClassGroupsCount, -1);      mClassName = StringTable->EmptyString();      mClassSizeof = 0;      mClassType = 0;      mDescription = StringTable->EmptyString();#ifdef TORQUE_NET_STATS      dMemset(mDirtyMaskFrequency, 0, sizeof(mDirtyMaskFrequency));      dMemset(mDirtyMaskTotal, 0, sizeof(mDirtyMaskTotal));#endif      mDynamicGroupExpand = false;      mNamespace = NULL;      mNetEventDir = 0;      nextClass = NULL;      parentClass  = NULL;      mIsRenderEnabled = true;      mIsSelectionEnabled = true;   }   /// @}   /// @name Representation Interface   /// @{//TODO: move over to EngineTypeNetInfo   S32 mClassGroupMask;                   ///< Mask indicating in which NetGroups this object belongs.   S32 mClassType;                        ///< Stores the NetClass of this class.   S32 mNetEventDir;                      ///< Stores the NetDirection of this class.   S32 mClassId[ NetClassGroupsCount ];   ///< Stores the IDs assigned to this class for each group.   S32 mClassSizeof;                      ///< Size of instances in bytes.//TODO: move over to EngineTypeNetInfo#ifdef TORQUE_NET_STATS   struct NetStatInstance   {      U32 numEvents;      U32 total;      S32 min;      S32 max;      void reset()      {         numEvents = 0;         total = 0;         min = S32_MAX;         max = S32_MIN;      }      void update(U32 amount)      {         numEvents++;         total += amount;         min = getMin((S32)amount, min);         max = getMax((S32)amount, max);      }      NetStatInstance()      {         reset();      }   };   NetStatInstance mNetStatPack;   NetStatInstance mNetStatUnpack;   NetStatInstance mNetStatWrite;   NetStatInstance mNetStatRead;   U32 mDirtyMaskFrequency[32];   U32 mDirtyMaskTotal[32];   void resetNetStats()   {      mNetStatPack.reset();      mNetStatUnpack.reset();      mNetStatWrite.reset();      mNetStatRead.reset();      for(S32 i=0; i<32; i++)      {         mDirtyMaskFrequency[i] = 0;         mDirtyMaskTotal[i] = 0;      }   }   void updateNetStatPack(U32 dirtyMask, U32 length)   {      mNetStatPack.update(length);      for(S32 i=0; i<32; i++)         if(BIT(i) & dirtyMask)         {            mDirtyMaskFrequency[i]++;            mDirtyMaskTotal[i] += length;         }   }   void updateNetStatUnpack(U32 length)   {      mNetStatUnpack.update(length);   }   void updateNetStatWriteData(U32 length)   {      mNetStatWrite.update(length);   }   void updateNetStatReadData(U32 length)   {      mNetStatRead.update(length);   }#endif   S32                        getClassId  (U32 netClassGroup)   const { return mClassId[ netClassGroup ]; }   static U32                 getClassCRC (U32 netClassGroup) { return classCRC[ netClassGroup ]; }   AbstractClassRep*          getCommonParent( const AbstractClassRep *otherClass ) const;   /// Return the name of this class.   StringTableEntry getClassName() const { return mClassName; }   /// Return the namespace that contains the methods of this class.   Namespace* getNameSpace() const { return mNamespace; }   /// Return the AbstractClassRep of the class that this class is derived from.   AbstractClassRep* getParentClass() const { return parentClass; }   virtual AbstractClassRep*    getContainerChildClass(const bool recurse) = 0;   virtual WriteCustomTamlSchema getCustomTamlSchema(void) = 0;   /// Return the size of instances of this class in bytes.   S32 getSizeof() const { return mClassSizeof; }   /// Return the next class in the global class list link chain.   AbstractClassRep* getNextClass() const { return nextClass; }   /// Return the head of the global class list.   static AbstractClassRep* getClassList() { return classLinkList; }   /// Helper class to see if we are a given class, or a subclass thereof by   /// comparing AbstractClassRep pointers.   bool isSubclassOf( const AbstractClassRep* klass ) const   {      const AbstractClassRep *walk = this;      // Walk up parents, checking for equivalence.      while ( walk )      {         if ( walk == klass )            return true;         walk = walk->parentClass;      };      return false;   }   /// Helper class to see if we are a given class, or a subclass thereof by   /// comparing the class name strings.   bool isSubclassOf( const char *klass ) const   {      klass = StringTable->insert( klass );      // Walk up parents, checking for equivalence.      const AbstractClassRep *walk = this;      while ( walk )      {         if ( walk->mClassName == klass )            return true;         walk = walk->parentClass;      };      return false;   }   /// @deprecated Use isSubclassOf.   bool isClass( const AbstractClassRep* acr ) const   {      return isSubclassOf( acr );   }   virtual ConsoleObject*     create      () const = 0;   AbstractClassRep* findFieldRoot(StringTableEntry fieldName);protected:   virtual void init();   const char *       mClassName;   AbstractClassRep * nextClass;   AbstractClassRep * parentClass;   Namespace *        mNamespace;   /// @}public:   bool mIsRenderEnabled;   bool mIsSelectionEnabled;   bool isRenderEnabled() const { return mIsRenderEnabled; }   bool isSelectionEnabled() const { return mIsSelectionEnabled; }   /// @name Categories   /// @{protected:   const char* mCategory;   const char* mDescription;public:   /// Return the space separated category path for the class.   const char* getCategory() const { return mCategory; }   /// Return a short description string suitable for displaying in tooltips.   const char* getDescription() const { return mDescription; }   /// @}   /// @name Fields   /// @{public:   /// This is a function pointer typedef to support get/set callbacks for fields   typedef bool (*SetDataNotify)( void *obj, const char *array, const char *data );   typedef const char *(*GetDataNotify)( void *obj, const char *data );   /// This is a function pointer typedef to support optional writing for fields.   typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName);   /// These are special field type values used to mark   /// groups and arrays in the field list.   /// @see Field::type   /// @see addArray, endArray   /// @see addGroup, endGroup   /// @see addGroup, endGroup   /// @see addDeprecatedField   enum ACRFieldTypes : U32   {      /// The first custom field type... all fields      /// types greater or equal to this one are not      /// console data types.      ARCFirstCustomField = 0xFFFFFFFB,      /// Marks the start of a fixed size array of fields.      /// @see addArray      StartArrayFieldType = 0xFFFFFFFB,      /// Marks the end of a fixed size array of fields.      /// @see endArray      EndArrayFieldType   = 0xFFFFFFFC,      /// Marks the beginning of a group of fields.      /// @see addGroup      StartGroupFieldType = 0xFFFFFFFD,      /// Marks the beginning of a group of fields.      /// @see endGroup      EndGroupFieldType   = 0xFFFFFFFE,      /// Marks a field that is depreciated and no      /// longer stores a value.      /// @see addDeprecatedField      DeprecatedFieldType = 0xFFFFFFFF   };   enum FieldFlags   {      FIELD_HideInInspectors     = BIT( 0 ),    ///< Do not show the field in inspectors.      FIELD_ComponentInspectors = BIT(1),       ///< Custom fields used by components. They are likely to be non-standard size/configuration, so                                                 ///< They are handled specially      FIELD_CustomInspectors = BIT(2),          ///< Display as a button in inspectors.      FIELD_SpecialtyArrayField = BIT(3)   };   struct Field   {      Field()         :  pFieldname( NULL ),            pGroupname( NULL ),            pFieldDocs( NULL ),            groupExpand( false ),            type( 0 ),            offset( 0 ),            elementCount( 0 ),            table( NULL ),            validator( NULL ),            setDataFn( NULL ),            getDataFn( NULL ),            writeDataFn(NULL),            networkMask(0)      {         doNotSubstitute = keepClearSubsOnly = false;      }      StringTableEntry pFieldname;    ///< Name of the field.      const char*    pGroupname;      ///< Optionally filled field containing the group name.                                 ///                                 ///  This is filled when type is StartField or EndField      const char*    pFieldDocs;    ///< Documentation about this field; see consoleDoc.cc.      bool           groupExpand;   ///< Flag to track expanded/not state of this group in the editor.      U32            type;          ///< A data type ID or one of the special custom fields. @see ACRFieldTypes      U32            offset;        ///< Memory offset from beginning of class for this field.      S32            elementCount;  ///< Number of elements, if this is an array.      const EnumTable *    table;   ///< If this is an enum, this points to the table defining it.      BitSet32       flag;          ///< Stores various flags      TypeValidator *validator;     ///< Validator, if any.      SetDataNotify  setDataFn;     ///< Set data notify Fn      GetDataNotify  getDataFn;     ///< Get data notify Fn	    WriteDataNotify writeDataFn;  ///< Function to determine whether data should be written or not.      bool           doNotSubstitute;      bool           keepClearSubsOnly;      U32            networkMask;   };   typedef Vector<Field> FieldList;   FieldList mFieldList;   bool mDynamicGroupExpand;   const Field* findField( StringTableEntry fieldName ) const;   /// @}   /// @name Console Type Interface   /// @{   void* getNativeVariable() override { return new ( AbstractClassRep* ); } // Any pointer-sized allocation will do.   void deleteNativeVariable( void* var ) override { delete reinterpret_cast< AbstractClassRep** >( var ); }   /// @}   /// @name Abstract Class Database   /// @{protected:   static AbstractClassRep ** classTable[NetClassGroupsCount][NetClassTypesCount];   static AbstractClassRep *  classLinkList;   static U32                 classCRC[NetClassGroupsCount];   static bool                initialized;   static ConsoleObject* create(const char*  in_pClassName);   static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);public:   static U32  NetClassCount [NetClassGroupsCount][NetClassTypesCount];   static U32  NetClassBitSize[NetClassGroupsCount][NetClassTypesCount];   static void registerClassRep(AbstractClassRep*);   static AbstractClassRep* findClassRep(const char* in_pClassName);   static AbstractClassRep* findClassRep( U32 groupId, U32 typeId, U32 classId );   static void removeClassRep(AbstractClassRep*); // This should not be used lightly   static void initialize(); // Called from Con::init once on startup   static void shutdown();   /// @}};extern AbstractClassRep::FieldList sg_tempFieldList;//=============================================================================//    ConcreteClassRep.//=============================================================================/// Helper class for AbstractClassRep.////// @see AbtractClassRep/// @see ConsoleObjecttemplate< class T >class ConcreteAbstractClassRep : public AbstractClassRep{public:   AbstractClassRep* getContainerChildClass(const bool recurse) override   {      // Fetch container children type.      AbstractClassRep* pChildren = T::getContainerChildStaticClassRep();      if (!recurse || pChildren != NULL)         return pChildren;      // Fetch parent type.      AbstractClassRep* pParent = T::getParentStaticClassRep();      if (pParent == NULL)         return NULL;      // Get parent container children.      return pParent->getContainerChildClass(recurse);   }   WriteCustomTamlSchema getCustomTamlSchema(void) override   {      return T::getStaticWriteCustomTamlSchema();   }   static EnginePropertyTable _smPropertyTable;   static EnginePropertyTable& smPropertyTable;   ConcreteAbstractClassRep(const char* name,      const char* conTypeName,      S32* conTypeIdPtr,      S32 netClassGroupMask,      S32 netClassType,      S32 netEventDir,      AbstractClassRep* parent,      const char* (*parentDesc)())      : AbstractClassRep(conTypeIdPtr, conTypeName)   {      mClassName = StringTable->insert(name);      mCategory = T::__category();      mTypeInfo = _MAPTYPE< T >();      if (mTypeInfo)         const_cast< EngineTypeInfo* >(mTypeInfo)->mPropertyTable = &smPropertyTable;      if (&T::__description != parentDesc)          mDescription = T::__description();      // Clean up mClassId      for (U32 i = 0; i < NetClassGroupsCount; i++)         mClassId[i] = -1;      // Set properties for this ACR      mClassType = netClassType;      mClassGroupMask = netClassGroupMask;      mNetEventDir = netEventDir;      parentClass = parent;      mClassSizeof = sizeof(T);       // Finally, register ourselves.      registerClassRep(this);   };    /// Wrap constructor.   ConsoleObject* create() const override { return NULL; }   /// Perform class specific initialization tasks.   ///   /// Link namespaces, call initPersistFields() and consoleInit().   void init() override   {      // Get handle to our parent class, if any, and ourselves (we are our parent's child).      AbstractClassRep *parent = T::getParentStaticClassRep();      AbstractClassRep *child = T::getStaticClassRep();        // If we got reps, then link those namespaces! (To get proper inheritance.)      if (parent && child)         Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());      // Finally, do any class specific initialization...      T::initPersistFields();      T::consoleInit();      EnginePropertyTable::Property* props = new EnginePropertyTable::Property[sg_tempFieldList.size() + 1];      for (int i = 0; i < sg_tempFieldList.size(); ++i)      {         EnginePropertyTable::Property prop;         prop.mDocString = sg_tempFieldList[i].pFieldDocs;         prop.mName = sg_tempFieldList[i].pFieldname;         prop.mNumElements = sg_tempFieldList[i].elementCount;         prop.mFlags = 0;         if (sg_tempFieldList[i].type == StartGroupFieldType)            prop.mFlags |= EnginePropertyGroupBegin;         if (sg_tempFieldList[i].type == EndGroupFieldType)            prop.mFlags |= EnginePropertyGroupEnd;         prop.mType = sg_tempFieldList[i].type;         props[i] = prop;      }      _smPropertyTable = EnginePropertyTable(sg_tempFieldList.size(), props);      smPropertyTable = _smPropertyTable;      const_cast<EngineTypeInfo*>(mTypeInfo)->mPropertyTable = &_smPropertyTable;       // Let the base finish up.      AbstractClassRep::init();   }    /// @name Console Type Interface   /// @{    void setData(void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag) override   {      if (argc == 1)      {         T** obj = (T**)dptr;         *obj = dynamic_cast< T* >(T::__findObject(argv[0]));      }      else          Con::errorf("Cannot set multiple args to a single ConsoleObject*.");   }    const char* getData(void* dptr, const EnumTable* tbl, BitSet32 flag) override   {       T** obj = (T**)dptr;       return Con::getReturnBuffer(T::__getObjectId(*obj));   }    const char* getTypeClassName() override { return mClassName; }   const bool isDatablock() override { return T::__smIsDatablock; };   /// @} };  template< class T > class ConcreteClassRep : public ConcreteAbstractClassRep<T> { public:    ConcreteClassRep(const char* name,       const char* conTypeName,       S32* conTypeIdPtr,       S32 netClassGroupMask,       S32 netClassType,       S32 netEventDir,       AbstractClassRep* parent,       const char* (*parentDesc)())       : ConcreteAbstractClassRep<T>(name, conTypeName, conTypeIdPtr, netClassGroupMask, netClassType, netEventDir, parent, parentDesc)    {    }    /// Wrap constructor.   ConsoleObject* create() const override { return new T; }};template< typename T > EnginePropertyTable ConcreteAbstractClassRep< T >::_smPropertyTable(0, NULL);template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPropertyTable = ConcreteAbstractClassRep< T >::_smPropertyTable;//------------------------------------------------------------------------------// Forward declaration of this function so  it can be used in the classconst char *defaultProtectedGetFn( void *obj, const char *data );bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName);//=============================================================================//    ConsoleObject.//=============================================================================/// Interface class to the console.////// @section ConsoleObject_basics The Basics////// Any object which you want to work with the console system should derive from this,/// and access functionality through the static interface.////// This class is always used with the DECLARE_CONOBJECT and IMPLEMENT_* macros.////// @code/// // A very basic example object. It will do nothing!/// class TorqueObject : public ConsoleObject {///      // Must provide a Parent typedef so the console system knows what we inherit from.///      typedef ConsoleObject Parent;//////      // This does a lot of menial declaration for you.///      DECLARE_CONOBJECT(TorqueObject);//////      // This is for us to register our fields in.///      static void initPersistFields();//////      // A sample field.///      S8 mSample;/// }/// @endcode////// @code/// // And the accordant implementation.../// IMPLEMENT_CONOBJECT(TorqueObject);////// void TorqueObject::initPersistFields()/// {///   // If you want to inherit any fields from the parent (you do), do this:///   Parent::initPersistFields();//////   // Pass the field, the type, the offset,                  and a usage string.///   addField("sample", TypeS8, Offset(mSample, TorqueObject), "A test field.");/// }/// @endcode////// That's all you need to do to get a class registered with the console system. At this point,/// you can instantiate it via script, tie methods to it using ConsoleMethod, register fields,/// and so forth. You can also register any global variables related to the class by creating/// a consoleInit() method.////// You will need to use different IMPLEMENT_ macros in different cases; for instance, if you/// are making a NetObject (for ghosting), a DataBlock, or a NetEvent.////// @see AbstractClassRep for gory implementation details./// @nosubgroupingclass ConsoleObject : public EngineObject{   DECLARE_ABSTRACT_CLASS( ConsoleObject, EngineObject );protected:   /// @deprecated This is disallowed.   ConsoleObject(const ConsoleObject&) { mDocsClick = false; };public:   /// <summary>   /// Only used for interfacing with the editor's inspector docsURL button   /// </summary>   bool mDocsClick;   ConsoleObject() { mDocsClick = false; }   /// Get a reference to a field by name.   const AbstractClassRep::Field *findField(StringTableEntry fieldName) const;   /// Gets the ClassRep.   virtual AbstractClassRep* getClassRep() const;#define DECLARE_ABSTRACT_CONOBJECT( className )                \   DECLARE_ABSTRACT_CLASS( className, Parent );                \   static S32 _smTypeId;                                       \   static ConcreteAbstractClassRep< className > dynClassRep;   \   static AbstractClassRep* getParentStaticClassRep();         \   static AbstractClassRep* getStaticClassRep();               \   static SimObjectRefConsoleBaseType< className > ptrRefType; \   virtual AbstractClassRep* getClassRep() const    /// Set the value of a field.   bool setField(const char *fieldName, const char *value);public:   /// @name Object Creation   /// @{   static ConsoleObject* create(const char*  in_pClassName);   static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);   /// @}public:   /// Get the classname from a class tag.   static const char* lookupClassName(const U32 in_classTag) { return ""; };   /// @name Fields   /// @{   /// Mark the beginning of a group of fields.   ///   /// This is used in the consoleDoc system.   /// @see console_autodoc   static void addGroup(const char*  in_pGroupname, const char* in_pGroupDocs = NULL);   /// Mark the end of a group of fields.   ///   /// This is used in the consoleDoc system.   /// @see console_autodoc   static void endGroup(const char*  in_pGroupname);   /// Marks the start of a fixed size array of fields.   /// @see console_autodoc   static void addArray( const char *arrayName, S32 count );   /// Marks the end of an array of fields.   /// @see console_autodoc   static void endArray( const char *arrayName );   /// Register a complex field.   ///   /// @param  in_pFieldname     Name of the field.   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc   static void addField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      const U32     in_elementCount = 1,      const char*   in_pFieldDocs   = NULL,      U32 flags = 0 );   static void addField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::WriteDataNotify in_writeDataFn,      const U32     in_elementCount = 1,      const char*   in_pFieldDocs = NULL,      U32 flags = 0);   /// Register a simple field.   ///   /// @param  in_pFieldname  Name of the field.   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc   static void addField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      const char*   in_pFieldDocs,      U32 flags = 0 );   static void addField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::WriteDataNotify in_writeDataFn,      const char*   in_pFieldDocs,      U32 flags = 0);   /// Register a validated field.   ///   /// A validated field is just like a normal field except that you can't   /// have it be an array, and that you give it a pointer to a TypeValidator   /// subclass, which is then used to validate any value placed in it. Invalid   /// values are ignored and an error is printed to the console.   ///   /// @see addField   /// @see typeValidators.h   static void addFieldV(const char*   in_pFieldname,      const U32      in_fieldType,      const dsize_t  in_fieldOffset,      TypeValidator *v,      const char *   in_pFieldDocs = NULL);   /// Register a complex protected field.   ///   /// @param  in_pFieldname     Name of the field.   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.   /// @param  in_setDataFn      When this field gets set, it will call the callback provided. @see console_protected   /// @param  in_getDataFn      When this field is accessed for it's data, it will return the value of this function   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc   static void addProtectedField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::SetDataNotify in_setDataFn,      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,      AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,      const U32     in_elementCount = 1,      const char*   in_pFieldDocs = NULL,      U32 flags = 0);   static void addProtectedField(const char*  in_pFieldname,      const U32 in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::SetDataNotify in_setDataFn,      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,      const U32 in_elementCount = 1,      const char* in_pFieldDocs = NULL,      U32 flags = 0);   /// Register a simple protected field.   ///   /// @param  in_pFieldname  Name of the field.   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.   /// @param  in_setDataFn   When this field gets set, it will call the callback provided. @see console_protected   /// @param  in_getDataFn   When this field is accessed for it's data, it will return the value of this function   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc   static void addProtectedField(const char*   in_pFieldname,      const U32     in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::SetDataNotify in_setDataFn,      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,      AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,      const char*   in_pFieldDocs = NULL,      U32 flags = 0);   static void addProtectedField(const char*  in_pFieldname,      const U32 in_fieldType,      const dsize_t in_fieldOffset,      AbstractClassRep::SetDataNotify in_setDataFn,      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,      const char* in_pFieldDocs = NULL,      U32 flags = 0);   /// Add a deprecated field.   ///   /// A deprecated field will always be undefined, even if you assign a value to it. This   /// is useful when you need to make sure that a field is not being used anymore.   static void addDeprecatedField(const char *fieldName);   /// Remove a field.   ///   /// Sometimes, you just have to remove a field!   /// @returns True on success.   static bool removeField(const char* in_pFieldname);   /// @}   /// @name Logging   /// @{   /// Overload this in subclasses to change the message formatting.   /// @param fmt A printf style format string.   /// @param args A va_list containing the args passed ot a log function.   /// @note It is suggested that you use String::VToString.   virtual String _getLogMessage(const char* fmt, va_list args) const;   /// @}public:   /// @name Logging   /// These functions will try to print out a message along the lines   /// of "ObjectClass - ObjectName(ObjectId) - formatted message"   /// @{   /// Logs with Con::printf.   void logMessage(const char* fmt, ...) const;   /// Logs with Con::warnf.   void logWarning(const char* fmt, ...) const;   /// Logs with Con::errorf.   void logError(const char* fmt, ...) const;   /// @}   /// Register dynamic fields in a subclass of ConsoleObject.   ///   /// @see addField(), addFieldV(), addDeprecatedField(), addGroup(), endGroup()   static void initPersistFields();   /// Register global constant variables and do other one-time initialization tasks in   /// a subclass of ConsoleObject.   ///   /// @deprecated You should use ConsoleMethod and ConsoleFunction, not this, to   ///             register methods or commands.   /// @see console   static void consoleInit();   /// @name Field List   /// @{   /// Get a list of all the fields. This information cannot be modified.   const AbstractClassRep::FieldList& getFieldList() const;   /// Get a list of all the fields, set up so we can modify them.   ///   /// @note This is a bad trick to pull if you aren't very careful,   ///       since you can blast field data!   AbstractClassRep::FieldList& getModifiableFieldList();   /// Get a handle to a boolean telling us if we expanded the dynamic group.   ///   /// @see GuiInspector::Inspect()   bool& getDynamicGroupExpand();   /// @}   /// @name ConsoleObject Implementation   ///   /// These functions are implemented in every subclass of   /// ConsoleObject by an IMPLEMENT_CONOBJECT or IMPLEMENT_CO_* macro.   /// @{   /// Get the abstract class information for this class.   static AbstractClassRep *getStaticClassRep() { return NULL; }   /// Get the abstract class information for this class's superclass.   static AbstractClassRep *getParentStaticClassRep() { return NULL; }   /// Get our network-layer class id.   ///   /// @param  netClassGroup  The net class for which we want our ID.   /// @see   S32 getClassId(U32 netClassGroup) const;   /// Get our compiler and platform independent class name.   ///   /// @note This name can be used to instantiate another instance using create()   StringTableEntry getClassName() const;   /// @}   static const char* __category() { return ""; }   static const char* __description() { return ""; }   /// Subclasses of ConsoleObjects that are datablocks should redefine this static member variable   /// and set it to true.   static const bool __smIsDatablock = false;   /// @name Object IDs and lookup.   /// For a subclass hierarchy based on ConsoleObject to become functional for use as a console object type,   /// the hierarchy must implement a naming scheme and indexing function for looking up objects by name.   /// @{   static ConsoleObject* __findObject( const char* ) { return NULL; }   static const char* __getObjectId( ConsoleObject* ) { return ""; }protected:   static bool disableFieldSubstitutions(const char* in_pFieldname);   static bool onlyKeepClearSubstitutions(const char* in_pFieldname);};#define addNamedField(fieldName,type,className) addField(#fieldName, type, Offset(fieldName,className))#define addNamedFieldV(fieldName,type,className, validator) addFieldV(#fieldName, type, Offset(fieldName,className), validator)//------------------------------------------------------------------------------//-------------------------------------- Inlines//inline S32 ConsoleObject::getClassId(U32 netClassGroup) const{   AssertFatal(getClassRep() != NULL,"Cannot get tag from non-declared dynamic class!");   return getClassRep()->getClassId(netClassGroup);}inline StringTableEntry ConsoleObject::getClassName() const{   AssertFatal(getClassRep() != NULL,      "Cannot get tag from non-declared dynamic class");   return getClassRep()->getClassName();}inline const AbstractClassRep::Field * ConsoleObject::findField(StringTableEntry name) const{   AssertFatal(getClassRep() != NULL,      avar("Cannot get field '%s' from non-declared dynamic class.", name));   return getClassRep()->findField(name);}inline bool ConsoleObject::setField(const char *fieldName, const char *value){   //sanity check   if ((! fieldName) || (! fieldName[0]) || (! value))      return false;   if (! getClassRep())      return false;   const AbstractClassRep::Field *myField = getClassRep()->findField(StringTable->insert(fieldName));   if (! myField)      return false;   Con::setData(      myField->type,      (void *) (((const char *)(this)) + myField->offset),      0,      1,      &value,      myField->table,      myField->flag);   return true;}inline ConsoleObject* ConsoleObject::create(const char* in_pClassName){   return AbstractClassRep::create(in_pClassName);}inline ConsoleObject* ConsoleObject::create(const U32 groupId, const U32 typeId, const U32 in_classId){   return AbstractClassRep::create(groupId, typeId, in_classId);}inline const AbstractClassRep::FieldList& ConsoleObject::getFieldList() const{   return getClassRep()->mFieldList;}inline AbstractClassRep::FieldList& ConsoleObject::getModifiableFieldList(){   return getClassRep()->mFieldList;}inline bool& ConsoleObject::getDynamicGroupExpand(){   return getClassRep()->mDynamicGroupExpand;}/// @name ConsoleObject Macros/// @{#define DECLARE_CONOBJECT( className )                   \   DECLARE_CLASS( className, Parent );                   \   static S32 _smTypeId;                                 \   static ConcreteClassRep< className > dynClassRep;     \   static AbstractClassRep* getParentStaticClassRep();   \   static AbstractClassRep* getStaticClassRep();         \   static SimObjectRefConsoleBaseType< className > ptrRefType;         \   static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema();         \   static AbstractClassRep* getContainerChildStaticClassRep();         \   AbstractClassRep* getClassRep() const override#define DECLARE_CATEGORY( string )                      \   static const char* __category() { return string; }#define DECLARE_DESCRIPTION( string )                   \   static const char* __description() { return string; }#define IMPLEMENT_CONOBJECT( className )                                                           \   IMPLEMENT_CLASS( className, NULL )                                                              \   END_IMPLEMENT_CLASS;                                                                            \   S32 className::_smTypeId;                                                                       \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );      \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }            \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                       \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \   AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                 \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \   ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_CONOBJECT_CHILDREN( className )                                                  \   IMPLEMENT_CLASS( className, NULL )                                                              \   END_IMPLEMENT_CLASS;                                                                            \   S32 className::_smTypeId;                                                                       \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );      \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }            \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                       \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \   AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }        \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \   ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_CONOBJECT_SCHEMA( className, schema )                                            \   IMPLEMENT_CLASS( className, NULL )                                                              \   END_IMPLEMENT_CLASS;                                                                            \   S32 className::_smTypeId;                                                                       \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );      \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }            \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                       \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \   AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                 \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; }            \   ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema )                                   \   IMPLEMENT_CLASS( className, NULL )                                                              \   END_IMPLEMENT_CLASS;                                                                            \   S32 className::_smTypeId;                                                                       \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );      \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }            \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                       \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \   AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }          \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; }            \   ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_ABSTRACT_CONOBJECT( className )                                                  \   IMPLEMENT_NONINSTANTIABLE_CLASS( className, NULL )                                              \   END_IMPLEMENT_CLASS;                                                                            \   S32 className::_smTypeId;                                                                       \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );      \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }            \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                       \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \   ConcreteAbstractClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_CO_NETOBJECT_V1( className )                                                           \   IMPLEMENT_CLASS( className, NULL )                                                                    \   END_IMPLEMENT_CLASS;                                                                                  \   S32 className::_smTypeId;                                                                             \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );            \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                  \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                             \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \   AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }        \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }  \   ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep(), &Parent::__description )#define IMPLEMENT_CO_DATABLOCK_V1( className )                                                           \   IMPLEMENT_CLASS( className, NULL )                                                                    \   END_IMPLEMENT_CLASS;                                                                                  \   S32 className::_smTypeId;                                                                             \   SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" );            \   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                  \   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                             \   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \   AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                 \   AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }  \   ConcreteClassRep<className> className::dynClassRep(#className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep(), &Parent::__description )// Support for adding properties to classes CONOBJECT style.#define PROPERTY_TABLE( className )                                                                      \   namespace { namespace _ ## className {                                                                \      extern EnginePropertyTable _propTable;                                                             \   } }                                                                                                   \   template<> EnginePropertyTable&                                                                       \   ConcreteClassRep< className >::smPropertyTable = _ ## className::_propTable;                          \   namespace { namespace _ ## className {                                                                \      EnginePropertyTable::Property _props[] = {#define END_PROPERTY_TABLE                                                                               \         { NULL }                                                                                        \      };                                                                                                 \      EnginePropertyTable _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props );            \   } }/// @}//------------------------------------------------------------------------------// Protected field default get/set functions//// The reason for these functions is that it will save one branch per console// data request and script functions will still execute at the same speed as// before the modifications to allow protected static fields. These will just// inline and the code should be roughly the same size, and just as fast as// before the modifications. -pwinline bool defaultProtectedSetFn( void *object, const char *index, const char *data ){   return true;}inline bool defaultProtectedSetNotEmptyFn( void *object, const char *index, const char *data ){   return data && data[0];}inline const char *defaultProtectedGetFn( void *obj, const char *data ){   return data;}inline const char *emptyStringProtectedGetFn( void *obj, const char *data ){   return "";}inline bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName){   return true;}inline bool defaultProtectedNotSetFn(void* obj, const char *array, const char* data){   return false;}inline bool defaultProtectedNotWriteFn(void* obj, StringTableEntry pFieldName){   return false;}/// @}#endif //_CONSOLEOBJECT_H_
 |