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