Torque3D Documentation / _generateds / consoleObject.h

consoleObject.h

Engine/source/console/consoleObject.h

Legacy console object system.

More...

Classes:

class

Core functionality for class manipulation.

class

Interface class to the console.

Public User Defined

enum
NetClassGroups {
  NetClassGroupGame = 0
  NetClassGroupCommunity 
  NetClassGroup3 
  NetClassGroup4 
  NetClassGroupsCount 
}
enum
NetClassMasks {
  NetClassGroupGameMask = BIT(NetClassGroupGame)
  NetClassGroupCommunityMask = BIT(NetClassGroupCommunity)
}
enum
NetClassTypes {
  NetClassTypeObject = 0
  NetClassTypeDataBlock 
  NetClassTypeEvent 
  NetClassTypesCount 
}
enum
NetDirection {
  NetEventDirAny 
  NetEventDirServerToClient 
  NetEventDirClientToServer 
}
DECLARE_SCOPE(ConsoleAPI )
const char *
defaultProtectedGetFn(void * obj, const char * data)
define
addNamedField(fieldName, type, className) addField(#fieldName, type, (fieldName,className))
define
addNamedFieldV(fieldName, type, className, validator) addFieldV(#fieldName, type, (fieldName,className), validator)

ConsoleObject Macros

define
ConsoleDocClass(className, docString)    ( className, docString )

Add an auto-doc for a class.

define
DECLARE_CATEGORY(string)    static  char* __category() { return string; }
define
DECLARE_CONOBJECT(className)    ( className, Parent );                   \
   static  _smTypeId;                                 \
   static < className > dynClassRep;     \
   static * getParentStaticClassRep();   \
   static * getStaticClassRep();         \
   static < className > ptrRefType;         \
   static  getStaticWriteCustomTamlSchema();         \
   static * getContainerChildStaticClassRep();         \
   virtual * getClassRep() 
define
DECLARE_DESCRIPTION(string)    static  char* __description() { return string; }
define
END_PROPERTY_TABLE()          {  }                                                                                        \
      };                                                                                                 \
       _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props );            \
   } }
