consoleObject.cpp
Engine/source/console/consoleObject.cpp
Public Variables
char
replacebuf [1024]
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." )
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