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
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

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