define
IMPLEMENT_ABSTRACT_CONOBJECT(className)    ( className,  )                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CO_DATABLOCK_V1(className)    ( className,  )                                                                    \
   ;                                                                                  \
    className::_smTypeId;                                                                             \
   < className > className::ptrRefType( "Type" #className "Ref" );            \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }                  \
   * className::getStaticClassRep() { return &dynClassRep; }                             \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return ; }  \
   <className> className::dynClassRep(#className, "Type" #className, &_smTypeId, , , 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CO_NETOBJECT_V1(className)    ( className,  )                                                                    \
   ;                                                                                  \
    className::_smTypeId;                                                                             \
   < className > className::ptrRefType( "Type" #className "Ref" );            \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }                  \
   * className::getStaticClassRep() { return &dynClassRep; }                             \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \
   * className::getContainerChildStaticClassRep() { return ; }        \
    className::getStaticWriteCustomTamlSchema() { return ; }  \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, , , 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CONOBJECT(className)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return ; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CONOBJECT_CHILDREN(className)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }        \
    className::getStaticWriteCustomTamlSchema() { return ; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA(className, schema)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }          \
    className::getStaticWriteCustomTamlSchema() { return schema; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
define
IMPLEMENT_CONOBJECT_SCHEMA(className, schema)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return schema; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
define
PROPERTY_TABLE(className)    namespace { namespace _ ## className {                                                                \
      extern  _propTable;                                                             \
   } }                                                                                                   \
   template<> &                                                                       \
   < className >::smPropertyTable = _ ## className::_propTable;                          \
   namespace { namespace _ ## className {                                                                \
       _props[] = {

Public Defines

define
DECLARE_ABSTRACT_CONOBJECT(className)    ( className, Parent );                \
   static  _smTypeId;                                       \
   static < className > dynClassRep;   \
   static * getParentStaticClassRep();         \
   static * getStaticClassRep();               \
   static < className > ptrRefType; \
   virtual * getClassRep() 

Public Functions

bool
defaultProtectedNotSetFn(void * obj, const char * array, const char * data)
bool
defaultProtectedSetFn(void * object, const char * index, const char * data)
bool
defaultProtectedSetNotEmptyFn(void * object, const char * index, const char * data)
const char *
emptyStringProtectedGetFn(void * obj, const char * data)

Detailed Description

Legacy console object system.

Public User Defined

NetClassGroups

Enumerator

NetClassGroupGame = 0
NetClassGroupCommunity
NetClassGroup3
NetClassGroup4
NetClassGroupsCount
NetClassMasks

Enumerator

NetClassGroupGameMask = BIT(NetClassGroupGame)
NetClassGroupCommunityMask = BIT(NetClassGroupCommunity)
NetClassTypes

Enumerator

NetClassTypeObject = 0
NetClassTypeDataBlock
NetClassTypeEvent
NetClassTypesCount
NetDirection

Enumerator

NetEventDirAny
NetEventDirServerToClient
NetEventDirClientToServer
DECLARE_SCOPE(ConsoleAPI )

defaultProtectedGetFn(void * obj, const char * data)

defaultProtectedWriteFn(void * obj, StringTableEntry pFieldName)

AbstractClassRep::FieldList sg_tempFieldList 
addNamedField(fieldName, type, className) addField(#fieldName, type, (fieldName,className))
addNamedFieldV(fieldName, type, className, validator) addFieldV(#fieldName, type, (fieldName,className), validator)

ConsoleObject Macros

ConsoleDocClass(className, docString)    ( className, docString )

Add an auto-doc for a class.

DECLARE_CATEGORY(string)    static  char* __category() { return string; }
DECLARE_CONOBJECT(className)    ( className, Parent );                   \
   static  _smTypeId;                                 \
   static < className > dynClassRep;     \
   static * getParentStaticClassRep();   \
   static * getStaticClassRep();         \
   static < className > ptrRefType;         \
   static  getStaticWriteCustomTamlSchema();         \
   static * getContainerChildStaticClassRep();         \
   virtual * getClassRep() 
DECLARE_DESCRIPTION(string)    static  char* __description() { return string; }
END_PROPERTY_TABLE()          {  }                                                                                        \
      };                                                                                                 \
       _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props );            \
   } }
IMPLEMENT_ABSTRACT_CONOBJECT(className)    ( className,  )                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CO_DATABLOCK_V1(className)    ( className,  )                                                                    \
   ;                                                                                  \
    className::_smTypeId;                                                                             \
   < className > className::ptrRefType( "Type" #className "Ref" );            \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }                  \
   * className::getStaticClassRep() { return &dynClassRep; }                             \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return ; }  \
   <className> className::dynClassRep(#className, "Type" #className, &_smTypeId, , , 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CO_NETOBJECT_V1(className)    ( className,  )                                                                    \
   ;                                                                                  \
    className::_smTypeId;                                                                             \
   < className > className::ptrRefType( "Type" #className "Ref" );            \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }                  \
   * className::getStaticClassRep() { return &dynClassRep; }                             \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }        \
   * className::getContainerChildStaticClassRep() { return ; }        \
    className::getStaticWriteCustomTamlSchema() { return ; }  \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, , , 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CONOBJECT(className)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return ; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CONOBJECT_CHILDREN(className)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }        \
    className::getStaticWriteCustomTamlSchema() { return ; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA(className, schema)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }          \
    className::getStaticWriteCustomTamlSchema() { return schema; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
IMPLEMENT_CONOBJECT_SCHEMA(className, schema)    ( className,  )                                                              \
   ;                                                                            \
    className::_smTypeId;                                                                       \
   < className > className::ptrRefType( "Type" #className "Ref" );      \
   AbstractClassRep* className::getClassRep()  { return &className::dynClassRep; }            \
   * className::getStaticClassRep() { return &dynClassRep; }                       \
   * className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }  \
   * className::getContainerChildStaticClassRep() { return ; }                 \
    className::getStaticWriteCustomTamlSchema() { return schema; }            \
   <className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
PROPERTY_TABLE(className)    namespace { namespace _ ## className {                                                                \
      extern  _propTable;                                                             \
   } }                                                                                                   \
   template<> &                                                                       \
   < className >::smPropertyTable = _ ## className::_propTable;                          \
   namespace { namespace _ ## className {                                                                \
       _props[] = {

Public Defines

DECLARE_ABSTRACT_CONOBJECT(className)    ( className, Parent );                \
   static  _smTypeId;                                       \
   static < className > dynClassRep;   \
   static * getParentStaticClassRep();         \
   static * getStaticClassRep();               \
   static < className > ptrRefType; \
   virtual * getClassRep() 

Public Functions

defaultProtectedNotSetFn(void * obj, const char * array, const char * data)

defaultProtectedNotWriteFn(void * obj, StringTableEntry pFieldName)

defaultProtectedSetFn(void * object, const char * index, const char * data)

defaultProtectedSetNotEmptyFn(void * object, const char * index, const char * data)

emptyStringProtectedGetFn(void * obj, const char * data)

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