consoleObject.h
Engine/source/console/consoleObject.h
Legacy console object system.
Classes:
class
Core functionality for class manipulation.
class
Helper class for AbstractClassRep.
class
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)
bool
defaultProtectedWriteFn(void * obj, StringTableEntry pFieldName)
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
defaultProtectedNotWriteFn(void * obj, StringTableEntry pFieldName)
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