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