Torque3D Documentation / _generateds / consoleObject.cpp

consoleObject.cpp

Engine/source/console/consoleObject.cpp

More...

Public Variables

char
replacebuf [1024]

Public Functions

DefineEngineFunction(dumpNetStats , void , () , "@brief Dumps network statistics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "The returned <<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>>avg</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>> , < <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >min</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >max</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > values are in bits sent per update. " "The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >num</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > value is the total number of events <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">collected.\n</a>" " @note This method only works when TORQUE_NET_STATS is defined in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">torqueConfig.h.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )
DefineEngineFunction(enumerateConsoleClasses , const char * , (const char *className) , ("") , "@brief Returns a list of classes that derive from the named <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "If the named class is omitted this dumps all the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@param className The optional base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@return A tab delimited list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )
DefineEngineFunction(enumerateConsoleClassesByCategory , const char * , (String category) , "@brief Provide a list of classes that belong <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">category.\n\n</a>" "@param category The category <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@return A tab delimited list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )
DefineEngineFunction(getCategoryOfClass , const char * , (const char *className) , "@brief Returns the category of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@param className The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@ingroup Console" )
DefineEngineFunction(getDescriptionOfClass , const char * , (const char *className) , "@brief Returns the description string <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the named <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@param className The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@return The class description in string <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">format.\n</a>" "@ingroup Console" )
DefineEngineFunction(isClass , bool , (const char *identifier) , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the passed identifier is the name of a declared <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@ingroup Console" )
DefineEngineFunction(isMemberOfClass , bool , (const char *className, const char *superClassName) , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the class is derived from the super <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "If either class doesn'<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a21feba301403a65090791a94f26c9d92">t</a> exist this returns <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">false.\n</a>" "@param className The class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param superClassName The super class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@ingroup Console" )
DefineEngineFunction(linkNamespaces , bool , (String childNSName, String parentNSName) , "@brief Links childNS <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parentNS.\n\n</a>" "Links childNS <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> parentNS, or nothing <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> parentNS is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">NULL.\n</a>" "Will unlink the namespace from previous namespace <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> a parent already <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">internal\n</a>" )
DefineEngineFunction(sizeof , S32 , (const char *objectOrClass) , "@brief Determines the memory consumption of a class or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param objectOrClass The object or class being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">measured.\n</a>" "@return Returns the total <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of an object in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bytes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Debugging\n</a>" )
IMPLEMENT_NONINSTANTIABLE_CLASS(ConsoleObject , "Legacy console system root class. Will disappear." )
IMPLEMENT_SCOPE(ConsoleAPI , Console , "Functionality related <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the legacy TorqueScript console system." )
const char *
returnClassList(Vector< AbstractClassRep * > & classes, U32 bufSize)
char *
suppressSpaces(const char * in_pname)

Detailed Description

Public Variables

char replacebuf [1024]
AbstractClassRep::FieldList sg_tempFieldList (__FILE__, __LINE__)

Public Functions

ACRCompare(const void * aptr, const void * bptr)

DefineEngineFunction(dumpNetStats , void , () , "@brief Dumps network statistics <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n\n</a>" "The returned <<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>>avg</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a>> , < <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >min</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >max</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > values are in bits sent per update. " "The< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >num</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > value is the total number of events <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">collected.\n</a>" " @note This method only works when TORQUE_NET_STATS is defined in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">torqueConfig.h.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Networking\n</a>" )

DefineEngineFunction(enumerateConsoleClasses , const char * , (const char *className) , ("") , "@brief Returns a list of classes that derive from the named <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "If the named class is omitted this dumps all the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@param className The optional base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@return A tab delimited list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )

DefineEngineFunction(enumerateConsoleClassesByCategory , const char * , (String category) , "@brief Provide a list of classes that belong <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">category.\n\n</a>" "@param category The category <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@return A tab delimited list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )

DefineEngineFunction(getCategoryOfClass , const char * , (const char *className) , "@brief Returns the category of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@param className The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@ingroup Console" )

DefineEngineFunction(getDescriptionOfClass , const char * , (const char *className) , "@brief Returns the description string <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the named <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@param className The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@return The class description in string <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">format.\n</a>" "@ingroup Console" )

DefineEngineFunction(isClass , bool , (const char *identifier) , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the passed identifier is the name of a declared <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "@ingroup Console" )

DefineEngineFunction(isMemberOfClass , bool , (const char *className, const char *superClassName) , "@brief Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the class is derived from the super <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n\n</a>" "If either class doesn'<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a21feba301403a65090791a94f26c9d92">t</a> exist this returns <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">false.\n</a>" "@param className The class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param superClassName The super class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@ingroup Console" )

DefineEngineFunction(linkNamespaces , bool , (String childNSName, String parentNSName) , "@brief Links childNS <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parentNS.\n\n</a>" "Links childNS <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> parentNS, or nothing <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> parentNS is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">NULL.\n</a>" "Will unlink the namespace from previous namespace <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> a parent already <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">internal\n</a>" )

DefineEngineFunction(sizeof , S32 , (const char *objectOrClass) , "@brief Determines the memory consumption of a class or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param objectOrClass The object or class being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">measured.\n</a>" "@return Returns the total <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of an object in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bytes.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Debugging\n</a>" )

IMPLEMENT_NONINSTANTIABLE_CLASS(ConsoleObject , "Legacy console system root class. Will disappear." )

IMPLEMENT_SCOPE(ConsoleAPI , Console , "Functionality related <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the legacy TorqueScript console system." )

returnClassList(Vector< AbstractClassRep * > & classes, U32 bufSize)

suppressSpaces(const char * in_pname)

  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#include "platform/platform.h"
 25#include "console/consoleObject.h"
 26
 27#include "core/stringTable.h"
 28#include "core/crc.h"
 29#include "core/dataChunker.h"
 30#include "console/console.h"
 31#include "console/consoleInternal.h"
 32#include "console/typeValidators.h"
 33#include "console/simObject.h"
 34#include "console/engineTypes.h"
 35#include "console/engineAPI.h"
 36
 37
 38IMPLEMENT_SCOPE( ConsoleAPI, Console,,
 39   "Functionality related to the legacy TorqueScript console system." );
 40
 41IMPLEMENT_NONINSTANTIABLE_CLASS( ConsoleObject,
 42   "Legacy console system root class.  Will disappear." )
 43END_IMPLEMENT_CLASS;
 44
 45
 46AbstractClassRep *                 AbstractClassRep::classLinkList = NULL;
 47AbstractClassRep::FieldList        sg_tempFieldList( __FILE__, __LINE__ );
 48U32                                AbstractClassRep::NetClassCount  [NetClassGroupsCount][NetClassTypesCount] = {{"{"}}0, },};
 49U32                                AbstractClassRep::NetClassBitSize[NetClassGroupsCount][NetClassTypesCount] = {{"{"}}0, },};
 50
 51AbstractClassRep **                AbstractClassRep::classTable[NetClassGroupsCount][NetClassTypesCount];
 52
 53U32                                AbstractClassRep::classCRC[NetClassGroupsCount] = {CRC::INITIAL_CRC_VALUE, };
 54bool                               AbstractClassRep::initialized = false;
 55
 56
 57
 58//-----------------------------------------------------------------------------
 59AbstractClassRep* AbstractClassRep::findFieldRoot(StringTableEntry fieldName)
 60{
 61   // Find the field.
 62   const Field* pField = findField(fieldName);
 63
 64   // Finish if not found.
 65   if (pField == NULL)
 66      return NULL;
 67
 68   // We're the root if we have no parent.
 69   if (getParentClass() == NULL)
 70      return this;
 71
 72   // Find the field root via the parent.
 73   AbstractClassRep* pFieldRoot = getParentClass()->findFieldRoot(fieldName);
 74
 75   // We're the root if the parent does not have it else return the field root.
 76   return pFieldRoot == NULL ? this : pFieldRoot;
 77}
 78
 79void AbstractClassRep::init()
 80{
 81   // Only add the renderable and selectable globals for
 82   // classes derived from SceneObject which are the only
 83   // objects for which these work.
 84   if ( isSubclassOf( "SceneObject" ) )
 85   {
 86      Con::addVariable( avar( "$%s::isRenderable", getClassName() ), TypeBool, &mIsRenderEnabled,
 87         "@brief Disables rendering of all instances of this type.\n\n" );
 88
 89      Con::addVariable( avar( "$%s::isSelectable", getClassName() ), TypeBool, &mIsSelectionEnabled,
 90         "@brief Disables selection of all instances of this type.\n\n" );
 91   }
 92}
 93
 94const AbstractClassRep::Field *AbstractClassRep::findField(StringTableEntry name) const
 95{
 96   for(U32 i = 0; i < mFieldList.size(); i++)
 97      if(mFieldList[i].pFieldname == name)
 98         return &mFieldList[i];
 99
100   return NULL;
101}
102
103AbstractClassRep* AbstractClassRep::findClassRep(const char* in_pClassName)
104{
105   AssertFatal(initialized,
106      "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize().");
107
108   for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
109      if (!dStricmp(walk->getClassName(), in_pClassName))
110         return walk;
111
112   return NULL;
113}
114
115AbstractClassRep* AbstractClassRep::findClassRep( U32 groupId, U32 typeId, U32 classId )
116{
117   AssertFatal(initialized,
118      "AbstractClassRep::findClasRep() - Tried to create an object before AbstractClassRep::initialize().");
119   AssertFatal(classId < NetClassCount[groupId][typeId],
120      "AbstractClassRep::findClassRep() - Class id out of range.");
121   AssertFatal(classTable[groupId][typeId][classId] != NULL,
122      "AbstractClassRep::findClassRep() - No class with requested ID type.");
123
124   // Look up the specified class and create it.
125   if(classTable[groupId][typeId][classId])
126      return classTable[groupId][typeId][classId];
127      
128   return NULL;
129}
130
131//--------------------------------------
132void AbstractClassRep::registerClassRep(AbstractClassRep* in_pRep)
133{
134   AssertFatal(in_pRep != NULL, "AbstractClassRep::registerClassRep was passed a NULL pointer!");
135
136#ifdef TORQUE_DEBUG  // assert if this class is already registered.
137   for(AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
138   {
139      AssertFatal(dStrcmp(in_pRep->mClassName, walk->mClassName),
140         "Duplicate class name registered in AbstractClassRep::registerClassRep()");
141   }
142#endif
143
144   in_pRep->nextClass = classLinkList;
145   classLinkList = in_pRep;
146}
147
148//--------------------------------------
149void AbstractClassRep::removeClassRep(AbstractClassRep* in_pRep)
150{
151   for( AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass )
152   {
153      // This is the case that will most likely get hit.
154      if( walk->nextClass == in_pRep ) 
155         walk->nextClass = walk->nextClass->nextClass;
156      else if( walk == in_pRep )
157      {
158         AssertFatal( in_pRep == classLinkList, "Pat failed in his logic for un linking RuntimeClassReps from the class linked list" );
159         classLinkList = in_pRep->nextClass;
160      }
161   }
162}
163
164//--------------------------------------
165
166ConsoleObject* AbstractClassRep::create(const char* in_pClassName)
167{
168   AssertFatal(initialized,
169      "AbstractClassRep::create() - Tried to create an object before AbstractClassRep::initialize().");
170
171   const AbstractClassRep *rep = AbstractClassRep::findClassRep(in_pClassName);
172   if(rep)
173      return rep->create();
174
175   AssertWarn(0, avar("Couldn't find class rep for dynamic class: %s", in_pClassName));
176   return NULL;
177}
178
179//--------------------------------------
180ConsoleObject* AbstractClassRep::create(const U32 groupId, const U32 typeId, const U32 in_classId)
181{
182   AbstractClassRep* classRep = findClassRep( groupId, typeId, in_classId );
183   if( !classRep )
184      return NULL;
185
186   return classRep->create();
187}
188
189//--------------------------------------
190
191static S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr)
192{
193   const AbstractClassRep *a = *((const AbstractClassRep **) aptr);
194   const AbstractClassRep *b = *((const AbstractClassRep **) bptr);
195
196   if(a->mClassType != b->mClassType)
197      return a->mClassType - b->mClassType;
198   return dStrnatcasecmp(a->getClassName(), b->getClassName());
199}
200
201void AbstractClassRep::initialize()
202{
203   AssertFatal(!initialized, "Duplicate call to AbstractClassRep::initialize()!");
204   Vector<AbstractClassRep*> dynamicTable(__FILE__, __LINE__);
205
206   AbstractClassRep *walk;
207
208   // Initialize namespace references...
209   for (walk = classLinkList; walk; walk = walk->nextClass)
210   {
211      walk->mNamespace = Con::lookupNamespace(StringTable->insert(walk->getClassName()));
212      walk->mNamespace->mUsage = walk->getDocString();
213      walk->mNamespace->mClassRep = walk;
214   }
215
216   // Initialize field lists... (and perform other console registration).
217   for (walk = classLinkList; walk; walk = walk->nextClass)
218   {
219      // sg_tempFieldList is used as a staging area for field lists
220      // (see addField, addGroup, etc.)
221      sg_tempFieldList.setSize(0);
222
223      walk->init();
224
225      // So if we have things in it, copy it over...
226      if (sg_tempFieldList.size() != 0)
227         walk->mFieldList = sg_tempFieldList;
228
229      // And of course delete it every round.
230      sg_tempFieldList.clear();
231   }
232
233   // Calculate counts and bit sizes for the various NetClasses.
234   for (U32 group = 0; group < NetClassGroupsCount; group++)
235   {
236      U32 groupMask = 1 << group;
237
238      // Specifically, for each NetClass of each NetGroup...
239      for(U32 type = 0; type < NetClassTypesCount; type++)
240      {
241         // Go through all the classes and find matches...
242         for (walk = classLinkList; walk; walk = walk->nextClass)
243         {
244            if(walk->mClassType == type && walk->mClassGroupMask & groupMask)
245               dynamicTable.push_back(walk);
246         }
247
248         // Set the count for this NetGroup and NetClass
249         NetClassCount[group][type] = dynamicTable.size();
250         if(!NetClassCount[group][type])
251            continue; // If no classes matched, skip to next.
252
253         // Sort by type and then by name.
254         dQsort((void *) &dynamicTable[0], dynamicTable.size(), sizeof(AbstractClassRep *), ACRCompare);
255
256         // Allocate storage in the classTable
257         classTable[group][type] = new AbstractClassRep*[NetClassCount[group][type]];
258
259         // Fill this in and assign class ids for this group.
260         for(U32 i = 0; i < NetClassCount[group][type];i++)
261         {
262            classTable[group][type][i] = dynamicTable[i];
263            dynamicTable[i]->mClassId[group] = i;
264         }
265
266         // And calculate the size of bitfields for this group and type.
267         NetClassBitSize[group][type] =
268               getBinLog2(getNextPow2(NetClassCount[group][type] + 1));
269         AssertFatal(NetClassCount[group][type] < (1 << NetClassBitSize[group][type]), "NetClassBitSize too small!");
270
271         dynamicTable.clear();
272      }
273   }
274
275   // Ok, we're golden!
276   initialized = true;
277}
278
279void AbstractClassRep::shutdown()
280{
281   AssertFatal( initialized, "AbstractClassRep::shutdown - not initialized" );
282
283   // Release storage allocated to the class table.
284
285   for (U32 group = 0; group < NetClassGroupsCount; group++)
286      for(U32 type = 0; type < NetClassTypesCount; type++)
287         if( classTable[ group ][ type ] )
288            SAFE_DELETE_ARRAY( classTable[ group ][ type ] );
289
290   initialized = false;
291}
292
293AbstractClassRep *AbstractClassRep::getCommonParent( const AbstractClassRep *otherClass ) const
294{
295   // CodeReview: This may be a noob way of doing it. There may be some kind of
296   // super-spiffy algorithm to do what the code below does, but this appeared
297   // to make sense to me, and it is pretty easy to see what it is doing [6/23/2007 Pat]
298
299   static VectorPtr<AbstractClassRep*> thisClassHeirarchy;
300   thisClassHeirarchy.clear();
301
302   AbstractClassRep *walk = const_cast<AbstractClassRep *>( this );
303
304   while( walk != NULL )
305   {
306      thisClassHeirarchy.push_front( walk );
307      walk = walk->getParentClass();
308   }
309
310   static VectorPtr<AbstractClassRep*> compClassHeirarchy;
311   compClassHeirarchy.clear();
312   walk = const_cast<AbstractClassRep *>( otherClass );
313   while( walk != NULL )
314   {
315      compClassHeirarchy.push_front( walk );
316      walk = walk->getParentClass();
317   }
318
319   // Make sure we only iterate over the list the number of times we can
320   S32 maxIterations = getMin( compClassHeirarchy.size(), thisClassHeirarchy.size() );
321
322   U32 i = 0;
323   for( ; i < maxIterations; i++ )
324   {
325      if( compClassHeirarchy[i] != thisClassHeirarchy[i] )
326         break;
327   }
328
329   return compClassHeirarchy[i];
330}
331
332//------------------------------------------------------------------------------
333//-------------------------------------- ConsoleObject
334
335static char replacebuf[1024];
336static char* suppressSpaces(const char* in_pname)
337{
338   U32 i = 0;
339   char chr;
340   do
341   {
342      chr = in_pname[i];
343      replacebuf[i++] = (chr != 32) ? chr : '_';
344   } while(chr);
345
346   return replacebuf;
347}
348
349void ConsoleObject::addGroup(const char* in_pGroupname, const char* in_pGroupDocs)
350{
351   // Remove spaces.
352   char* pFieldNameBuf = suppressSpaces(in_pGroupname);
353
354   // Append group type to fieldname.
355   dStrcat(pFieldNameBuf, "_begingroup");
356
357   // Create Field.
358   AbstractClassRep::Field f;
359   f.pFieldname   = StringTable->insert(pFieldNameBuf);
360   f.pGroupname   = in_pGroupname;
361
362   if(in_pGroupDocs)
363      f.pFieldDocs   = in_pGroupDocs;
364
365   f.type         = AbstractClassRep::StartGroupFieldType;
366   f.elementCount = 0;
367   f.groupExpand  = false;
368   f.validator    = NULL;
369   f.setDataFn    = &defaultProtectedSetFn;
370   f.getDataFn    = &defaultProtectedGetFn;
371   f.writeDataFn = &defaultProtectedWriteFn;
372
373   // Add to field list.
374   sg_tempFieldList.push_back(f);
375}
376
377void ConsoleObject::endGroup(const char*  in_pGroupname)
378{
379   // Remove spaces.
380   char* pFieldNameBuf = suppressSpaces(in_pGroupname);
381
382   // Append group type to fieldname.
383   dStrcat(pFieldNameBuf, "_endgroup");
384
385   // Create Field.
386   AbstractClassRep::Field f;
387   f.pFieldname   = StringTable->insert(pFieldNameBuf);
388   f.pGroupname   = in_pGroupname;
389   f.type         = AbstractClassRep::EndGroupFieldType;
390   f.groupExpand  = false;
391   f.validator    = NULL;
392   f.setDataFn    = &defaultProtectedSetFn;
393   f.getDataFn    = &defaultProtectedGetFn;
394   f.writeDataFn = &defaultProtectedWriteFn;
395   f.elementCount = 0;
396
397   // Add to field list.
398   sg_tempFieldList.push_back(f);
399}
400
401void ConsoleObject::addArray( const char *arrayName, S32 count )
402{
403   char *nameBuff = suppressSpaces(arrayName);
404   dStrcat(nameBuff, "_beginarray");
405
406   // Create Field.
407   AbstractClassRep::Field f;
408   f.pFieldname   = StringTable->insert(nameBuff);
409   f.pGroupname   = arrayName;
410
411   f.type         = AbstractClassRep::StartArrayFieldType;
412   f.elementCount = count;
413   f.groupExpand  = false;
414   f.validator    = NULL;
415   f.setDataFn    = &defaultProtectedSetFn;
416   f.getDataFn    = &defaultProtectedGetFn;
417   f.writeDataFn = &defaultProtectedWriteFn;
418
419   // Add to field list.
420   sg_tempFieldList.push_back(f);
421}
422
423void ConsoleObject::endArray( const char *arrayName )
424{
425   char *nameBuff = suppressSpaces(arrayName);
426   dStrcat(nameBuff, "_endarray");
427
428   // Create Field.
429   AbstractClassRep::Field f;
430   f.pFieldname   = StringTable->insert(nameBuff);
431   f.pGroupname   = arrayName;
432   f.type         = AbstractClassRep::EndArrayFieldType;
433   f.groupExpand  = false;
434   f.validator    = NULL;
435   f.setDataFn    = &defaultProtectedSetFn;
436   f.getDataFn    = &defaultProtectedGetFn;
437   f.writeDataFn = &defaultProtectedWriteFn;
438   f.elementCount = 0;
439
440   // Add to field list.
441   sg_tempFieldList.push_back(f);
442}
443
444void ConsoleObject::addField(const char*  in_pFieldname,
445                       const U32 in_fieldType,
446                       const dsize_t in_fieldOffset,
447                       const char* in_pFieldDocs,
448                       U32 flags )
449{
450   addField(
451      in_pFieldname,
452      in_fieldType,
453      in_fieldOffset,
454      1,
455      in_pFieldDocs,
456      flags );
457}
458
459void ConsoleObject::addField(const char*  in_pFieldname,
460   const U32 in_fieldType,
461   const dsize_t in_fieldOffset,
462   AbstractClassRep::WriteDataNotify in_writeDataFn,
463   const char* in_pFieldDocs,
464   U32 flags)
465{
466   addField(
467      in_pFieldname,
468      in_fieldType,
469      in_fieldOffset,
470      in_writeDataFn,
471      1,
472      in_pFieldDocs,
473      flags);
474}
475
476void ConsoleObject::addField(const char*  in_pFieldname,
477   const U32 in_fieldType,
478   const dsize_t in_fieldOffset,
479   const U32 in_elementCount,
480   const char* in_pFieldDocs,
481   U32 flags)
482{
483   addField(in_pFieldname,
484      in_fieldType,
485      in_fieldOffset,
486      &defaultProtectedWriteFn,
487      in_elementCount,
488      in_pFieldDocs,
489      flags);
490}
491
492void ConsoleObject::addField(const char*  in_pFieldname,
493   const U32 in_fieldType,
494   const dsize_t in_fieldOffset,
495   AbstractClassRep::WriteDataNotify in_writeDataFn,
496   const U32 in_elementCount,
497   const char* in_pFieldDocs,
498   U32 flags)
499{
500   AbstractClassRep::Field f;
501   f.pFieldname = StringTable->insert(in_pFieldname);
502
503   if (in_pFieldDocs)
504      f.pFieldDocs = in_pFieldDocs;
505
506   f.type = in_fieldType;
507   f.offset = in_fieldOffset;
508   f.elementCount = in_elementCount;
509   f.validator = NULL;
510   f.flag = flags;
511
512   f.setDataFn = &defaultProtectedSetFn;
513   f.getDataFn = &defaultProtectedGetFn;
514   f.writeDataFn = in_writeDataFn;
515
516   ConsoleBaseType* conType = ConsoleBaseType::getType(in_fieldType);
517   AssertFatal(conType, "ConsoleObject::addField - invalid console type");
518   f.table = conType->getEnumTable();
519
520   sg_tempFieldList.push_back(f);
521}
522
523void ConsoleObject::addProtectedField(const char*  in_pFieldname,
524   const U32 in_fieldType,
525   const dsize_t in_fieldOffset,
526   AbstractClassRep::SetDataNotify in_setDataFn,
527   AbstractClassRep::GetDataNotify in_getDataFn,
528   const char* in_pFieldDocs,
529   U32 flags)
530{
531   addProtectedField(
532      in_pFieldname,
533      in_fieldType,
534      in_fieldOffset,
535      in_setDataFn,
536      in_getDataFn,
537      &defaultProtectedWriteFn,
538      1,
539      in_pFieldDocs,
540      flags);
541}
542
543void ConsoleObject::addProtectedField(const char*  in_pFieldname,
544   const U32 in_fieldType,
545   const dsize_t in_fieldOffset,
546   AbstractClassRep::SetDataNotify in_setDataFn,
547   AbstractClassRep::GetDataNotify in_getDataFn,
548   AbstractClassRep::WriteDataNotify in_writeDataFn,
549   const char* in_pFieldDocs,
550   U32 flags)
551{
552   addProtectedField(
553      in_pFieldname,
554      in_fieldType,
555      in_fieldOffset,
556      in_setDataFn,
557      in_getDataFn,
558      in_writeDataFn,
559      1,
560      in_pFieldDocs,
561      flags);
562}
563
564void ConsoleObject::addProtectedField(const char*  in_pFieldname,
565   const U32 in_fieldType,
566   const dsize_t in_fieldOffset,
567   AbstractClassRep::SetDataNotify in_setDataFn,
568   AbstractClassRep::GetDataNotify in_getDataFn,
569   const U32 in_elementCount,
570   const char* in_pFieldDocs,
571   U32 flags)
572{
573   addProtectedField(
574      in_pFieldname,
575      in_fieldType,
576      in_fieldOffset,
577      in_setDataFn,
578      in_getDataFn,
579      &defaultProtectedWriteFn,
580      in_elementCount,
581      in_pFieldDocs,
582      flags);
583}
584void ConsoleObject::addProtectedField(const char*  in_pFieldname,
585   const U32 in_fieldType,
586   const dsize_t in_fieldOffset,
587   AbstractClassRep::SetDataNotify in_setDataFn,
588   AbstractClassRep::GetDataNotify in_getDataFn,
589   AbstractClassRep::WriteDataNotify in_writeDataFn,
590   const U32 in_elementCount,
591   const char* in_pFieldDocs,
592   U32 flags)
593{
594   AbstractClassRep::Field f;
595   f.pFieldname = StringTable->insert(in_pFieldname);
596
597   if (in_pFieldDocs)
598      f.pFieldDocs = in_pFieldDocs;
599
600   f.type = in_fieldType;
601   f.offset = in_fieldOffset;
602   f.elementCount = in_elementCount;
603   f.validator = NULL;
604   f.flag = flags;
605
606   f.setDataFn = in_setDataFn;
607   f.getDataFn = in_getDataFn;
608   f.writeDataFn = in_writeDataFn;
609
610   ConsoleBaseType* conType = ConsoleBaseType::getType(in_fieldType);
611   AssertFatal(conType, "ConsoleObject::addProtectedField - invalid console type");
612   f.table = conType->getEnumTable();
613
614   sg_tempFieldList.push_back(f);
615}
616
617void ConsoleObject::addFieldV(const char*  in_pFieldname,
618                       const U32 in_fieldType,
619                       const dsize_t in_fieldOffset,
620                       TypeValidator *v,
621                       const char* in_pFieldDocs)
622{
623   AbstractClassRep::Field f;
624   f.pFieldname   = StringTable->insert(in_pFieldname);
625   if(in_pFieldDocs)
626      f.pFieldDocs   = in_pFieldDocs;
627   f.type         = in_fieldType;
628   f.offset       = in_fieldOffset;
629   f.elementCount = 1;
630   f.table        = NULL;
631   f.setDataFn    = &defaultProtectedSetFn;
632   f.getDataFn    = &defaultProtectedGetFn;
633   f.writeDataFn = &defaultProtectedWriteFn;
634   f.validator    = v;
635   v->fieldIndex  = sg_tempFieldList.size();
636
637   sg_tempFieldList.push_back(f);
638}
639
640void ConsoleObject::addDeprecatedField(const char *fieldName)
641{
642   AbstractClassRep::Field f;
643   f.pFieldname   = StringTable->insert(fieldName);
644   f.type         = AbstractClassRep::DeprecatedFieldType;
645   f.offset       = 0;
646   f.elementCount = 0;
647   f.table        = NULL;
648   f.validator    = NULL;
649   f.setDataFn    = &defaultProtectedSetFn;
650   f.getDataFn    = &defaultProtectedGetFn;
651   f.writeDataFn = &defaultProtectedWriteFn;
652
653   sg_tempFieldList.push_back(f);
654}
655
656
657bool ConsoleObject::removeField(const char* in_pFieldname)
658{
659   for (U32 i = 0; i < sg_tempFieldList.size(); i++) {
660      if (dStricmp(in_pFieldname, sg_tempFieldList[i].pFieldname) == 0) {
661         sg_tempFieldList.erase(i);
662         return true;
663      }
664   }
665
666   return false;
667}
668
669//--------------------------------------
670void ConsoleObject::initPersistFields()
671{
672}
673
674//--------------------------------------
675void ConsoleObject::consoleInit()
676{
677}
678
679//--------------------------------------
680AbstractClassRep* ConsoleObject::getClassRep() const
681{
682   return NULL;
683}
684
685String ConsoleObject::_getLogMessage(const char* fmt, va_list args) const
686{
687   String objClass = "UnknownClass";
688   if(getClassRep())
689      objClass = getClassRep()->getClassName();
690   
691   String formattedMessage = String::VToString(fmt, args);
692   return String::ToString("%s - Object at %x - %s", 
693      objClass.c_str(), this, formattedMessage.c_str());
694}
695
696void ConsoleObject::logMessage(const char* fmt, ...) const
697{
698   va_list args;
699   va_start(args, fmt);
700   Con::printf(_getLogMessage(fmt, args));
701   va_end(args);
702}
703
704void ConsoleObject::logWarning(const char* fmt, ...) const
705{
706   va_list args;
707   va_start(args, fmt);
708   Con::warnf(_getLogMessage(fmt, args));
709   va_end(args);
710}
711
712void ConsoleObject::logError(const char* fmt, ...) const
713{
714   va_list args;
715   va_start(args, fmt);
716   Con::errorf(_getLogMessage(fmt, args));
717   va_end(args);
718}
719
720
721//------------------------------------------------------------------------------
722
723static const char* returnClassList( Vector< AbstractClassRep*>& classes, U32 bufSize )
724{
725   if( !classes.size() )
726      return "";
727      
728   dQsort( classes.address(), classes.size(), sizeof( AbstractClassRep* ), ACRCompare );
729
730   char* ret = Con::getReturnBuffer( bufSize );
731   dStrcpy( ret, classes[ 0 ]->getClassName() );
732   for( U32 i = 1; i < classes.size(); i ++ )
733   {
734      dStrcat( ret, "\t" );
735      dStrcat( ret, classes[ i ]->getClassName() );
736   }
737   
738   return ret;
739}
740
741//------------------------------------------------------------------------------
742
743DefineEngineFunction( isClass, bool,  ( const char* identifier ),,
744            "@brief Returns true if the passed identifier is the name of a declared class.\n\n"
745            "@ingroup Console")
746{
747   AbstractClassRep* rep = AbstractClassRep::findClassRep( identifier );
748   return rep != NULL;
749}
750
751DefineEngineFunction( isMemberOfClass, bool, ( const char* className, const char* superClassName ),,
752   "@brief Returns true if the class is derived from the super class.\n\n"
753   "If either class doesn't exist this returns false.\n"
754   "@param className The class name.\n"
755   "@param superClassName The super class to look for.\n"
756   "@ingroup Console")
757{
758   AbstractClassRep *pRep = AbstractClassRep::findClassRep( className );
759   while (pRep)
760   {
761      if( !dStricmp( pRep->getClassName(), superClassName ) )
762         return true;
763      pRep = pRep->getParentClass();
764   }
765   return false;
766}
767
768DefineEngineFunction( getDescriptionOfClass, const char*, ( const char* className ),,
769            "@brief Returns the description string for the named class.\n\n"
770            "@param className The name of the class.\n"
771            "@return The class description in string format.\n"
772            "@ingroup Console")
773{
774   AbstractClassRep* rep = AbstractClassRep::findClassRep( className );
775   if( rep )
776      return rep->getDescription();
777
778   Con::errorf( "getDescriptionOfClass - no class called '%s'", className );
779   return "";
780}
781
782DefineEngineFunction( getCategoryOfClass, const char*,  ( const char* className ),,
783            "@brief Returns the category of the given class.\n\n"
784            "@param className The name of the class.\n"
785            "@ingroup Console")
786{
787   AbstractClassRep* rep = AbstractClassRep::findClassRep( className );
788   if( rep )
789      return rep->getCategory();
790
791   Con::errorf( "getCategoryOfClass - no class called '%s'", className );
792   return "";
793}
794
795DefineEngineFunction( enumerateConsoleClasses, const char*, ( const char* className ), ( "" ),
796            "@brief Returns a list of classes that derive from the named class.\n\n"
797            "If the named class is omitted this dumps all the classes.\n"
798            "@param className The optional base class name.\n"
799            "@return A tab delimited list of classes.\n"
800            "@ingroup Editors\n"
801            "@internal")
802{
803   AbstractClassRep *base = NULL;    
804   if(className && *className)
805   {
806      base = AbstractClassRep::findClassRep(className);
807      if(!base)
808         return "";
809   }
810   
811   Vector<AbstractClassRep*> classes;
812   U32 bufSize = 0;
813   for(AbstractClassRep *rep = AbstractClassRep::getClassList(); rep; rep = rep->getNextClass())
814   {
815      if( !base || rep->isClass(base))
816      {
817         classes.push_back(rep);
818         bufSize += dStrlen(rep->getClassName()) + 1;
819      }
820   }
821
822   return returnClassList( classes, bufSize );
823}
824
825DefineEngineFunction( enumerateConsoleClassesByCategory, const char*, ( String category ),,
826            "@brief Provide a list of classes that belong to the given category.\n\n"
827            "@param category The category name.\n"
828            "@return A tab delimited list of classes.\n"
829            "@ingroup Editors\n"
830            "@internal")
831{
832   U32 categoryLength = category.length();
833   
834   U32 bufSize = 0;
835   Vector< AbstractClassRep*> classes;
836   
837   for( AbstractClassRep* rep = AbstractClassRep::getClassList(); rep != NULL; rep = rep->getNextClass() )
838   {
839      const String& repCategory = rep->getCategory();
840      
841      if( repCategory.length() >= categoryLength
842          && ( repCategory.compare( category, categoryLength, String::NoCase ) == 0 )
843          && ( repCategory[ categoryLength ] == ' ' || repCategory[ categoryLength ] == '\0' ) )
844      {
845         classes.push_back( rep );
846         bufSize += dStrlen( rep->getClassName() + 1 );
847      }
848   }
849
850   return returnClassList( classes, bufSize );
851}
852
853DefineEngineFunction( dumpNetStats, void, (),,
854   "@brief Dumps network statistics for each class to the console.\n\n"
855
856   "The returned <i>avg</i>, <i>min</i> and <i>max</i> values are in bits sent per update.  "
857   "The <i>num</i> value is the total number of events collected.\n"
858
859   "@note This method only works when TORQUE_NET_STATS is defined in torqueConfig.h.\n"
860   "@ingroup Networking\n" )
861{
862#ifdef TORQUE_NET_STATS
863   for (AbstractClassRep * rep = AbstractClassRep::getClassList(); rep; rep = rep->getNextClass())
864   {
865      if (rep->mNetStatPack.numEvents || rep->mNetStatUnpack.numEvents || rep->mNetStatWrite.numEvents || rep->mNetStatRead.numEvents)
866      {
867         Con::printf("class %s net info",rep->getClassName());
868         if (rep->mNetStatPack.numEvents)
869            Con::printf("   packUpdate: avg (%f), min (%i), max (%i), num (%i)",
870                                       F32(rep->mNetStatPack.total)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mNetStatPack.numEvents),
871                                       rep->mNetStatPack.min,
872                                       rep->mNetStatPack.max,
873                                       rep->mNetStatPack.numEvents);
874         if (rep->mNetStatUnpack.numEvents)
875            Con::printf("   unpackUpdate: avg (%f), min (%i), max (%i), num (%i)",
876                                       F32(rep->mNetStatUnpack.total)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mNetStatUnpack.numEvents),
877                                       rep->mNetStatUnpack.min,
878                                       rep->mNetStatUnpack.max,
879                                       rep->mNetStatUnpack.numEvents);
880         if (rep->mNetStatWrite.numEvents)
881            Con::printf("   write: avg (%f), min (%i), max (%i), num (%i)",
882                                       F32(rep->mNetStatWrite.total)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mNetStatWrite.numEvents),
883                                       rep->mNetStatWrite.min,
884                                       rep->mNetStatWrite.max,
885                                       rep->mNetStatWrite.numEvents);
886         if (rep->mNetStatRead.numEvents)
887            Con::printf("   read: avg (%f), min (%i), max (%i), num (%i)",
888                                       F32(rep->mNetStatRead.total)/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mNetStatRead.numEvents),
889                                       rep->mNetStatRead.min,
890                                       rep->mNetStatRead.max,
891                                       rep->mNetStatRead.numEvents);
892         S32 sum = 0;
893         for (S32 i=0; i<32; i++)
894            sum  += rep->mDirtyMaskFrequency[i];
895         if (sum)
896         {
897            Con::printf("   Mask bits:");
898            for (S32 i=0; i<8; i++)
899            {
900               F32 avg0  = rep->mDirtyMaskFrequency[i] ? F32(rep->mDirtyMaskTotal[i])/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mDirtyMaskFrequency[i]) : 0.0f;
901               F32 avg8  = rep->mDirtyMaskFrequency[i+8] ? F32(rep->mDirtyMaskTotal[i+8])/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mDirtyMaskFrequency[i+8]) : 0.0f;
902               F32 avg16 = rep->mDirtyMaskFrequency[i+16] ? F32(rep->mDirtyMaskTotal[i+16])/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mDirtyMaskFrequency[i+16]) : 0.0f;
903               F32 avg24 = rep->mDirtyMaskFrequency[i+24] ? F32(rep->mDirtyMaskTotal[i+24])/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(rep->mDirtyMaskFrequency[i+24]) : 0.0f;
904               Con::printf("      %2i - %4i (%6.2f)     %2i - %4i (%6.2f)     %2i - %4i (%6.2f)     %2i - %4i, (%6.2f)",
905                  i   ,rep->mDirtyMaskFrequency[i],avg0,
906                  i+8 ,rep->mDirtyMaskFrequency[i+8],avg8,
907                  i+16,rep->mDirtyMaskFrequency[i+16],avg16,
908                  i+24,rep->mDirtyMaskFrequency[i+24],avg24);
909            }
910         }
911      }
912      rep->resetNetStats();
913   }
914#endif
915}
916
917DefineEngineFunction( sizeof, S32, ( const char *objectOrClass ),,
918            "@brief Determines the memory consumption of a class or object.\n\n"
919            "@param objectOrClass The object or class being measured.\n"
920            "@return Returns the total size of an object in bytes.\n"
921            "@ingroup Debugging\n")
922{
923   AbstractClassRep *acr = NULL;
924   SimObject *obj = Sim::findObject(objectOrClass);
925   if(obj)
926      acr = obj->getClassRep();
927
928   if(!acr)
929      acr = AbstractClassRep::findClassRep(objectOrClass);
930
931   if(acr)
932      return acr->getSizeof();
933
934   if(dStricmp("ConsoleObject", objectOrClass) == 0)
935     return sizeof(ConsoleObject);
936
937   Con::warnf("could not find a class rep for that object or class name.");
938   return 0;
939}
940
941
942DefineEngineFunction(linkNamespaces, bool, ( String childNSName, String parentNSName  ),,
943                     "@brief Links childNS to parentNS.\n\n"
944                     "Links childNS to parentNS, or nothing if parentNS is NULL.\n"
945                     "Will unlink the namespace from previous namespace if a parent already exists.\n"
946                     "@internal\n")
947{
948   StringTableEntry childNSSTE = StringTable->insert(childNSName.c_str());
949   StringTableEntry parentNSSTE = StringTable->insert(parentNSName.c_str());
950   
951   Namespace *childNS = Namespace::find(childNSSTE);
952   Namespace *parentNS = Namespace::find(parentNSSTE);
953   
954   if (!childNS)
955   {
956      return false;
957   }
958
959   Namespace *currentParent = childNS->getParent();
960   
961   // Link to new NS if applicable
962   
963   if (currentParent != parentNS)
964   {
965      if (currentParent != NULL)
966      {
967         if (!childNS->unlinkClass(currentParent))
968         {
969            return false;
970         }
971      }
972      
973      if (parentNS != NULL)
974      {
975         return childNS->classLinkTo(parentNS);
976      }
977   }
978   
979   return true;
980}
981
982