simObject.cpp
Engine/source/console/simObject.cpp
Classes:
class
Namespaces:
namespace
Public Variables
notifyChunker (128000)
Public Functions
ConsoleDocClass(SimObject , "@brief Base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> almost all objects involved in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">simulation.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" )
ConsoleMethod(SimObject , call , const char * , 3 , 0 , "( string method, string args... ) Dynamically call a method on an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param method Name of method <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" "@param args Zero or more arguments <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return The result of the method call." )
ConsoleMethod(SimObject , schedule , S32 , 4 , 0 , "( float time, string method, string args... ) Delay an invocation of a <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@param time The number of milliseconds after which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> invoke the method. This is a soft <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">limit.\n</a>" "@param method The method <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" "@param args The arguments with which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> call the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return The numeric ID of the created schedule. Can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> cancel the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" )
DefineConsoleMethod(SimObject , assignFieldsFrom , void , (SimObject *fromObject) , "Copy fields from another object onto this one. The objects must " "be of same type. Everything from the object will overwrite what's " "in this object; extra fields in this object will remain. This " "includes dynamic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">fields.\n</a>" "@param fromObject The object from which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> copy fields." )
DefineConsoleMethod(SimObject , delete , void , () , "Delete and remove the object." )
DefineConsoleMethod(SimObject , dumpClassHierarchy , void , () , "Dump the native C++ class hierarchy of this object's C++ class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )
DefineConsoleMethod(SimObject , dumpMethods , ArrayObject * , () , "List the methods defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "Each description is a newline-separated vector with the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">elements:\n</a>" "- Minimum number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">arguments.\n</a>" "- Maximum number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">arguments.\n</a>" "- Prototype <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "- Full script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> path (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> script method).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "- Line number of method definition in script (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> script method).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "- Documentation string (not including prototype). This takes up the remainder of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" "@return An <a href="/coding/class/classarrayobject/">ArrayObject</a> populated with (name,description) pairs of all methods defined on the object." )
DefineConsoleMethod(SimObject , getCanSave , bool , () , "Get whether the object will be included in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">saves.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object will be saved; false otherwise." )
DefineConsoleMethod(SimObject , getClassName , const char * , () , "Get the name of the C++ class which the object is an instance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The name of the C++ class of the object." )
DefineConsoleMethod(SimObject , getClassNamespace , const char * , () , "Get the name of the class namespace assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The name of the 'class' namespace." )
DefineConsoleMethod(SimObject , getDeclarationLine , S32 , () , "Get the line number at which the object is defined in its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" "@return The line number of the object's definition in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">script.\n</a>" "@see getFilename()" )
DefineConsoleMethod(SimObject , getDynamicField , const char * , (S32 index) , "Get a value of a dynamic field by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The index of the dynamic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The value of the dynamic field at the given index or \"\"." )
DefineConsoleMethod(SimObject , getDynamicFieldCount , S32 , () , "Get the number of dynamic fields defined on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The number of dynamic fields defined on the object." )
DefineConsoleMethod(SimObject , getField , const char * , (S32 index) , "Retrieve the value of a static field by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The index of the static <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The value of the static field with the given index or \"\"." )
DefineConsoleMethod(SimObject , getFieldCount , S32 , () , "Get the number of static fields on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The number of static fields defined on the object." )
DefineConsoleMethod(SimObject , getFieldType , const char * , (const char *fieldName) , "Get the console type code of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The numeric type code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the underlying console type of the given field." )
DefineConsoleMethod(SimObject , getFieldValue , const char * , (const char *fieldName, S32 index) , (-1) , "Return the value of the given field on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the field. If it includes a field index, the index is parsed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param index Optional parameter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specify the index of an array field <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">separately.\n</a>" " @return The value of the given field or \"\" <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> undefined." )
DefineConsoleMethod(SimObject , getFilename , const char * , () , "Returns the filename the object is attached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@return The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> the object is associated with; usually the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> the object was loaded from." )
DefineConsoleMethod(SimObject , getSuperClassNamespace , const char * , () , "Get the name of the superclass namespace assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The name of the 'superClass' namespace." )
DefineConsoleMethod(SimObject , isExpanded , bool , () , "Get whether the object has been marked as expanded. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is marked expanded." )
DefineConsoleMethod(SimObject , isField , bool , (const char *fieldName) , "Test whether the given field is defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object implements the given field." )
DefineConsoleMethod(SimObject , isInNamespaceHierarchy , bool , (const char *name) , "Test whether the namespace of this object is a direct or indirect child <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@param name The name of a <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the given namespace name is within the namespace hierarchy of this object." )
DefineConsoleMethod(SimObject , isMemberOfClass , bool , (const char *className) , "Test whether this object is a member of the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@param className Name of a native C++ <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object is an instance of the given C++ class or any of its super classes." )
DefineConsoleMethod(SimObject , isMethod , bool , (const char *methodName) , "Test whether the given method is defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object implements the given method." )
DefineConsoleMethod(SimObject , save , bool , (const char *fileName, bool selectedOnly, const char *preAppendString) , (false, "") , "Save out the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n</a>" "@param fileName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> save to." "@param selectedOnly If true, only objects marked as selected will be saved <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param preAppendString Text which will be preprended directly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">serialization.\n</a>" " @param True on success, false on failure." )
DefineConsoleMethod(SimObject , setCanSave , void , (bool value) , (true) , "Set whether the object will be included in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">saves.\n</a>" "@param value If true, the object will be included in saves;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, it will be excluded." )
DefineConsoleMethod(SimObject , setClassNamespace , void , (const char *name) , "Assign a class namespace <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param name The name of the 'class' namespace <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object." )
DefineConsoleMethod(SimObject , setFieldType , void , (const char *fieldName, const char *type) , "Set the console type code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@param fieldName The name of the dynamic field <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param type The name of the console <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">type.\n</a>" "@note This only works <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> dynamic fields. Types of static fields cannot be changed." )
DefineConsoleMethod(SimObject , setFieldValue , bool , (const char *fieldName, const char *value, S32 index) , (-1) , "Set the value of the given field on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the field <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign to. If it includes an array index, the index will be parsed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param value The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> value <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" " @param index Optional argument <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specify an index <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an array <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" " @return True." )
DefineConsoleMethod(SimObject , setFilename , void , (const char *fileName) , "Sets the object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path\n</a>" "@param fileName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> associate this object with." )
DefineConsoleMethod(SimObject , setIsExpanded , void , (bool state) , (true) , "Set whether the object has been marked as expanded. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be marked expanded; false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> not." )
DefineConsoleMethod(SimObject , setSuperClassNamespace , void , (const char *name) , "Assign a superclass namespace <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param name The name of the 'superClass' namespace <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object." )
DefineEngineMethod(SimObject , assignPersistentId , void , () , "Assign a persistent ID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> it does not already have one." )
DefineEngineMethod(SimObject , clone , SimObject * , () , "Create a copy of this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return An exact duplicate of this object." )
DefineEngineMethod(SimObject , deepClone , SimObject * , () , "Create a copy of this object and all its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subobjects.\n</a>" "@return An exact duplicate of this object and all objects it references." )
DefineEngineMethod(SimObject , dump , void , (bool detailed) , (false) , "Dump a description of all fields and methods defined on this object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n</a>" "@param detailed Whether <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> print detailed information about members." )
DefineEngineMethod(SimObject , dumpGroupHierarchy , void , () , "Dump the hierarchy of this object up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> RootGroup <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )
DefineEngineMethod(SimObject , getGroup , SimGroup * , () , "Get the group that this object is contained <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">in.\n</a>" "@note If not assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> particular SimGroup, an object belongs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RootGroup.\n</a>" " @return The <a href="/coding/class/classsimgroup/">SimGroup</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which the object belongs." )
DefineEngineMethod(SimObject , getId , S32 , () , "Get the underlying unique numeric ID of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@note <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> IDs are unique only during single engine <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">runs.\n</a>" "@return The unique numeric ID of the object." )
DefineEngineMethod(SimObject , getInternalName , const char * , () , "Get the internal name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The internal name of the object." )
DefineEngineMethod(SimObject , getName , const char * , () , "Get the global name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The global name assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object." )
DefineEngineMethod(SimObject , isChildOfGroup , bool , (SimGroup *group) , "Test whether the object belongs directly or indirectly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n</a>" "@param group The <a href="/coding/class/classsimgroup/">SimGroup</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is a child of the given group or a child of a group that the given group is directly or indirectly a child to." )
DefineEngineMethod(SimObject , isEditorOnly , bool , () , "Return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is only used by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object exists only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the sake of editing." )
DefineEngineMethod(SimObject , isNameChangeAllowed , bool , () , "Get whether this object may be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">renamed.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object can be renamed; false otherwise." )
DefineEngineMethod(SimObject , isSelected , bool , () , "Get whether the object has been marked as selected. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is currently selected." )
DefineEngineMethod(SimObject , setEditorOnly , void , (bool value) , (true) , "Set/clear the editor-only flag on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param value If true, the object is marked as existing only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the editor." )
DefineEngineMethod(SimObject , setHidden , void , (bool value) , (true) , "Hide/unhide the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param value If true, the object will be hidden;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, the object will be unhidden." )
DefineEngineMethod(SimObject , setInternalName , void , (const char *newInternalName) , "Set the internal name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param newInternalName The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> internal name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the object." )
DefineEngineMethod(SimObject , setIsSelected , void , (bool state) , (true) , "Set whether the object has been marked as selected. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> object is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be marked selected; false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> not." )
DefineEngineMethod(SimObject , setLocked , void , (bool value) , (true) , "Lock/unlock the object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n</a>" "@param value If true, the object will be locked;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, the object will be unlocked." )
DefineEngineMethod(SimObject , setName , void , (const char *newName) , "Set the global name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param newName The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> global name <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@note If name changing is disallowed on the object, the method will fail with a console error." )
DefineEngineMethod(SimObject , setNameChangeAllowed , void , (bool value) , (true) , "Set whether this object can be renamed from its first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param value If true, renaming is allowed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, trying <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change the name of the object will generate a console error." )
Detailed Description
Public Variables
Chunker< SimObject::Notify > notifyChunker (128000)
Public Functions
ConsoleDocClass(SimObject , "@brief Base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> almost all objects involved in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">simulation.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" )
ConsoleMethod(SimObject , call , const char * , 3 , 0 , "( string method, string args... ) Dynamically call a method on an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param method Name of method <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" "@param args Zero or more arguments <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return The result of the method call." )
ConsoleMethod(SimObject , schedule , S32 , 4 , 0 , "( float time, string method, string args... ) Delay an invocation of a <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@param time The number of milliseconds after which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> invoke the method. This is a soft <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">limit.\n</a>" "@param method The method <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" "@param args The arguments with which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> call the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return The numeric ID of the created schedule. Can be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> cancel the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">call.\n</a>" )
DefineConsoleMethod(SimObject , assignFieldsFrom , void , (SimObject *fromObject) , "Copy fields from another object onto this one. The objects must " "be of same type. Everything from the object will overwrite what's " "in this object; extra fields in this object will remain. This " "includes dynamic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">fields.\n</a>" "@param fromObject The object from which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> copy fields." )
DefineConsoleMethod(SimObject , delete , void , () , "Delete and remove the object." )
DefineConsoleMethod(SimObject , dumpClassHierarchy , void , () , "Dump the native C++ class hierarchy of this object's C++ class <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )
DefineConsoleMethod(SimObject , dumpMethods , ArrayObject * , () , "List the methods defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "Each description is a newline-separated vector with the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">elements:\n</a>" "- Minimum number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">arguments.\n</a>" "- Maximum number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">arguments.\n</a>" "- Prototype <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "- Full script <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> path (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> script method).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "- Line number of method definition in script (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> script method).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "- Documentation string (not including prototype). This takes up the remainder of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" "@return An <a href="/coding/class/classarrayobject/">ArrayObject</a> populated with (name,description) pairs of all methods defined on the object." )
DefineConsoleMethod(SimObject , getCanSave , bool , () , "Get whether the object will be included in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">saves.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object will be saved; false otherwise." )
DefineConsoleMethod(SimObject , getClassName , const char * , () , "Get the name of the C++ class which the object is an instance <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The name of the C++ class of the object." )
DefineConsoleMethod(SimObject , getClassNamespace , const char * , () , "Get the name of the class namespace assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The name of the 'class' namespace." )
DefineConsoleMethod(SimObject , getDeclarationLine , S32 , () , "Get the line number at which the object is defined in its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n\n</a>" "@return The line number of the object's definition in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">script.\n</a>" "@see getFilename()" )
DefineConsoleMethod(SimObject , getDynamicField , const char * , (S32 index) , "Get a value of a dynamic field by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The index of the dynamic <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The value of the dynamic field at the given index or \"\"." )
DefineConsoleMethod(SimObject , getDynamicFieldCount , S32 , () , "Get the number of dynamic fields defined on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The number of dynamic fields defined on the object." )
DefineConsoleMethod(SimObject , getField , const char * , (S32 index) , "Retrieve the value of a static field by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The index of the static <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The value of the static field with the given index or \"\"." )
DefineConsoleMethod(SimObject , getFieldCount , S32 , () , "Get the number of static fields on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The number of static fields defined on the object." )
DefineConsoleMethod(SimObject , getFieldType , const char * , (const char *fieldName) , "Get the console type code of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return The numeric type code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the underlying console type of the given field." )
DefineConsoleMethod(SimObject , getFieldValue , const char * , (const char *fieldName, S32 index) , (-1) , "Return the value of the given field on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the field. If it includes a field index, the index is parsed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param index Optional parameter <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specify the index of an array field <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">separately.\n</a>" " @return The value of the given field or \"\" <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> undefined." )
DefineConsoleMethod(SimObject , getFilename , const char * , () , "Returns the filename the object is attached <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@return The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> the object is associated with; usually the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> the object was loaded from." )
DefineConsoleMethod(SimObject , getSuperClassNamespace , const char * , () , "Get the name of the superclass namespace assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The name of the 'superClass' namespace." )
DefineConsoleMethod(SimObject , isExpanded , bool , () , "Get whether the object has been marked as expanded. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is marked expanded." )
DefineConsoleMethod(SimObject , isField , bool , (const char *fieldName) , "Test whether the given field is defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object implements the given field." )
DefineConsoleMethod(SimObject , isInNamespaceHierarchy , bool , (const char *name) , "Test whether the namespace of this object is a direct or indirect child <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@param name The name of a <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the given namespace name is within the namespace hierarchy of this object." )
DefineConsoleMethod(SimObject , isMemberOfClass , bool , (const char *className) , "Test whether this object is a member of the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@param className Name of a native C++ <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object is an instance of the given C++ class or any of its super classes." )
DefineConsoleMethod(SimObject , isMethod , bool , (const char *methodName) , "Test whether the given method is defined on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object implements the given method." )
DefineConsoleMethod(SimObject , save , bool , (const char *fileName, bool selectedOnly, const char *preAppendString) , (false, "") , "Save out the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n</a>" "@param fileName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> save to." "@param selectedOnly If true, only objects marked as selected will be saved <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param preAppendString Text which will be preprended directly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">serialization.\n</a>" " @param True on success, false on failure." )
DefineConsoleMethod(SimObject , setCanSave , void , (bool value) , (true) , "Set whether the object will be included in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">saves.\n</a>" "@param value If true, the object will be included in saves;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, it will be excluded." )
DefineConsoleMethod(SimObject , setClassNamespace , void , (const char *name) , "Assign a class namespace <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param name The name of the 'class' namespace <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object." )
DefineConsoleMethod(SimObject , setFieldType , void , (const char *fieldName, const char *type) , "Set the console type code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" "@param fieldName The name of the dynamic field <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param type The name of the console <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">type.\n</a>" "@note This only works <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> dynamic fields. Types of static fields cannot be changed." )
DefineConsoleMethod(SimObject , setFieldValue , bool , (const char *fieldName, const char *value, S32 index) , (-1) , "Set the value of the given field on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param fieldName The name of the field <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign to. If it includes an array index, the index will be parsed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param value The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> value <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" " @param index Optional argument <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specify an index <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> an array <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">field.\n</a>" " @return True." )
DefineConsoleMethod(SimObject , setFilename , void , (const char *fileName) , "Sets the object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path\n</a>" "@param fileName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> associate this object with." )
DefineConsoleMethod(SimObject , setIsExpanded , void , (bool state) , (true) , "Set whether the object has been marked as expanded. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be marked expanded; false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> not." )
DefineConsoleMethod(SimObject , setSuperClassNamespace , void , (const char *name) , "Assign a superclass namespace <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param name The name of the 'superClass' namespace <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object." )
DefineEngineMethod(SimObject , assignPersistentId , void , () , "Assign a persistent ID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> it does not already have one." )
DefineEngineMethod(SimObject , clone , SimObject * , () , "Create a copy of this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return An exact duplicate of this object." )
DefineEngineMethod(SimObject , deepClone , SimObject * , () , "Create a copy of this object and all its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">subobjects.\n</a>" "@return An exact duplicate of this object and all objects it references." )
DefineEngineMethod(SimObject , dump , void , (bool detailed) , (false) , "Dump a description of all fields and methods defined on this object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console.\n</a>" "@param detailed Whether <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> print detailed information about members." )
DefineEngineMethod(SimObject , dumpGroupHierarchy , void , () , "Dump the hierarchy of this object up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> RootGroup <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )
DefineEngineMethod(SimObject , getGroup , SimGroup * , () , "Get the group that this object is contained <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">in.\n</a>" "@note If not assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> particular SimGroup, an object belongs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RootGroup.\n</a>" " @return The <a href="/coding/class/classsimgroup/">SimGroup</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> which the object belongs." )
DefineEngineMethod(SimObject , getId , S32 , () , "Get the underlying unique numeric ID of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@note <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> IDs are unique only during single engine <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">runs.\n</a>" "@return The unique numeric ID of the object." )
DefineEngineMethod(SimObject , getInternalName , const char * , () , "Get the internal name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The internal name of the object." )
DefineEngineMethod(SimObject , getName , const char * , () , "Get the global name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return The global name assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object." )
DefineEngineMethod(SimObject , isChildOfGroup , bool , (SimGroup *group) , "Test whether the object belongs directly or indirectly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n</a>" "@param group The <a href="/coding/class/classsimgroup/">SimGroup</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is a child of the given group or a child of a group that the given group is directly or indirectly a child to." )
DefineEngineMethod(SimObject , isEditorOnly , bool , () , "Return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is only used by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object exists only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the sake of editing." )
DefineEngineMethod(SimObject , isNameChangeAllowed , bool , () , "Get whether this object may be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">renamed.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> this object can be renamed; false otherwise." )
DefineEngineMethod(SimObject , isSelected , bool , () , "Get whether the object has been marked as selected. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> the object is currently selected." )
DefineEngineMethod(SimObject , setEditorOnly , void , (bool value) , (true) , "Set/clear the editor-only flag on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param value If true, the object is marked as existing only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the editor." )
DefineEngineMethod(SimObject , setHidden , void , (bool value) , (true) , "Hide/unhide the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param value If true, the object will be hidden;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, the object will be unhidden." )
DefineEngineMethod(SimObject , setInternalName , void , (const char *newInternalName) , "Set the internal name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param newInternalName The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> internal name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the object." )
DefineEngineMethod(SimObject , setIsSelected , void , (bool state) , (true) , "Set whether the object has been marked as selected. (in editor)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> object is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be marked selected; false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> not." )
DefineEngineMethod(SimObject , setLocked , void , (bool value) , (true) , "Lock/unlock the object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editor.\n</a>" "@param value If true, the object will be locked;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, the object will be unlocked." )
DefineEngineMethod(SimObject , setName , void , (const char *newName) , "Set the global name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param newName The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> global name <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@note If name changing is disallowed on the object, the method will fail with a console error." )
DefineEngineMethod(SimObject , setNameChangeAllowed , void , (bool value) , (true) , "Set whether this object can be renamed from its first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param value If true, renaming is allowed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this object;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a2594a51175f310ed96ad6cd7d6514878">if</a> false, trying <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change the name of the object will generate a console error." )
IMPLEMENT_CONOBJECT(SimObject )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "platform/platformMemory.h" 26#include "console/simObject.h" 27#include "console/console.h" 28#include "console/consoleInternal.h" 29#include "console/engineAPI.h" 30#include "console/simFieldDictionary.h" 31#include "console/simPersistID.h" 32#include "console/typeValidators.h" 33#include "console/arrayObject.h" 34#include "console/codeBlock.h" 35#include "core/frameAllocator.h" 36#include "core/stream/fileStream.h" 37#include "core/fileObject.h" 38#include "persistence/taml/tamlCustom.h" 39 40IMPLEMENT_CONOBJECT( SimObject ); 41 42// See full description in the new CHM manual 43ConsoleDocClass( SimObject, 44 "@brief Base class for almost all objects involved in the simulation.\n\n" 45 46 "@ingroup Console\n" 47); 48 49bool SimObject::smForceId = false; 50SimObjectId SimObject::smForcedId = 0; 51 52 53namespace Sim 54{ 55 // Defined in simManager.cpp 56 extern SimGroup *gRootGroup; 57 extern SimManagerNameDictionary *gNameDictionary; 58 extern SimIdDictionary *gIdDictionary; 59 extern U32 gNextObjectId; 60} 61 62 63//----------------------------------------------------------------------------- 64 65SimObject::SimObject() 66{ 67 objectName = NULL; 68 mOriginalName = NULL; 69 mInternalName = NULL; 70 nextNameObject = (SimObject*)-1; 71 nextManagerNameObject = (SimObject*)-1; 72 nextIdObject = NULL; 73 74 mFilename = NULL; 75 mDeclarationLine = -1; 76 77 mId = 0; 78 mIdString[ 0 ] = '\0'; 79 mGroup = 0; 80 mNameSpace = NULL; 81 mNotifyList = NULL; 82 mFlags.set( ModStaticFields | ModDynamicFields ); 83 84 mFieldDictionary = NULL; 85 mCanSaveFieldDictionary = true; 86 87 mClassName = NULL; 88 mSuperClassName = NULL; 89 90 mCopySource = NULL; 91 mPersistentId = NULL; 92} 93 94//----------------------------------------------------------------------------- 95 96SimObject::~SimObject() 97{ 98 if( mFieldDictionary ) 99 { 100 delete mFieldDictionary; 101 mFieldDictionary = NULL; 102 } 103 104 // Release persistent ID. 105 if( mPersistentId ) 106 { 107 mPersistentId->unresolve(); 108 mPersistentId->decRefCount(); 109 mPersistentId = NULL; 110 } 111 112 if( mCopySource ) 113 mCopySource->unregisterReference( &mCopySource ); 114 115 AssertFatal(nextNameObject == (SimObject*)-1,avar( 116 "SimObject::~SimObject: Not removed from dictionary: name %s, id %i", 117 objectName, mId)); 118 AssertFatal(nextManagerNameObject == (SimObject*)-1,avar( 119 "SimObject::~SimObject: Not removed from manager dictionary: name %s, id %i", 120 objectName,mId)); 121 AssertFatal(mFlags.test(Added) == 0, "SimObject::object " 122 "missing call to SimObject::onRemove"); 123} 124 125//----------------------------------------------------------------------------- 126 127bool SimObject::processArguments(S32 argc, ConsoleValueRef *argv) 128{ 129 return argc == 0; 130} 131 132//----------------------------------------------------------------------------- 133 134void SimObject::initPersistFields() 135{ 136 addGroup( "Ungrouped" ); 137 138 addProtectedField( "name", TypeName, Offset(objectName, SimObject), &setProtectedName, &defaultProtectedGetFn, 139 "Optional global name of this object." ); 140 141 endGroup( "Ungrouped" ); 142 143 addGroup( "Object" ); 144 145 addField( "internalName", TypeString, Offset(mInternalName, SimObject), 146 "Optional name that may be used to lookup this object within a SimSet."); 147 148 addProtectedField( "parentGroup", TYPEID< SimObject >(), Offset(mGroup, SimObject), &setProtectedParent, &defaultProtectedGetFn, 149 "Group hierarchy parent of the object." ); 150 151 addProtectedField( "class", TypeString, Offset(mClassName, SimObject), &setClass, &defaultProtectedGetFn, 152 "Script class of object." ); 153 154 addProtectedField( "superClass", TypeString, Offset(mSuperClassName, SimObject), &setSuperClass, &defaultProtectedGetFn, 155 "Script super-class of object." ); 156 157 // For legacy support 158 addProtectedField( "className", TypeString, Offset(mClassName, SimObject), &setClass, &defaultProtectedGetFn, 159 "Script class of object.", AbstractClassRep::FIELD_HideInInspectors ); 160 161 endGroup( "Object" ); 162 163 addGroup( "Editing" ); 164 165 addProtectedField( "hidden", TypeBool, NULL, 166 &_setHidden, &_getHidden, 167 "Whether the object is visible." ); 168 addProtectedField( "locked", TypeBool, NULL, 169 &_setLocked, &_getLocked, 170 "Whether the object can be edited." ); 171 172 endGroup( "Editing" ); 173 174 addGroup( "Persistence" ); 175 176 addProtectedField( "canSave", TypeBool, Offset( mFlags, SimObject ), 177 &_setCanSave, &_getCanSave, 178 "Whether the object can be saved out. If false, the object is purely transient in nature." ); 179 180 addField( "canSaveDynamicFields", TypeBool, Offset(mCanSaveFieldDictionary, SimObject), 181 "True if dynamic fields (added at runtime) should be saved. Defaults to true." ); 182 183 addProtectedField( "persistentId", TypePID, Offset( mPersistentId, SimObject ), 184 &_setPersistentID, &defaultProtectedGetFn, 185 "The universally unique identifier for the object." ); 186 187 endGroup( "Persistence" ); 188 189 Parent::initPersistFields(); 190} 191 192//----------------------------------------------------------------------------- 193 194String SimObject::describeSelf() const 195{ 196 String desc = Parent::describeSelf(); 197 198 if( mId != 0 ) 199 desc = avar( "%s|id: %i", desc.c_str(), mId ); 200 if( objectName ) 201 desc = avar( "%s|name: %s", desc.c_str(), objectName ); 202 if( mInternalName ) 203 desc = avar( "%s|internal: %s", desc.c_str(), mInternalName ); 204 if( mNameSpace ) 205 desc = avar( "%s|nspace: %s", desc.c_str(), mNameSpace->mName ); 206 if( mGroup ) 207 desc = avar( "%s|group: %s", desc.c_str(), mGroup->getName() ); 208 if( mCopySource ) 209 desc = avar( "%s|copy: %s", desc.c_str(), mCopySource->getName() ); 210 if( mPersistentId ) 211 desc = avar( "%s|pid: %s", desc.c_str(), mPersistentId->getUUID().toString().c_str() ); 212 213 return desc; 214} 215 216//============================================================================= 217// Persistence. 218//============================================================================= 219// MARK: ---- Persistence ---- 220 221//----------------------------------------------------------------------------- 222 223bool SimObject::writeField(StringTableEntry fieldname, const char* value) 224{ 225 // Don't write empty fields. 226 if (!value || !*value) 227 return false; 228 229 // Don't write owner field for components 230 static StringTableEntry sOwner = StringTable->insert( "owner" ); 231 if( fieldname == sOwner ) 232 return false; 233 234 // Don't write ParentGroup 235 static StringTableEntry sParentGroup = StringTable->insert( "parentGroup" ); 236 if( fieldname == sParentGroup ) 237 return false; 238 239 // Don't write name, is within the parenthesis already 240 static StringTableEntry sName = StringTable->insert( "name" ); 241 if( fieldname == sName ) 242 return false; 243 244 // Don't write className, it is read for legacy support but we 245 // write it out as class. 246 static StringTableEntry sClassName = StringTable->insert( "className" ); 247 if( fieldname == sClassName ) 248 return false; 249 250 // Write persistent ID only if present. 251 static StringTableEntry sPersistentId = StringTable->insert( "persistentId" ); 252 if( fieldname == sPersistentId && ( !value || !value[ 0 ] ) ) 253 return false; 254 255 // Don't write hidden and locked flags if they are at their default value. 256 257 static StringTableEntry sHidden = StringTable->insert( "hidden" ); 258 static StringTableEntry sLocked = StringTable->insert( "locked" ); 259 260 if( fieldname == sHidden && !dAtob( value ) ) 261 return false; 262 if( fieldname == sLocked && !dAtob( value ) ) 263 return false; 264 265 return true; 266} 267 268//----------------------------------------------------------------------------- 269 270void SimObject::writeFields(Stream &stream, U32 tabStop) 271{ 272 // Write static fields. 273 274 const AbstractClassRep::FieldList &list = getFieldList(); 275 276 for(U32 i = 0; i < list.size(); i++) 277 { 278 const AbstractClassRep::Field* f = &list[i]; 279 280 // Skip the special field types. 281 if ( f->type >= AbstractClassRep::ARCFirstCustomField ) 282 continue; 283 284 for(U32 j = 0; S32(j) < f->elementCount; j++) 285 { 286 char array[8]; 287 dSprintf( array, 8, "%d", j ); 288 const char *val = getDataField(StringTable->insert( f->pFieldname ), array ); 289 290 // Make a copy for the field check. 291 if (!val) 292 continue; 293 294 U32 nBufferSize = dStrlen( val ) + 1; 295 FrameTemp<char> valCopy( nBufferSize ); 296 dStrcpy( (char *)valCopy, val ); 297 298 if (!writeField(f->pFieldname, valCopy)) 299 continue; 300 301 val = valCopy; 302 303 U32 expandedBufferSize = ( nBufferSize * 2 ) + dStrlen(f->pFieldname) + 32; 304 FrameTemp<char> expandedBuffer( expandedBufferSize ); 305 if(f->elementCount == 1) 306 dSprintf(expandedBuffer, expandedBufferSize, "%s = \"", f->pFieldname); 307 else 308 dSprintf(expandedBuffer, expandedBufferSize, "%s[%d] = \"", f->pFieldname, j); 309 310 // detect and collapse relative path information 311 char fnBuf[1024]; 312 if (f->type == TypeFilename || 313 f->type == TypeStringFilename || 314 f->type == TypeImageFilename || 315 f->type == TypePrefabFilename || 316 f->type == TypeShapeFilename) 317 { 318 Con::collapseScriptFilename(fnBuf, 1024, val); 319 val = fnBuf; 320 } 321 322 expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), val); 323 dStrcat(expandedBuffer, "\";\r\n"); 324 325 stream.writeTabs(tabStop); 326 stream.write(dStrlen(expandedBuffer),expandedBuffer); 327 } 328 } 329 330 // Write dynamic fields, if enabled. 331 332 if(mFieldDictionary && mCanSaveFieldDictionary) 333 mFieldDictionary->writeFields(this, stream, tabStop); 334} 335 336//----------------------------------------------------------------------------- 337 338void SimObject::write(Stream &stream, U32 tabStop, U32 flags) 339{ 340 if( !getCanSave() && !( flags & IgnoreCanSave ) ) 341 return; 342 343 // Only output selected objects if they want that. 344 if((flags & SelectedOnly) && !isSelected()) 345 return; 346 347 stream.writeTabs(tabStop); 348 char buffer[1024]; 349 dSprintf(buffer, sizeof(buffer), "new %s(%s) {\r\n", getClassName(), getName() && !(flags & NoName) ? getName() : ""); 350 stream.write(dStrlen(buffer), buffer); 351 writeFields(stream, tabStop + 1); 352 353 stream.writeTabs(tabStop); 354 stream.write(4, "};\r\n"); 355} 356 357//----------------------------------------------------------------------------- 358 359bool SimObject::save(const char *pcFileName, bool bOnlySelected, const char *preappend) 360{ 361 static const char *beginMessage = "//--- OBJECT WRITE BEGIN ---"; 362 static const char *endMessage = "//--- OBJECT WRITE END ---"; 363 FileStream *stream; 364 FileObject f; 365 f.readMemory(pcFileName); 366 367 // check for flags <selected, ...> 368 U32 writeFlags = 0; 369 if(bOnlySelected) 370 writeFlags |= SimObject::SelectedOnly; 371 372 if((stream = FileStream::createAndOpen( pcFileName, Torque::FS::File::Write )) == NULL) 373 return false; 374 375 char docRoot[256]; 376 char modRoot[256]; 377 378 dStrcpy(docRoot, pcFileName); 379 char *p = dStrrchr(docRoot, '/'); 380 if (p) *++p = '\0'; 381 else docRoot[0] = '\0'; 382 383 dStrcpy(modRoot, pcFileName); 384 p = dStrchr(modRoot, '/'); 385 if (p) *++p = '\0'; 386 else modRoot[0] = '\0'; 387 388 Con::setVariable("$DocRoot", docRoot); 389 Con::setVariable("$ModRoot", modRoot); 390 391 const char *buffer; 392 while(!f.isEOF()) 393 { 394 buffer = (const char *) f.readLine(); 395 if(!dStrcmp(buffer, beginMessage)) 396 break; 397 stream->write(dStrlen(buffer), buffer); 398 stream->write(2, "\r\n"); 399 } 400 stream->write(dStrlen(beginMessage), beginMessage); 401 stream->write(2, "\r\n"); 402 if ( preappend != NULL ) 403 stream->write(dStrlen(preappend),preappend); 404 write(*stream, 0, writeFlags); 405 stream->write(dStrlen(endMessage), endMessage); 406 stream->write(2, "\r\n"); 407 while(!f.isEOF()) 408 { 409 buffer = (const char *) f.readLine(); 410 if(!dStrcmp(buffer, endMessage)) 411 break; 412 } 413 while(!f.isEOF()) 414 { 415 buffer = (const char *) f.readLine(); 416 stream->write(dStrlen(buffer), buffer); 417 stream->write(2, "\r\n"); 418 } 419 420 Con::setVariable("$DocRoot", NULL); 421 Con::setVariable("$ModRoot", NULL); 422 423 delete stream; 424 425 return true; 426 427} 428 429//----------------------------------------------------------------------------- 430 431SimPersistID* SimObject::getOrCreatePersistentId() 432{ 433 if( !mPersistentId ) 434 { 435 mPersistentId = SimPersistID::create( this ); 436 mPersistentId->incRefCount(); 437 } 438 return mPersistentId; 439} 440 441 442 443void SimObject::onTamlCustomRead(TamlCustomNodes const& customNodes) 444{ 445 // Debug Profiling. 446 //PROFILE_SCOPE(SimObject_OnTamlCustomRead); 447 448 // Fetch field list. 449 const AbstractClassRep::FieldList& fieldList = getFieldList(); 450 const U32 fieldCount = fieldList.size(); 451 for (U32 index = 0; index < fieldCount; ++index) 452 { 453 // Fetch field. 454 const AbstractClassRep::Field* pField = &fieldList[index]; 455 456 // Ignore if field not appropriate. 457 if (pField->type == AbstractClassRep::StartArrayFieldType || pField->elementCount > 1) 458 { 459 // Find cell custom node. 460 const TamlCustomNode* pCustomCellNodes = NULL; 461 if (pField->pGroupname != NULL) 462 pCustomCellNodes = customNodes.findNode(pField->pGroupname); 463 if (!pCustomCellNodes) 464 { 465 char* niceFieldName = const_cast<char *>(pField->pFieldname); 466 niceFieldName[0] = dToupper(niceFieldName[0]); 467 String str_niceFieldName = String(niceFieldName); 468 pCustomCellNodes = customNodes.findNode(str_niceFieldName + "s"); 469 } 470 471 // Continue if we have explicit cells. 472 if (pCustomCellNodes != NULL) 473 { 474 // Fetch children cell nodes. 475 const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); 476 477 U8 idx = 0; 478 // Iterate cells. 479 for (TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr) 480 { 481 char buf[5]; 482 dSprintf(buf, 5, "%d", idx); 483 484 // Fetch cell node. 485 TamlCustomNode* pCellNode = *cellNodeItr; 486 487 // Fetch node name. 488 StringTableEntry nodeName = pCellNode->getNodeName(); 489 490 // Is this a valid alias? 491 if (nodeName != pField->pFieldname) 492 { 493 // No, so warn. 494 Con::warnf("SimObject::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, pField->pFieldname); 495 continue; 496 } 497 498 // Fetch fields. 499 const TamlCustomFieldVector& fields = pCellNode->getFields(); 500 501 // Iterate property fields. 502 for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr) 503 { 504 // Fetch field. 505 const TamlCustomField* pField = *fieldItr; 506 507 // Fetch field name. 508 StringTableEntry fieldName = pField->getFieldName(); 509 510 const AbstractClassRep::Field* field = findField(fieldName); 511 512 // Check common fields. 513 if (field) 514 { 515 setDataField(fieldName, buf, pField->getFieldValue()); 516 } 517 else 518 { 519 // Unknown name so warn. 520 Con::warnf("SimObject::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName); 521 continue; 522 } 523 } 524 525 idx++; 526 } 527 } 528 } 529 } 530} 531 532//----------------------------------------------------------------------------- 533 534bool SimObject::_setPersistentID( void* object, const char* index, const char* data ) 535{ 536 SimObject* simObject = reinterpret_cast< SimObject* >( object ); 537 538 // Make sure we don't already have a PID. 539 if( simObject->getPersistentId() ) 540 { 541 Con::errorf( "SimObject::_setPersistentID - cannot set a persistent ID on an object that already has a persistent ID assigned." ); 542 return false; 543 } 544 545 SimPersistID* pid; 546 Con::setData( TypePID, &pid, 0, 1, &data ); 547 if ( !pid ) 548 return false; 549 550 // Make sure it's not already bound to an object. 551 if( pid->getObject() ) 552 { 553 AssertWarn( pid->getObject() != simObject, "Sim::_setPersistentID - PID is bound to this object yet not assigned to it!" ); 554 555 SimObject* otherObj = pid->getObject(); 556 Con::errorf( "SimObject::_setPersistentID - UUID is already used by another object: '%s' -> %i:%s (%s)", 557 data, otherObj->getId(), otherObj->getClassName(), otherObj->getName() ); 558 559 return false; 560 } 561 562 pid->resolve( simObject ); 563 pid->incRefCount(); 564 simObject->mPersistentId = pid; 565 566 return false; 567} 568 569//----------------------------------------------------------------------------- 570 571void SimObject::setFilename( const char* file ) 572{ 573 if( file ) 574 mFilename = StringTable->insert( file ); 575 else 576 mFilename = StringTable->EmptyString(); 577} 578 579//----------------------------------------------------------------------------- 580 581void SimObject::setDeclarationLine(U32 lineNumber) 582{ 583 mDeclarationLine = lineNumber; 584} 585 586//============================================================================= 587// Management. 588//============================================================================= 589// MARK: ---- Management ---- 590 591//----------------------------------------------------------------------------- 592 593bool SimObject::registerObject() 594{ 595 AssertFatal( !mFlags.test( Added ), "reigsterObject - Object already registered!"); 596 mFlags.clear(Deleted | Removed); 597 598 if(smForceId) 599 { 600 setId(smForcedId); 601 smForceId = false; 602 } 603 604 if( !mId ) 605 { 606 mId = Sim::gNextObjectId++; 607 dSprintf( mIdString, sizeof( mIdString ), "%u", mId ); 608 } 609 610 AssertFatal(Sim::gIdDictionary && Sim::gNameDictionary, 611 "SimObject::registerObject - tried to register an object before Sim::init()!"); 612 613 Sim::gIdDictionary->insert(this); 614 615 Sim::gNameDictionary->insert(this); 616 617 // Notify object 618 bool ret = onAdd(); 619 620 if(!ret) 621 unregisterObject(); 622 623 AssertFatal(!ret || isProperlyAdded(), "Object did not call SimObject::onAdd()"); 624 return ret; 625} 626 627//----------------------------------------------------------------------------- 628 629void SimObject::unregisterObject() 630{ 631 mFlags.set(Removed); 632 633 // Notify object first 634 onRemove(); 635 636 // Clear out any pending notifications before 637 // we call our own, just in case they delete 638 // something that we have referenced. 639 clearAllNotifications(); 640 641 // Notify all objects that are waiting for delete 642 // messages 643 if (getGroup()) 644 getGroup()->removeObject(this); 645 646 processDeleteNotifies(); 647 648 // Do removals from the Sim. 649 Sim::gNameDictionary->remove(this); 650 Sim::gIdDictionary->remove(this); 651 Sim::cancelPendingEvents(this); 652} 653 654//----------------------------------------------------------------------------- 655 656void SimObject::deleteObject() 657{ 658 Parent::destroySelf(); 659} 660 661//----------------------------------------------------------------------------- 662 663void SimObject::_destroySelf() 664{ 665 AssertFatal( !isDeleted(), "SimObject::destroySelf - Object has already been deleted" ); 666 AssertFatal( !isRemoved(), "SimObject::destroySelf - Object in the process of being removed" ); 667 668 mFlags.set( Deleted ); 669 670 if( mFlags.test( Added ) ) 671 unregisterObject(); 672 673 Parent::_destroySelf(); 674} 675 676//----------------------------------------------------------------------------- 677 678void SimObject::destroySelf() 679{ 680 // When using the legacy console interop, we don't delete objects 681 // when their reference count drops to zero but rather defer their 682 // deletion until deleteObject() is called. 683 684 if( engineAPI::gUseConsoleInterop ) 685 return; 686 687 Parent::destroySelf(); 688} 689 690//----------------------------------------------------------------------------- 691 692class SimObjectDeleteEvent : public SimEvent 693{ 694public: 695 void process(SimObject *object) 696 { 697 object->deleteObject(); 698 } 699}; 700 701void SimObject::safeDeleteObject() 702{ 703 Sim::postEvent( this, new SimObjectDeleteEvent, Sim::getCurrentTime() + 1 ); 704} 705 706//----------------------------------------------------------------------------- 707 708void SimObject::setId(SimObjectId newId) 709{ 710 if(!mFlags.test(Added)) 711 mId = newId; 712 else 713 { 714 // get this object out of the id dictionary if it's in it 715 Sim::gIdDictionary->remove(this); 716 717 // Free current Id. 718 // Assign new one. 719 mId = newId ? newId : Sim::gNextObjectId++; 720 Sim::gIdDictionary->insert(this); 721 } 722 723 dSprintf( mIdString, sizeof( mIdString ), "%u", mId ); 724} 725 726//----------------------------------------------------------------------------- 727 728void SimObject::assignName(const char *name) 729{ 730 if( objectName && !isNameChangeAllowed() ) 731 { 732 Con::errorf( "SimObject::assignName - not allowed to change name of object '%s'", objectName ); 733 return; 734 } 735 736 // Added this assert 3/30/2007 because it is dumb to try to name 737 // a SimObject the same thing as it's class name -patw 738 //AssertFatal( dStricmp( getClassName(), name ), "Attempted to assign a name to a SimObject which matches it's type name." ); 739 if( dStricmp( getClassName(), name ) == 0 ) 740 Con::errorf( "SimObject::assignName - Assigning name '%s' to instance of object with type '%s'." 741 " This can cause namespace linking issues.", getClassName(), name ); 742 743 StringTableEntry newName = NULL; 744 if(name[0]) 745 newName = StringTable->insert(name); 746 747 onNameChange( newName ); 748 749 if( mGroup ) 750 mGroup->mNameDictionary.remove( this ); 751 if( isProperlyAdded() ) 752 { 753 unlinkNamespaces(); 754 Sim::gNameDictionary->remove( this ); 755 } 756 757 objectName = newName; 758 759 if( mGroup ) 760 mGroup->mNameDictionary.insert( this ); 761 if( isProperlyAdded() ) 762 { 763 Sim::gNameDictionary->insert( this ); 764 linkNamespaces(); 765 } 766} 767 768//----------------------------------------------------------------------------- 769 770bool SimObject::registerObject(U32 id) 771{ 772 setId(id); 773 return registerObject(); 774} 775 776//----------------------------------------------------------------------------- 777 778bool SimObject::registerObject(const char *name) 779{ 780 assignName(name); 781 return registerObject(); 782} 783 784//----------------------------------------------------------------------------- 785 786bool SimObject::registerObject(const char *name, U32 id) 787{ 788 setId(id); 789 assignName(name); 790 return registerObject(); 791} 792 793//============================================================================= 794// Introspection. 795//============================================================================= 796// MARK: ---- Introspection ---- 797 798//----------------------------------------------------------------------------- 799 800bool SimObject::isMethod( const char* methodName ) 801{ 802 if( !methodName || !methodName[0] ) 803 return false; 804 805 StringTableEntry stname = StringTable->insert( methodName ); 806 807 if( getNamespace() ) 808 return ( getNamespace()->lookup( stname ) != NULL ); 809 810 return false; 811} 812 813//----------------------------------------------------------------------------- 814 815bool SimObject::isField( const char* fieldName, bool includeStatic, bool includeDynamic ) 816{ 817 const char* strFieldName = StringTable->insert( fieldName ); 818 819 if( includeStatic && getClassRep()->findField( strFieldName ) ) 820 return true; 821 822 if( includeDynamic && getFieldDictionary() && getFieldDictionary()->findDynamicField( strFieldName ) ) 823 return true; 824 825 return false; 826} 827 828//----------------------------------------------------------------------------- 829 830void SimObject::assignDynamicFieldsFrom(SimObject* parent) 831{ 832 if(parent->mFieldDictionary) 833 { 834 if( mFieldDictionary == NULL ) 835 mFieldDictionary = new SimFieldDictionary; 836 mFieldDictionary->assignFrom(parent->mFieldDictionary); 837 } 838} 839 840//----------------------------------------------------------------------------- 841 842void SimObject::assignFieldsFrom(SimObject *parent) 843{ 844 // Only allow field assigns from objects of the same class or 845 // a superclass. 846 847 if( getClassRep()->isClass( parent->getClassRep() ) ) 848 { 849 const AbstractClassRep::FieldList &list = parent->getFieldList(); 850 851 // copy out all the fields: 852 for(U32 i = 0; i < list.size(); i++) 853 { 854 const AbstractClassRep::Field* f = &list[i]; 855 856 // Skip the special field types. 857 if ( f->type >= AbstractClassRep::ARCFirstCustomField ) 858 continue; 859 860 // Skip certain fields that we don't want to see copied so we don't 861 // get error messages from their setters. 862 863 static StringTableEntry sName = StringTable->insert( "name" ); 864 static StringTableEntry sPersistentId = StringTable->insert( "persistentId" ); 865 866 if( f->pFieldname == sName || f->pFieldname == sPersistentId ) 867 continue; 868 869 S32 lastField = f->elementCount - 1; 870 for(S32 j = 0; j <= lastField; j++) 871 { 872 const char* fieldVal = (*f->getDataFn)( parent, Con::getData(f->type, (void *) (((const char *)parent) + f->offset), j, f->table, f->flag)); 873 874 // Don't assign the field is the pointer is null or if 875 // the field is not empty and writing it was disallowed. 876 if ( !fieldVal || ( fieldVal[0] && !writeField( f->pFieldname, fieldVal ) ) ) 877 continue; 878 879 // code copied from SimObject::setDataField(). 880 // TODO: paxorr: abstract this into a better setData / getData that considers prot fields. 881 FrameTemp<char> buffer(2048); 882 FrameTemp<char> bufferSecure(2048); // This buffer is used to make a copy of the data 883 ConsoleBaseType *cbt = ConsoleBaseType::getType( f->type ); 884 const char* szBuffer = cbt->prepData( fieldVal, buffer, 2048 ); 885 dMemset( bufferSecure, 0, 2048 ); 886 dMemcpy( bufferSecure, szBuffer, dStrlen( szBuffer ) ); 887 888 if((*f->setDataFn)( this, NULL, bufferSecure ) ) 889 Con::setData(f->type, (void *) (((const char *)this) + f->offset), j, 1, &fieldVal, f->table); 890 } 891 } 892 } 893 else 894 { 895 Con::errorf( "SimObject::assignFieldsFrom() - cannot assigned fields from object of type '%s' to object of type '%s'", 896 parent->getClassName(), getClassName() 897 ); 898 } 899 900 assignDynamicFieldsFrom(parent); 901} 902 903//----------------------------------------------------------------------------- 904 905void SimObject::setDataField(StringTableEntry slotName, const char *array, const char *value) 906{ 907 // first search the static fields if enabled 908 if(mFlags.test(ModStaticFields)) 909 { 910 const AbstractClassRep::Field *fld = findField(slotName); 911 if(fld) 912 { 913 // Skip the special field types as they are not data. 914 if ( fld->type >= AbstractClassRep::ARCFirstCustomField ) 915 return; 916 917 S32 array1 = array ? dAtoi(array) : 0; 918 919 if(array1 >= 0 && array1 < fld->elementCount && fld->elementCount >= 1) 920 { 921 // If the set data notify callback returns true, then go ahead and 922 // set the data, otherwise, assume the set notify callback has either 923 // already set the data, or has deemed that the data should not 924 // be set at all. 925 FrameTemp<char> buffer(2048); 926 FrameTemp<char> bufferSecure(2048); // This buffer is used to make a copy of the data 927 // so that if the prep functions or any other functions use the string stack, the data 928 // is not corrupted. 929 930 ConsoleBaseType *cbt = ConsoleBaseType::getType( fld->type ); 931 AssertFatal( cbt != NULL, "Could not resolve Type Id." ); 932 933 const char* szBuffer = cbt->prepData( value, buffer, 2048 ); 934 dMemset( bufferSecure, 0, 2048 ); 935 dMemcpy( bufferSecure, szBuffer, dStrlen( szBuffer ) ); 936 937 if( (*fld->setDataFn)( this, array, bufferSecure ) ) 938 Con::setData(fld->type, (void *) (((const char *)this) + fld->offset), array1, 1, &value, fld->table); 939 940 if(fld->validator) 941 fld->validator->validateType(this, (void *) (((const char *)this) + fld->offset)); 942 943 onStaticModified( slotName, value ); 944 945 return; 946 } 947 948 if(fld->validator) 949 fld->validator->validateType(this, (void *) (((const char *)this) + fld->offset)); 950 951 onStaticModified( slotName, value ); 952 return; 953 } 954 } 955 956 if(mFlags.test(ModDynamicFields)) 957 { 958 if(!mFieldDictionary) 959 mFieldDictionary = new SimFieldDictionary; 960 961 if(!array) 962 { 963 mFieldDictionary->setFieldValue(slotName, value); 964 onDynamicModified( slotName, value ); 965 } 966 else 967 { 968 char buf[256]; 969 dStrcpy(buf, slotName); 970 dStrcat(buf, array); 971 StringTableEntry permanentSlotName = StringTable->insert(buf); 972 mFieldDictionary->setFieldValue(permanentSlotName, value); 973 onDynamicModified( permanentSlotName, value ); 974 } 975 } 976} 977 978//----------------------------------------------------------------------------- 979 980const char *SimObject::getDataField(StringTableEntry slotName, const char *array) 981{ 982 if(mFlags.test(ModStaticFields)) 983 { 984 S32 array1 = array ? dAtoi(array) : -1; 985 const AbstractClassRep::Field *fld = findField(slotName); 986 987 if(fld) 988 { 989 if(array1 == -1 && fld->elementCount == 1) 990 return (*fld->getDataFn)( this, Con::getData(fld->type, (void *) (((const char *)this) + fld->offset), 0, fld->table, fld->flag) ); 991 if(array1 >= 0 && array1 < fld->elementCount) 992 return (*fld->getDataFn)( this, Con::getData(fld->type, (void *) (((const char *)this) + fld->offset), array1, fld->table, fld->flag) );// + typeSizes[fld.type] * array1)); 993 return ""; 994 } 995 } 996 997 if(mFlags.test(ModDynamicFields)) 998 { 999 if(!mFieldDictionary) 1000 return ""; 1001 1002 if(!array) 1003 { 1004 if (const char* val = mFieldDictionary->getFieldValue(slotName)) 1005 return val; 1006 } 1007 else 1008 { 1009 static char buf[256]; 1010 dStrcpy(buf, slotName); 1011 dStrcat(buf, array); 1012 if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf))) 1013 return val; 1014 } 1015 } 1016 1017 return ""; 1018} 1019 1020 1021const char *SimObject::getPrefixedDataField(StringTableEntry fieldName, const char *array) 1022{ 1023 // Sanity! 1024 AssertFatal(fieldName != NULL, "Cannot get field value with NULL field name."); 1025 1026 // Fetch field value. 1027 const char* pFieldValue = getDataField(fieldName, array); 1028 1029 // Sanity. 1030 //AssertFatal(pFieldValue != NULL, "Field value cannot be NULL."); 1031 if (!pFieldValue) 1032 return NULL; 1033 1034 // Return without the prefix if there's no value. 1035 if (*pFieldValue == 0) 1036 return StringTable->EmptyString(); 1037 1038 // Fetch the field prefix. 1039 StringTableEntry fieldPrefix = getDataFieldPrefix(fieldName); 1040 1041 // Sanity! 1042 AssertFatal(fieldPrefix != NULL, "Field prefix cannot be NULL."); 1043 1044 // Calculate a buffer size including prefix. 1045 const U32 valueBufferSize = dStrlen(fieldPrefix) + dStrlen(pFieldValue) + 1; 1046 1047 // Fetch a buffer. 1048 char* pValueBuffer = Con::getReturnBuffer(valueBufferSize); 1049 1050 // Format the value buffer. 1051 dSprintf(pValueBuffer, valueBufferSize, "%s%s", fieldPrefix, pFieldValue); 1052 1053 return pValueBuffer; 1054} 1055 1056//----------------------------------------------------------------------------- 1057 1058void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value) 1059{ 1060 // Sanity! 1061 AssertFatal(fieldName != NULL, "Cannot set object field value with NULL field name."); 1062 AssertFatal(value != NULL, "Field value cannot be NULL."); 1063 1064 // Set value without prefix if there's no value. 1065 if (*value == 0) 1066 { 1067 setDataField(fieldName, NULL, value); 1068 return; 1069 } 1070 1071 // Fetch the field prefix. 1072 StringTableEntry fieldPrefix = getDataFieldPrefix(fieldName); 1073 1074 // Sanity. 1075 AssertFatal(fieldPrefix != NULL, "Field prefix cannot be NULL."); 1076 1077 // Do we have a field prefix? 1078 if (fieldPrefix == StringTable->EmptyString()) 1079 { 1080 // No, so set the data field in the usual way. 1081 setDataField(fieldName, NULL, value); 1082 return; 1083 } 1084 1085 // Yes, so fetch the length of the field prefix. 1086 const U32 fieldPrefixLength = dStrlen(fieldPrefix); 1087 1088 // Yes, so does it start with the object field prefix? 1089 if (dStrnicmp(value, fieldPrefix, fieldPrefixLength) != 0) 1090 { 1091 // No, so set the data field in the usual way. 1092 setDataField(fieldName, NULL, value); 1093 return; 1094 } 1095 1096 // Yes, so set the data excluding the prefix. 1097 setDataField(fieldName, NULL, value + fieldPrefixLength); 1098} 1099 1100//----------------------------------------------------------------------------- 1101 1102const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType) 1103{ 1104 // Sanity! 1105 AssertFatal(fieldName != NULL, "Cannot get field value with NULL field name."); 1106 1107 // Fetch field value. 1108 const char* pFieldValue = getDataField(fieldName, array); 1109 1110 // Sanity. 1111 AssertFatal(pFieldValue != NULL, "Field value cannot be NULL."); 1112 1113 // Return the field if no field type is specified. 1114 if (fieldType == -1) 1115 return pFieldValue; 1116 1117 // Return without the prefix if there's no value. 1118 if (*pFieldValue == 0) 1119 return StringTable->EmptyString(); 1120 1121 // Fetch the console base type. 1122 ConsoleBaseType* pConsoleBaseType = ConsoleBaseType::getType(fieldType); 1123 1124 // Did we find the console base type? 1125 if (pConsoleBaseType == NULL) 1126 { 1127 // No, so warn. 1128 Con::warnf("getPrefixedDynamicDataField() - Invalid field type '%d' specified for field '%s' with value '%s'.", 1129 fieldType, fieldName, pFieldValue); 1130 } 1131 1132 // Fetch the field prefix. 1133 StringTableEntry fieldPrefix = pConsoleBaseType->getTypePrefix(); 1134 1135 // Sanity! 1136 AssertFatal(fieldPrefix != NULL, "Field prefix cannot be NULL."); 1137 1138 // Calculate a buffer size including prefix. 1139 const U32 valueBufferSize = dStrlen(fieldPrefix) + dStrlen(pFieldValue) + 1; 1140 1141 // Fetch a buffer. 1142 char* pValueBuffer = Con::getReturnBuffer(valueBufferSize); 1143 1144 // Format the value buffer. 1145 dSprintf(pValueBuffer, valueBufferSize, "%s%s", fieldPrefix, pFieldValue); 1146 1147 return pValueBuffer; 1148} 1149 1150//----------------------------------------------------------------------------- 1151 1152void SimObject::setPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const char *value, const S32 fieldType) 1153{ 1154 // Sanity! 1155 AssertFatal(fieldName != NULL, "Cannot set object field value with NULL field name."); 1156 AssertFatal(value != NULL, "Field value cannot be NULL."); 1157 1158 // Set value without prefix if no field type was specified. 1159 if (fieldType == -1) 1160 { 1161 setDataField(fieldName, NULL, value); 1162 return; 1163 } 1164 1165 // Fetch the console base type. 1166 ConsoleBaseType* pConsoleBaseType = ConsoleBaseType::getType(fieldType); 1167 1168 // Did we find the console base type? 1169 if (pConsoleBaseType == NULL) 1170 { 1171 // No, so warn. 1172 Con::warnf("setPrefixedDynamicDataField() - Invalid field type '%d' specified for field '%s' with value '%s'.", 1173 fieldType, fieldName, value); 1174 } 1175 1176 // Set value without prefix if there's no value or we didn't find the console base type. 1177 if (*value == 0 || pConsoleBaseType == NULL) 1178 { 1179 setDataField(fieldName, NULL, value); 1180 return; 1181 } 1182 1183 // Fetch the field prefix. 1184 StringTableEntry fieldPrefix = pConsoleBaseType->getTypePrefix(); 1185 1186 // Sanity. 1187 AssertFatal(fieldPrefix != NULL, "Field prefix cannot be NULL."); 1188 1189 // Do we have a field prefix? 1190 if (fieldPrefix == StringTable->EmptyString()) 1191 { 1192 // No, so set the data field in the usual way. 1193 setDataField(fieldName, NULL, value); 1194 return; 1195 } 1196 1197 // Yes, so fetch the length of the field prefix. 1198 const U32 fieldPrefixLength = dStrlen(fieldPrefix); 1199 1200 // Yes, so does it start with the object field prefix? 1201 if (dStrnicmp(value, fieldPrefix, fieldPrefixLength) != 0) 1202 { 1203 // No, so set the data field in the usual way. 1204 setDataField(fieldName, NULL, value); 1205 return; 1206 } 1207 1208 // Yes, so set the data excluding the prefix. 1209 setDataField(fieldName, NULL, value + fieldPrefixLength); 1210} 1211 1212//----------------------------------------------------------------------------- 1213 1214StringTableEntry SimObject::getDataFieldPrefix(StringTableEntry fieldName) 1215{ 1216 // Sanity! 1217 AssertFatal(fieldName != NULL, "Cannot get field prefix with NULL field name."); 1218 1219 // Find the field. 1220 const AbstractClassRep::Field* pField = findField(fieldName); 1221 1222 // Return nothing if field was not found. 1223 if (pField == NULL) 1224 return StringTable->EmptyString(); 1225 1226 // Yes, so fetch the console base type. 1227 ConsoleBaseType* pConsoleBaseType = ConsoleBaseType::getType(pField->type); 1228 1229 // Fetch the type prefix. 1230 return pConsoleBaseType->getTypePrefix(); 1231} 1232 1233 1234//----------------------------------------------------------------------------- 1235 1236U32 SimObject::getDataFieldType( StringTableEntry slotName, const char* array ) 1237{ 1238 const AbstractClassRep::Field* field = findField( slotName ); 1239 if(field) 1240 return field->type; 1241 1242 // Check dynamic fields 1243 if(!mFieldDictionary) 1244 return 0; 1245 1246 if(array == NULL || *array == 0) 1247 return mFieldDictionary->getFieldType( slotName ); 1248 else 1249 { 1250 static char buf[256]; 1251 dStrcpy( buf, slotName ); 1252 dStrcat( buf, array ); 1253 1254 return mFieldDictionary->getFieldType( StringTable->insert( buf ) ); 1255 } 1256} 1257 1258//----------------------------------------------------------------------------- 1259 1260void SimObject::setDataFieldType(const U32 fieldTypeId, StringTableEntry slotName, const char *array) 1261{ 1262 // This only works on dynamic fields, bail if we have no field dictionary 1263 if(!mFieldDictionary) 1264 return; 1265 1266 if(array == NULL || *array == 0) 1267 { 1268 mFieldDictionary->setFieldType( slotName, fieldTypeId ); 1269 onDynamicModified( slotName, mFieldDictionary->getFieldValue(slotName) ); 1270 } 1271 else 1272 { 1273 static char buf[256]; 1274 dStrcpy( buf, slotName ); 1275 dStrcat( buf, array ); 1276 1277 mFieldDictionary->setFieldType( StringTable->insert( buf ), fieldTypeId ); 1278 onDynamicModified( slotName, mFieldDictionary->getFieldValue(slotName) ); 1279 } 1280} 1281 1282//----------------------------------------------------------------------------- 1283 1284void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName, const char *array) 1285{ 1286 // This only works on dynamic fields, bail if we have no field dictionary 1287 if(!mFieldDictionary) 1288 return; 1289 1290 if(array == NULL || *array == 0) 1291 mFieldDictionary->setFieldType( slotName, typeName ); 1292 else 1293 { 1294 static char buf[256]; 1295 dStrcpy( buf, slotName ); 1296 dStrcat( buf, array ); 1297 StringTableEntry permanentSlotName = StringTable->insert(buf); 1298 1299 mFieldDictionary->setFieldType( permanentSlotName, typeName ); 1300 onDynamicModified( permanentSlotName, mFieldDictionary->getFieldValue(permanentSlotName) ); 1301 } 1302} 1303 1304//----------------------------------------------------------------------------- 1305 1306void SimObject::dumpClassHierarchy() 1307{ 1308 AbstractClassRep* pRep = getClassRep(); 1309 while(pRep) 1310 { 1311 Con::warnf("%s ->", pRep->getClassName()); 1312 pRep = pRep->getParentClass(); 1313 } 1314} 1315 1316//----------------------------------------------------------------------------- 1317 1318SimObject* SimObject::clone() 1319{ 1320 if( !getClassRep() ) 1321 return NULL; 1322 1323 ConsoleObject* conObject = getClassRep()->create(); 1324 if( !conObject ) 1325 return NULL; 1326 1327 SimObject* simObject = dynamic_cast< SimObject* >( conObject ); 1328 if( !simObject ) 1329 { 1330 delete conObject; 1331 return NULL; 1332 } 1333 1334 simObject->assignFieldsFrom( this ); 1335 1336 String name = Sim::getUniqueName( getName() ); 1337 if( !simObject->registerObject( name ) ) 1338 { 1339 delete simObject; 1340 return NULL; 1341 } 1342 1343 if( getGroup() ) 1344 getGroup()->addObject( simObject ); 1345 1346 return simObject; 1347} 1348 1349//----------------------------------------------------------------------------- 1350 1351SimObject* SimObject::deepClone() 1352{ 1353 return clone(); 1354} 1355 1356//============================================================================= 1357// Grouping. 1358//============================================================================= 1359// MARK: ---- Grouping ---- 1360 1361//----------------------------------------------------------------------------- 1362 1363SimObject* SimObject::findObject( const char* ) 1364{ 1365 return NULL; 1366} 1367 1368//----------------------------------------------------------------------------- 1369 1370bool SimObject::isChildOfGroup(SimGroup* pGroup) 1371{ 1372 if(!pGroup) 1373 return false; 1374 1375 //if we *are* the group in question, 1376 //return true: 1377 if(pGroup == dynamic_cast<SimGroup*>(this)) 1378 return true; 1379 1380 SimGroup* temp = mGroup; 1381 while(temp) 1382 { 1383 if(temp == pGroup) 1384 return true; 1385 temp = temp->mGroup; 1386 } 1387 1388 return false; 1389} 1390 1391//----------------------------------------------------------------------------- 1392 1393bool SimObject::addToSet(SimObjectId spid) 1394{ 1395 if (mFlags.test(Added) == false) 1396 return false; 1397 1398 SimObject* ptr = Sim::findObject(spid); 1399 if (ptr) 1400 { 1401 SimSet* sp = dynamic_cast<SimSet*>(ptr); 1402 AssertFatal(sp != 0, 1403 "SimObject::addToSet: " 1404 "ObjectId does not refer to a set object"); 1405 sp->addObject(this); 1406 return true; 1407 } 1408 return false; 1409} 1410 1411//----------------------------------------------------------------------------- 1412 1413bool SimObject::addToSet(const char *ObjectName) 1414{ 1415 if (mFlags.test(Added) == false) 1416 return false; 1417 1418 SimObject* ptr = Sim::findObject(ObjectName); 1419 if (ptr) 1420 { 1421 SimSet* sp = dynamic_cast<SimSet*>(ptr); 1422 AssertFatal(sp != 0, 1423 "SimObject::addToSet: " 1424 "ObjectName does not refer to a set object"); 1425 sp->addObject(this); 1426 return true; 1427 } 1428 return false; 1429} 1430 1431//----------------------------------------------------------------------------- 1432 1433bool SimObject::removeFromSet(SimObjectId sid) 1434{ 1435 if (mFlags.test(Added) == false) 1436 return false; 1437 1438 SimSet *set; 1439 if(Sim::findObject(sid, set)) 1440 { 1441 set->removeObject(this); 1442 return true; 1443 } 1444 return false; 1445} 1446 1447//----------------------------------------------------------------------------- 1448 1449bool SimObject::removeFromSet(const char *objectName) 1450{ 1451 if (mFlags.test(Added) == false) 1452 return false; 1453 1454 SimSet *set; 1455 if(Sim::findObject(objectName, set)) 1456 { 1457 set->removeObject(this); 1458 return true; 1459 } 1460 return false; 1461} 1462 1463//----------------------------------------------------------------------------- 1464 1465void SimObject::dumpGroupHierarchy() 1466{ 1467 String className( getClassName() ); 1468 String objectName( getName() ); 1469 1470 Con::warnf( "[%i] %s - %s ->", getId(), className.c_str(), objectName.c_str() ); 1471 1472 if ( mGroup ) 1473 mGroup->dumpGroupHierarchy(); 1474} 1475 1476//============================================================================= 1477// Events. 1478//============================================================================= 1479// MARK: ---- Events ---- 1480 1481//----------------------------------------------------------------------------- 1482 1483bool SimObject::onAdd() 1484{ 1485 mFlags.set(Added); 1486 1487 linkNamespaces(); 1488 1489 return true; 1490} 1491 1492//----------------------------------------------------------------------------- 1493 1494void SimObject::onRemove() 1495{ 1496 mFlags.clear(Added); 1497 1498 unlinkNamespaces(); 1499} 1500 1501//----------------------------------------------------------------------------- 1502 1503void SimObject::onGroupAdd() 1504{ 1505} 1506 1507//----------------------------------------------------------------------------- 1508 1509void SimObject::onGroupRemove() 1510{ 1511} 1512 1513//----------------------------------------------------------------------------- 1514 1515void SimObject::onDeleteNotify(SimObject*) 1516{ 1517} 1518 1519//----------------------------------------------------------------------------- 1520 1521void SimObject::onNameChange(const char*) 1522{ 1523} 1524 1525//----------------------------------------------------------------------------- 1526 1527void SimObject::onStaticModified(const char* slotName, const char* newValue) 1528{ 1529} 1530 1531//----------------------------------------------------------------------------- 1532 1533void SimObject::onDynamicModified(const char* slotName, const char* newValue) 1534{ 1535} 1536 1537//============================================================================= 1538// Notifications. 1539//============================================================================= 1540// MARK: ---- Notifications ---- 1541 1542static Chunker<SimObject::Notify> notifyChunker(128000); 1543SimObject::Notify *SimObject::mNotifyFreeList = NULL; 1544 1545//----------------------------------------------------------------------------- 1546 1547SimObject::Notify *SimObject::allocNotify() 1548{ 1549 if(mNotifyFreeList) 1550 { 1551 SimObject::Notify *ret = mNotifyFreeList; 1552 mNotifyFreeList = ret->next; 1553 return ret; 1554 } 1555 return notifyChunker.alloc(); 1556} 1557 1558//----------------------------------------------------------------------------- 1559 1560void SimObject::freeNotify(SimObject::Notify* note) 1561{ 1562 AssertFatal(note->type != SimObject::Notify::Invalid, "Invalid notify"); 1563 note->type = SimObject::Notify::Invalid; 1564 note->next = mNotifyFreeList; 1565 mNotifyFreeList = note; 1566} 1567 1568//----------------------------------------------------------------------------- 1569 1570SimObject::Notify* SimObject::removeNotify(void *ptr, SimObject::Notify::Type type) 1571{ 1572 Notify **list = &mNotifyList; 1573 while(*list) 1574 { 1575 if((*list)->ptr == ptr && (*list)->type == type) 1576 { 1577 SimObject::Notify *ret = *list; 1578 *list = ret->next; 1579 return ret; 1580 } 1581 list = &((*list)->next); 1582 } 1583 return NULL; 1584} 1585 1586//----------------------------------------------------------------------------- 1587 1588void SimObject::deleteNotify(SimObject* obj) 1589{ 1590 AssertFatal(!obj->isDeleted(), 1591 "SimManager::deleteNotify: Object is being deleted"); 1592 Notify *note = allocNotify(); 1593 note->ptr = (void *) this; 1594 note->next = obj->mNotifyList; 1595 note->type = Notify::DeleteNotify; 1596 obj->mNotifyList = note; 1597 1598 note = allocNotify(); 1599 note->ptr = (void *) obj; 1600 note->next = mNotifyList; 1601 note->type = Notify::ClearNotify; 1602 mNotifyList = note; 1603 1604 //obj->deleteNotifyList.pushBack(this); 1605 //clearNotifyList.pushBack(obj); 1606} 1607 1608//----------------------------------------------------------------------------- 1609 1610void SimObject::registerReference(SimObject **ptr) 1611{ 1612 Notify *note = allocNotify(); 1613 note->ptr = (void *) ptr; 1614 note->next = mNotifyList; 1615 note->type = Notify::ObjectRef; 1616 mNotifyList = note; 1617} 1618 1619//----------------------------------------------------------------------------- 1620 1621void SimObject::unregisterReference(SimObject **ptr) 1622{ 1623 Notify *note = removeNotify((void *) ptr, Notify::ObjectRef); 1624 if(note) 1625 { 1626 freeNotify(note); 1627 1628 if( mFlags.test( AutoDelete ) ) 1629 { 1630 for( Notify* n = mNotifyList; n != NULL; n = n->next ) 1631 if( n->type == Notify::ObjectRef ) 1632 return; 1633 1634 deleteObject(); 1635 } 1636 } 1637} 1638 1639//----------------------------------------------------------------------------- 1640 1641void SimObject::clearNotify(SimObject* obj) 1642{ 1643 Notify *note = obj->removeNotify((void *) this, Notify::DeleteNotify); 1644 if(note) 1645 freeNotify(note); 1646 1647 note = removeNotify((void *) obj, Notify::ClearNotify); 1648 if(note) 1649 freeNotify(note); 1650} 1651 1652//----------------------------------------------------------------------------- 1653 1654void SimObject::processDeleteNotifies() 1655{ 1656 // clear out any delete notifies and 1657 // object refs. 1658 1659 while(mNotifyList) 1660 { 1661 Notify *note = mNotifyList; 1662 mNotifyList = note->next; 1663 1664 AssertFatal(note->type != Notify::ClearNotify, "Clear notes should be all gone."); 1665 1666 if(note->type == Notify::DeleteNotify) 1667 { 1668 SimObject *obj = (SimObject *) note->ptr; 1669 Notify *cnote = obj->removeNotify((void *)this, Notify::ClearNotify); 1670 obj->onDeleteNotify(this); 1671 freeNotify(cnote); 1672 } 1673 else 1674 { 1675 // it must be an object ref - a pointer refs this object 1676 *((SimObject **) note->ptr) = NULL; 1677 } 1678 freeNotify(note); 1679 } 1680} 1681 1682//----------------------------------------------------------------------------- 1683 1684void SimObject::clearAllNotifications() 1685{ 1686 for(Notify **cnote = &mNotifyList; *cnote; ) 1687 { 1688 Notify *temp = *cnote; 1689 if(temp->type == Notify::ClearNotify) 1690 { 1691 *cnote = temp->next; 1692 Notify *note = ((SimObject *) temp->ptr)->removeNotify((void *) this, Notify::DeleteNotify); 1693 freeNotify(temp); 1694 if ( note ) 1695 freeNotify(note); 1696 } 1697 else 1698 cnote = &(temp->next); 1699 } 1700} 1701 1702//============================================================================= 1703// Namespaces. 1704//============================================================================= 1705// MARK: ---- Namespaces ---- 1706 1707//----------------------------------------------------------------------------- 1708 1709void SimObject::linkNamespaces() 1710{ 1711 // Don't link if we already have a namespace linkage in place. 1712 // If you want to change namespace linking, first call unlinkNamespaces() 1713 // while still having the class namespace fields matching the current 1714 // setup. 1715 1716 if (mNameSpace) 1717 { 1718 Con::warnf("SimObject::linkNamespaces -- Namespace linkage already in place %s", mNameSpace->getName()); 1719 return; 1720 } 1721 // Get the namespace for the C++ class. 1722 1723 Namespace* cppNamespace = getClassRep()->getNameSpace(); 1724 1725 // Parent namespace defaults to namespace of C++ class. 1726 1727 Namespace* parentNamespace = cppNamespace; 1728 1729 // Perform superclass linking, if requested. 1730 1731 if( mSuperClassName && mSuperClassName[ 0 ] ) 1732 { 1733 // Look up the superclass namespace. 1734 1735 Namespace* superClassNamespace = Con::lookupNamespace( mSuperClassName ); 1736 1737 // If packages are active and adding to the superclass namespace, then we will 1738 // have multiple packages in a parent chain that all have the same name. 1739 // Con::lookupNamespace returns the bottom-most package in the chain to us so 1740 // in order to properly link namespace here without conflicting with the package 1741 // mechanism, we need to properly link child namespaces to the bottom-most namespace 1742 // while linking parent namespaces to the topmost namespace. To find the latter 1743 // one, we walk up the hierarchy here. 1744 1745 Namespace* superClassNamespacePackageRoot = superClassNamespace->getPackageRoot(); 1746 1747 // Link the superclass namespace to the C++ class namespace. 1748 1749 if( superClassNamespacePackageRoot->getParent() == NULL ) 1750 { 1751 // The superclass namespace isn't linked yet so we just 1752 // link it to the C++ class namespace and make that our parent. 1753 // No increasing parent reference counts is needed in this case. 1754 1755 bool ok = superClassNamespacePackageRoot->classLinkTo( cppNamespace ); 1756 AssertFatal( ok, "SimObject::linkNamespaces - failed to link new namespace to c++ class name" ); 1757 parentNamespace = superClassNamespace; 1758 } 1759 else 1760 { 1761 // In debug builds, make sure the namespace hierarchy that's been 1762 // put into place actually makes sense and leads back to the C++ 1763 // class namespace. 1764 1765#ifdef TORQUE_DEBUG 1766 1767 bool foundClassNameNS = false; 1768 for( Namespace* linkWalk = superClassNamespacePackageRoot->getParent(); linkWalk != NULL; 1769 linkWalk = linkWalk->getParent() ) 1770 { 1771 if( linkWalk == cppNamespace ) 1772 { 1773 foundClassNameNS = true; 1774 break; 1775 } 1776 } 1777 1778 if( !foundClassNameNS ) 1779 { 1780 // C++ class namespace not in parent link chain. Warn about it. 1781 1782 Con::errorf( 1783 "SimObject::linkNamespaces - cannot link object to superclass %s because c++ class %s is not in the parent namespace chain. Linking object to c++ class.", 1784 mSuperClassName, 1785 getClassName() 1786 ); 1787 1788 // Clear out superclass name so we don't come across it during 1789 // unlinking. 1790 1791 mSuperClassName = NULL; 1792 } 1793 else 1794 1795#endif 1796 { 1797 // Super link is ok. 1798 1799 parentNamespace = superClassNamespace; 1800 1801 // Now increase the reference count of all namespaces in the parent hierarchy 1802 // (up to the C++ class). 1803 1804 for( Namespace* linkWalk = parentNamespace; 1805 linkWalk != NULL && linkWalk != cppNamespace && linkWalk->getParent() != NULL; 1806 linkWalk = linkWalk->getParent() ) 1807 { 1808 // Skip namespaces coming from packages. 1809 if( linkWalk->getPackage() != NULL ) 1810 continue; 1811 1812 linkWalk->incRefCountToParent(); 1813 } 1814 } 1815 } 1816 } 1817 1818 // If class name is set, link it in as the new parent 1819 // which itself inherits from the current parent. 1820 1821 if( mClassName && mClassName[ 0 ] ) 1822 { 1823 Namespace* classNamespace = Con::lookupNamespace( mClassName ); 1824 if( classNamespace && classNamespace->classLinkTo( parentNamespace ) ) 1825 { 1826 parentNamespace = classNamespace; 1827 } 1828 else 1829 { 1830 // Clear out class name so we don't perform a bogus unlink 1831 // in unlinkNamespaces(). 1832 mClassName = NULL; 1833 } 1834 } 1835 1836 // Finally, if we have an object name, link its namespace 1837 // as the child to the current parent namespace and let it 1838 // become the final namespace of this object. 1839 1840 StringTableEntry objectName = getName(); 1841 if( objectName && objectName[ 0 ] ) 1842 { 1843 Namespace* objectNamespace = Con::lookupNamespace( objectName ); 1844 if( objectNamespace && objectNamespace->classLinkTo( parentNamespace ) ) 1845 { 1846 parentNamespace = objectNamespace; 1847 } 1848 } 1849 1850 // Store our namespace. 1851 1852 mNameSpace = parentNamespace; 1853} 1854 1855//----------------------------------------------------------------------------- 1856 1857void SimObject::unlinkNamespaces() 1858{ 1859 if( !mNameSpace ) 1860 return; 1861 1862 Namespace* cppNamespace = getClassRep()->getNameSpace(); 1863 Namespace* parentNamespace = cppNamespace; 1864 1865 // Handle superclass. 1866 1867 if( mSuperClassName && mSuperClassName[ 0 ] ) 1868 { 1869 // Get the superclass namespace. 1870 1871 Namespace* superClassNamespace = Con::lookupNamespace( mSuperClassName ); 1872 1873 // Make it the parent namespace. 1874 1875 parentNamespace = superClassNamespace; 1876 1877 // Decrease parent refcounts on the superclass hierarchy. 1878 1879 for( Namespace* linkWalk = superClassNamespace; 1880 linkWalk != NULL && linkWalk != cppNamespace && linkWalk->getParent() != NULL; ) 1881 { 1882 // Store the parent link since it may disappear once we 1883 // decrease the reference count. 1884 Namespace* parent = linkWalk->getParent(); 1885 1886 // Decrease the refcount. 1887 if( linkWalk->getPackage() == NULL ) // Skip namespaces coming from packages. 1888 linkWalk->decRefCountToParent(); 1889 1890 // Walk up. 1891 linkWalk = parent; 1892 } 1893 } 1894 1895 // Handle class. 1896 1897 if( mClassName && mClassName[ 0 ] ) 1898 { 1899 Namespace* classNamespace = Con::lookupNamespace( mClassName ); 1900 if( classNamespace ) 1901 { 1902 classNamespace->decRefCountToParent(); 1903 parentNamespace = classNamespace; 1904 } 1905 } 1906 1907 // Handle object name. 1908 1909 StringTableEntry objectName = getName(); 1910 if( objectName && objectName[ 0 ] ) 1911 mNameSpace->decRefCountToParent(); 1912 1913 mNameSpace = NULL; 1914} 1915 1916//----------------------------------------------------------------------------- 1917 1918void SimObject::setClassNamespace( const char *classNamespace ) 1919{ 1920 StringTableEntry oldClassNamespace = mClassName; 1921 StringTableEntry newClassNamespace = StringTable->insert( classNamespace ); 1922 1923 if( oldClassNamespace == newClassNamespace ) 1924 return; 1925 1926 if( isProperlyAdded() ) 1927 unlinkNamespaces(); 1928 1929 mClassName = newClassNamespace; 1930 1931 if( isProperlyAdded() ) 1932 { 1933 linkNamespaces(); 1934 1935 // Restore old namespace setup if linkage failed. 1936 1937 if( mClassName != newClassNamespace ) 1938 { 1939 mClassName = oldClassNamespace; 1940 linkNamespaces(); 1941 } 1942 } 1943} 1944 1945//----------------------------------------------------------------------------- 1946 1947void SimObject::setSuperClassNamespace( const char *superClassNamespace ) 1948{ 1949 StringTableEntry oldSuperClassNamespace = mSuperClassName; 1950 StringTableEntry newSuperClassNamespace = StringTable->insert( superClassNamespace ); 1951 1952 if( oldSuperClassNamespace == newSuperClassNamespace ) 1953 return; 1954 1955 if( isProperlyAdded() ) 1956 unlinkNamespaces(); 1957 1958 mSuperClassName = newSuperClassNamespace; 1959 1960 if( isProperlyAdded() ) 1961 { 1962 linkNamespaces(); 1963 1964 // Restore old setup if linkage failed. 1965 1966 if( mSuperClassName != newSuperClassNamespace ) 1967 { 1968 mSuperClassName = oldSuperClassNamespace; 1969 linkNamespaces(); 1970 } 1971 } 1972} 1973 1974//============================================================================= 1975// Misc. 1976//============================================================================= 1977// MARK: ---- Misc ---- 1978 1979//----------------------------------------------------------------------------- 1980 1981void SimObject::setInternalName( const char* newname ) 1982{ 1983 if( newname ) 1984 mInternalName = StringTable->insert( newname ); 1985 else 1986 mInternalName = StringTable->EmptyString(); 1987} 1988 1989//----------------------------------------------------------------------------- 1990 1991void SimObject::setOriginalName( const char* originalName ) 1992{ 1993 if( originalName ) 1994 mOriginalName = StringTable->insert( originalName ); 1995 else 1996 mOriginalName = StringTable->EmptyString(); 1997} 1998 1999//----------------------------------------------------------------------------- 2000 2001const char *SimObject::tabComplete(const char *prevText, S32 baseLen, bool fForward) 2002{ 2003 return mNameSpace->tabComplete(prevText, baseLen, fForward); 2004} 2005 2006//----------------------------------------------------------------------------- 2007 2008void SimObject::setSelected( bool sel ) 2009{ 2010 if( mFlags.test( Selected ) == sel ) 2011 return; // No change. 2012 2013 if( sel ) 2014 { 2015 mFlags.set( Selected ); 2016 _onSelected(); 2017 } 2018 else 2019 { 2020 mFlags.clear( Selected ); 2021 _onUnselected(); 2022 } 2023} 2024 2025//----------------------------------------------------------------------------- 2026 2027bool SimObject::isSelectedRecursive() const 2028{ 2029 const SimObject *walk = this; 2030 while ( walk ) 2031 { 2032 if ( walk->isSelected() ) 2033 return true; 2034 walk = walk->getGroup(); 2035 } 2036 2037 return false; 2038} 2039 2040//----------------------------------------------------------------------------- 2041 2042void SimObject::setLocked( bool b ) 2043{ 2044 if( b ) 2045 mFlags.set( Locked ); 2046 else 2047 mFlags.clear( Locked ); 2048} 2049 2050//----------------------------------------------------------------------------- 2051 2052void SimObject::setHidden( bool b ) 2053{ 2054 if( b ) 2055 mFlags.set( Hidden ); 2056 else 2057 mFlags.clear( Hidden ); 2058} 2059 2060//----------------------------------------------------------------------------- 2061 2062void SimObject::setCopySource( SimObject* object ) 2063{ 2064 if( mCopySource ) 2065 mCopySource->unregisterReference( &mCopySource ); 2066 mCopySource = object; 2067 if( mCopySource ) 2068 mCopySource->registerReference( &mCopySource ); 2069} 2070 2071//--------------------------------------------------------------------------- 2072 2073bool SimObject::_setCanSave( void* object, const char* index, const char* data ) 2074{ 2075 SimObject* obj = reinterpret_cast< SimObject* >( object ); 2076 obj->setCanSave( dAtob( data ) ); 2077 return false; 2078} 2079 2080//----------------------------------------------------------------------------- 2081 2082const char* SimObject::_getCanSave( void* object, const char* data ) 2083{ 2084 SimObject* obj = reinterpret_cast< SimObject* >( object ); 2085 if( obj->getCanSave() ) 2086 return "1"; 2087 else 2088 return "0"; 2089} 2090 2091//--------------------------------------------------------------------------- 2092 2093// Copy SimObject to another SimObject (Originally designed for T2D). 2094void SimObject::copyTo( SimObject* object ) 2095{ 2096 object->mClassName = mClassName; 2097 object->mSuperClassName = mSuperClassName; 2098 2099 linkNamespaces(); 2100} 2101 2102//----------------------------------------------------------------------------- 2103 2104bool SimObject::setProtectedParent( void *obj, const char *index, const char *data ) 2105{ 2106 SimGroup *parent = NULL; 2107 SimObject *object = static_cast<SimObject*>(obj); 2108 2109 if(Sim::findObject(data, parent)) 2110 parent->addObject(object); 2111 2112 // always return false, because we've set mGroup when we called addObject 2113 return false; 2114} 2115 2116//----------------------------------------------------------------------------- 2117 2118bool SimObject::setProtectedName(void *obj, const char *index, const char *data) 2119{ 2120 SimObject *object = static_cast<SimObject*>(obj); 2121 2122 if ( object->isProperlyAdded() ) 2123 object->assignName( data ); 2124 2125 // always return false because we assign the name here 2126 return false; 2127} 2128 2129//----------------------------------------------------------------------------- 2130 2131void SimObject::inspectPreApply() 2132{ 2133} 2134 2135//----------------------------------------------------------------------------- 2136 2137void SimObject::inspectPostApply() 2138{ 2139} 2140 2141//----------------------------------------------------------------------------- 2142 2143String SimObject::_getLogMessage(const char* fmt, va_list args) const 2144{ 2145 String objClass = "UnknownClass"; 2146 if(getClassRep()) 2147 objClass = getClassRep()->getClassName(); 2148 2149 String objName = getName(); 2150 if(objName.isEmpty()) 2151 objName = "Unnamed"; 2152 2153 String formattedMessage = String::VToString(fmt, args); 2154 return String::ToString("%s - %s(%i) - %s", 2155 objClass.c_str(), objName.c_str(), getId(), formattedMessage.c_str()); 2156} 2157 2158//============================================================================= 2159// API. 2160//============================================================================= 2161// MARK: ---- API ---- 2162 2163//----------------------------------------------------------------------------- 2164 2165DefineEngineMethod( SimObject, dumpGroupHierarchy, void, (),, 2166 "Dump the hierarchy of this object up to RootGroup to the console." ) 2167{ 2168 object->dumpGroupHierarchy(); 2169} 2170 2171//----------------------------------------------------------------------------- 2172 2173DefineConsoleMethod( SimObject, isMethod, bool, ( const char* methodName ),, 2174 "Test whether the given method is defined on this object.\n" 2175 "@param The name of the method.\n" 2176 "@return True if the object implements the given method." ) 2177{ 2178 return object->isMethod( methodName ); 2179} 2180 2181//----------------------------------------------------------------------------- 2182 2183DefineEngineMethod( SimObject, isChildOfGroup, bool, ( SimGroup* group ),, 2184 "Test whether the object belongs directly or indirectly to the given group.\n" 2185 "@param group The SimGroup object.\n" 2186 "@return True if the object is a child of the given group or a child of a group that the given group is directly or indirectly a child to." ) 2187{ 2188 return object->isChildOfGroup( group ); 2189} 2190 2191//----------------------------------------------------------------------------- 2192 2193DefineConsoleMethod( SimObject, getClassNamespace, const char*, (),, 2194 "Get the name of the class namespace assigned to this object.\n" 2195 "@return The name of the 'class' namespace." ) 2196{ 2197 return object->getClassNamespace(); 2198} 2199 2200//----------------------------------------------------------------------------- 2201 2202DefineConsoleMethod( SimObject, getSuperClassNamespace, const char*, (),, 2203 "Get the name of the superclass namespace assigned to this object.\n" 2204 "@return The name of the 'superClass' namespace." ) 2205{ 2206 return object->getSuperClassNamespace(); 2207} 2208 2209//----------------------------------------------------------------------------- 2210 2211DefineConsoleMethod( SimObject, setClassNamespace, void, ( const char* name ),, 2212 "Assign a class namespace to this object.\n" 2213 "@param name The name of the 'class' namespace for this object." ) 2214{ 2215 object->setClassNamespace( name ); 2216} 2217 2218//----------------------------------------------------------------------------- 2219 2220DefineConsoleMethod( SimObject, setSuperClassNamespace, void, ( const char* name ),, 2221 "Assign a superclass namespace to this object.\n" 2222 "@param name The name of the 'superClass' namespace for this object." ) 2223{ 2224 object->setSuperClassNamespace( name ); 2225} 2226 2227//----------------------------------------------------------------------------- 2228 2229DefineEngineMethod( SimObject, isSelected, bool, (),, 2230 "Get whether the object has been marked as selected. (in editor)\n" 2231 "@return True if the object is currently selected." ) 2232{ 2233 return object->isSelected(); 2234} 2235 2236//----------------------------------------------------------------------------- 2237 2238DefineEngineMethod( SimObject, setIsSelected, void, ( bool state ), ( true ), 2239 "Set whether the object has been marked as selected. (in editor)\n" 2240 "@param state True if object is to be marked selected; false if not." ) 2241{ 2242 object->setSelected( state ); 2243} 2244 2245//----------------------------------------------------------------------------- 2246 2247DefineConsoleMethod( SimObject, isExpanded, bool, (),, 2248 "Get whether the object has been marked as expanded. (in editor)\n" 2249 "@return True if the object is marked expanded." ) 2250{ 2251 return object->isExpanded(); 2252} 2253 2254//----------------------------------------------------------------------------- 2255 2256DefineConsoleMethod( SimObject, setIsExpanded, void, ( bool state ), ( true ), 2257 "Set whether the object has been marked as expanded. (in editor)\n" 2258 "@param state True if the object is to be marked expanded; false if not." ) 2259{ 2260 object->setExpanded( state ); 2261} 2262 2263//----------------------------------------------------------------------------- 2264 2265DefineConsoleMethod( SimObject, getFilename, const char*, (),, 2266 "Returns the filename the object is attached to.\n" 2267 "@return The name of the file the object is associated with; usually the file the object was loaded from." ) 2268{ 2269 return object->getFilename(); 2270} 2271 2272//----------------------------------------------------------------------------- 2273 2274DefineConsoleMethod( SimObject, setFilename, void, ( const char* fileName ),, 2275 "Sets the object's file name and path\n" 2276 "@param fileName The name of the file to associate this object with." ) 2277{ 2278 return object->setFilename( fileName ); 2279} 2280 2281//----------------------------------------------------------------------------- 2282 2283DefineConsoleMethod( SimObject, getDeclarationLine, S32, (),, 2284 "Get the line number at which the object is defined in its file.\n\n" 2285 "@return The line number of the object's definition in script.\n" 2286 "@see getFilename()") 2287{ 2288 return object->getDeclarationLine(); 2289} 2290 2291//----------------------------------------------------------------------------- 2292 2293#ifdef TORQUE_DEBUG 2294 2295static const char* sEnumCallbackFunction; 2296static void sEnumCallback( EngineObject* object ) 2297{ 2298 SimObject* simObject = dynamic_cast< SimObject* >( object ); 2299 if( !simObject ) 2300 return; 2301 2302 Con::evaluatef( "%s( %i );", sEnumCallbackFunction, simObject->getId() ); 2303} 2304 2305DefineEngineFunction( debugEnumInstances, void, ( const char* className, const char* functionName ),, 2306 "Call the given function for each instance of the given class.\n" 2307 "@param className Name of the class for which to enumerate instances.\n" 2308 "@param functionName Name of function to call and pass each instance of the given class.\n" 2309 "@note This function is only available in debug builds and primarily meant as an aid in debugging." 2310 "@ingroup Console") 2311{ 2312 sEnumCallbackFunction = functionName; 2313 ConsoleObject::debugEnumInstances( className, sEnumCallback ); 2314} 2315 2316#endif 2317 2318//----------------------------------------------------------------------------- 2319 2320DefineConsoleMethod( SimObject, assignFieldsFrom, void, ( SimObject* fromObject ),, 2321 "Copy fields from another object onto this one. The objects must " 2322 "be of same type. Everything from the object will overwrite what's " 2323 "in this object; extra fields in this object will remain. This " 2324 "includes dynamic fields.\n" 2325 "@param fromObject The object from which to copy fields." ) 2326{ 2327 if( fromObject ) 2328 object->assignFieldsFrom( fromObject ); 2329} 2330 2331//----------------------------------------------------------------------------- 2332 2333DefineEngineMethod( SimObject, assignPersistentId, void, (),, 2334 "Assign a persistent ID to the object if it does not already have one." ) 2335{ 2336 object->getOrCreatePersistentId(); 2337} 2338 2339//----------------------------------------------------------------------------- 2340 2341DefineConsoleMethod( SimObject, getCanSave, bool, (),, 2342 "Get whether the object will be included in saves.\n" 2343 "@return True if the object will be saved; false otherwise." ) 2344{ 2345 return object->getCanSave(); 2346} 2347 2348//----------------------------------------------------------------------------- 2349 2350DefineConsoleMethod( SimObject, setCanSave, void, ( bool value ), ( true ), 2351 "Set whether the object will be included in saves.\n" 2352 "@param value If true, the object will be included in saves; if false, it will be excluded." ) 2353{ 2354 object->setCanSave( value ); 2355} 2356 2357//----------------------------------------------------------------------------- 2358 2359DefineEngineMethod( SimObject, isEditorOnly, bool, (),, 2360 "Return true if the object is only used by the editor.\n" 2361 "@return True if this object exists only for the sake of editing." ) 2362{ 2363 return object->isEditorOnly(); 2364} 2365 2366//----------------------------------------------------------------------------- 2367 2368DefineEngineMethod( SimObject, setEditorOnly, void, ( bool value ), ( true ), 2369 "Set/clear the editor-only flag on this object.\n" 2370 "@param value If true, the object is marked as existing only for the editor." ) 2371{ 2372 object->setEditorOnly( value ); 2373} 2374 2375//----------------------------------------------------------------------------- 2376 2377DefineEngineMethod( SimObject, isNameChangeAllowed, bool, (),, 2378 "Get whether this object may be renamed.\n" 2379 "@return True if this object can be renamed; false otherwise." ) 2380{ 2381 return object->isNameChangeAllowed(); 2382} 2383 2384//----------------------------------------------------------------------------- 2385 2386DefineEngineMethod( SimObject, setNameChangeAllowed, void, ( bool value ), ( true ), 2387 "Set whether this object can be renamed from its first name.\n" 2388 "@param value If true, renaming is allowed for this object; if false, trying to change the name of the object will generate a console error." ) 2389{ 2390 object->setNameChangeAllowed( value ); 2391} 2392 2393//----------------------------------------------------------------------------- 2394 2395DefineEngineMethod( SimObject, clone, SimObject*, (),, 2396 "Create a copy of this object.\n" 2397 "@return An exact duplicate of this object." ) 2398{ 2399 return object->clone(); 2400} 2401 2402//----------------------------------------------------------------------------- 2403 2404DefineEngineMethod( SimObject, deepClone, SimObject*, (),, 2405 "Create a copy of this object and all its subobjects.\n" 2406 "@return An exact duplicate of this object and all objects it references." ) 2407{ 2408 return object->deepClone(); 2409} 2410 2411//----------------------------------------------------------------------------- 2412 2413DefineEngineMethod( SimObject, setLocked, void, ( bool value ), ( true ), 2414 "Lock/unlock the object in the editor.\n" 2415 "@param value If true, the object will be locked; if false, the object will be unlocked." ) 2416{ 2417 object->setLocked( value ); 2418} 2419 2420//----------------------------------------------------------------------------- 2421 2422DefineEngineMethod( SimObject, setHidden, void, ( bool value ), ( true ), 2423 "Hide/unhide the object.\n" 2424 "@param value If true, the object will be hidden; if false, the object will be unhidden." ) 2425{ 2426 object->setHidden( value ); 2427} 2428 2429//----------------------------------------------------------------------------- 2430 2431DefineConsoleMethod( SimObject, dumpMethods, ArrayObject*, (),, 2432 "List the methods defined on this object.\n\n" 2433 "Each description is a newline-separated vector with the following elements:\n" 2434 "- Minimum number of arguments.\n" 2435 "- Maximum number of arguments.\n" 2436 "- Prototype string.\n" 2437 "- Full script file path (if script method).\n" 2438 "- Line number of method definition in script (if script method).\n\n" 2439 "- Documentation string (not including prototype). This takes up the remainder of the vector.\n" 2440 "@return An ArrayObject populated with (name,description) pairs of all methods defined on the object." ) 2441{ 2442 Namespace *ns = object->getNamespace(); 2443 if( !ns ) 2444 return 0; 2445 2446 ArrayObject* dictionary = new ArrayObject(); 2447 dictionary->registerObject(); 2448 2449 VectorPtr<Namespace::Entry*> vec(__FILE__, __LINE__); 2450 ns->getEntryList(&vec); 2451 2452 for(Vector< Namespace::Entry* >::iterator j = vec.begin(); j != vec.end(); j++) 2453 { 2454 Namespace::Entry* e = *j; 2455 2456 if( e->mType < 0 ) 2457 continue; 2458 2459 StringBuilder str; 2460 2461 str.append( String::ToString( e->mMinArgs ) ); 2462 str.append( '\n' ); 2463 str.append( String::ToString( e->mMaxArgs ) ); 2464 str.append( '\n' ); 2465 str.append( e->getPrototypeString() ); 2466 2467 str.append( '\n' ); 2468 if( e->mCode && e->mCode->fullPath ) 2469 str.append( e->mCode->fullPath ); 2470 str.append( '\n' ); 2471 if( e->mCode ) 2472 str.append( String::ToString( e->mFunctionLineNumber ) ); 2473 2474 str.append( '\n' ); 2475 String docs = e->getDocString(); 2476 if( !docs.isEmpty() ) 2477 str.append( docs ); 2478 2479 dictionary->push_back( e->mFunctionName, str.end() ); 2480 } 2481 2482 return dictionary; 2483} 2484 2485//----------------------------------------------------------------------------- 2486 2487namespace { 2488 S32 QSORT_CALLBACK compareFields( const void* a,const void* b ) 2489 { 2490 const AbstractClassRep::Field* fa = *((const AbstractClassRep::Field**)a); 2491 const AbstractClassRep::Field* fb = *((const AbstractClassRep::Field**)b); 2492 2493 return dStricmp(fa->pFieldname, fb->pFieldname); 2494 } 2495 2496 struct DocString 2497 { 2498 char mPadding[ 8 ]; 2499 String mPrototype; 2500 String mDescription; 2501 const char* mReturnType; 2502 2503 DocString( Namespace::Entry* entry ) 2504 : mPrototype( entry->getArgumentsString() ), 2505 mDescription( entry->getBriefDescription() ) 2506 { 2507 mReturnType = " "; 2508 mPadding[ 0 ] = 0; 2509 if( entry->mType == -4 ) 2510 { 2511 //TODO: need to have script callbacks set up proper return type info 2512 } 2513 else 2514 { 2515 switch( entry->mType ) 2516 { 2517 case Namespace::Entry::StringCallbackType: 2518 mReturnType = "string"; 2519 mPadding[ 0 ] = ' '; 2520 mPadding[ 1 ] = ' '; 2521 mPadding[ 2 ] = 0; 2522 break; 2523 2524 case Namespace::Entry::IntCallbackType: 2525 mReturnType = "int"; 2526 mPadding[ 0 ] = ' '; 2527 mPadding[ 1 ] = ' '; 2528 mPadding[ 2 ] = ' '; 2529 mPadding[ 3 ] = ' '; 2530 mPadding[ 4 ] = ' '; 2531 mPadding[ 5 ] = 0; 2532 break; 2533 2534 case Namespace::Entry::FloatCallbackType: 2535 mReturnType = "float"; 2536 mPadding[ 0 ] = ' '; 2537 mPadding[ 1 ] = ' '; 2538 mPadding[ 2 ] = ' '; 2539 mPadding[ 3 ] = 0; 2540 break; 2541 2542 case Namespace::Entry::VoidCallbackType: 2543 mReturnType = "void"; 2544 mPadding[ 0 ] = ' '; 2545 mPadding[ 1 ] = ' '; 2546 mPadding[ 2 ] = ' '; 2547 mPadding[ 3 ] = ' '; 2548 mPadding[ 4 ] = 0; 2549 break; 2550 2551 case Namespace::Entry::BoolCallbackType: 2552 mReturnType = "bool"; 2553 mPadding[ 0 ] = ' '; 2554 mPadding[ 1 ] = ' '; 2555 mPadding[ 2 ] = ' '; 2556 mPadding[ 3 ] = ' '; 2557 mPadding[ 4 ] = 0; 2558 break; 2559 } 2560 } 2561 } 2562 }; 2563} 2564 2565DefineEngineMethod( SimObject, dump, void, ( bool detailed ), ( false ), 2566 "Dump a description of all fields and methods defined on this object to the console.\n" 2567 "@param detailed Whether to print detailed information about members." ) 2568{ 2569 Con::printf( "Class: %s", object->getClassName() ); 2570 2571 const AbstractClassRep::FieldList &list = object->getFieldList(); 2572 char expandedBuffer[4096]; 2573 2574 Con::printf( "Static Fields:" ); 2575 Vector<const AbstractClassRep::Field*> flist(__FILE__, __LINE__); 2576 2577 for(U32 i = 0; i < list.size(); i++) 2578 flist.push_back(&list[i]); 2579 2580 dQsort(flist.address(),flist.size(),sizeof(AbstractClassRep::Field *),compareFields); 2581 2582 for(Vector<const AbstractClassRep::Field *>::iterator itr = flist.begin(); itr != flist.end(); itr++) 2583 { 2584 const AbstractClassRep::Field* f = *itr; 2585 2586 // The special field types can be skipped. 2587 if ( f->type >= AbstractClassRep::ARCFirstCustomField ) 2588 continue; 2589 2590 for(U32 j = 0; S32(j) < f->elementCount; j++) 2591 { 2592 // [neo, 07/05/2007 - #3000] 2593 // Some objects use dummy vars and projected fields so make sure we call the get functions 2594 //const char *val = Con::getData(f->type, (void *) (((const char *)object) + f->offset), j, f->table, f->flag); 2595 const char *val = (*f->getDataFn)( object, Con::getData(f->type, (void *) (((const char *)object) + f->offset), j, f->table, f->flag) );// + typeSizes[fld.type] * array1)); 2596 2597 ConsoleBaseType* conType = ConsoleBaseType::getType( f->type ); 2598 const char* conTypeName = "<unknown>"; 2599 if( conType ) 2600 conTypeName = conType->getTypeClassName(); 2601 2602 if( !val /*|| !*val*/ ) 2603 continue; 2604 if( f->elementCount == 1 ) 2605 dSprintf( expandedBuffer, sizeof( expandedBuffer ), " %s %s = \"", conTypeName, f->pFieldname ); 2606 else 2607 dSprintf( expandedBuffer, sizeof( expandedBuffer ), " %s %s[ %d ] = \"", conTypeName, f->pFieldname, j ); 2608 expandEscape( expandedBuffer + dStrlen(expandedBuffer), val); 2609 Con::printf( "%s\"", expandedBuffer ); 2610 2611 if( detailed && f->pFieldDocs && f->pFieldDocs[ 0 ] ) 2612 Con::printf( " %s", f->pFieldDocs ); 2613 } 2614 } 2615 2616 Con::printf( "Dynamic Fields:" ); 2617 if(object->getFieldDictionary()) 2618 object->getFieldDictionary()->printFields(object); 2619 2620 Con::printf( "Methods:" ); 2621 Namespace *ns = object->getNamespace(); 2622 VectorPtr<Namespace::Entry*> vec(__FILE__, __LINE__); 2623 2624 if(ns) 2625 ns->getEntryList(&vec); 2626 2627 bool sawCBs = false; 2628 2629 for(Vector<Namespace::Entry *>::iterator j = vec.begin(); j != vec.end(); j++) 2630 { 2631 Namespace::Entry *e = *j; 2632 2633 if(e->mType == Namespace::Entry::ScriptCallbackType) 2634 sawCBs = true; 2635 2636 if(e->mType < 0) 2637 continue; 2638 2639 DocString doc( e ); 2640 Con::printf( " %s%s%s%s", doc.mReturnType, doc.mPadding, e->mFunctionName, doc.mPrototype.c_str() ); 2641 2642 if( detailed && !doc.mDescription.isEmpty() ) 2643 Con::printf( " %s", doc.mDescription.c_str() ); 2644 } 2645 2646 if( sawCBs ) 2647 { 2648 Con::printf( "Callbacks:" ); 2649 2650 for(Vector<Namespace::Entry *>::iterator j = vec.begin(); j != vec.end(); j++) 2651 { 2652 Namespace::Entry *e = *j; 2653 2654 if(e->mType != Namespace::Entry::ScriptCallbackType) 2655 continue; 2656 2657 DocString doc( e ); 2658 Con::printf( " %s%s%s%s", doc.mReturnType, doc.mPadding, e->cb.mCallbackName, doc.mPrototype.c_str() ); 2659 2660 if( detailed && !doc.mDescription.isEmpty() ) 2661 Con::printf( " %s", doc.mDescription.c_str() ); 2662 } 2663 } 2664} 2665 2666//----------------------------------------------------------------------------- 2667 2668DefineConsoleMethod( SimObject, save, bool, ( const char* fileName, bool selectedOnly, const char* preAppendString ), ( false, "" ), 2669 "Save out the object to the given file.\n" 2670 "@param fileName The name of the file to save to." 2671 "@param selectedOnly If true, only objects marked as selected will be saved out.\n" 2672 "@param preAppendString Text which will be preprended directly to the object serialization.\n" 2673 "@param True on success, false on failure." ) 2674{ 2675 return object->save( fileName, selectedOnly, preAppendString ); 2676} 2677 2678//----------------------------------------------------------------------------- 2679 2680DefineEngineMethod( SimObject, setName, void, ( const char* newName ),, 2681 "Set the global name of the object.\n" 2682 "@param newName The new global name to assign to the object.\n" 2683 "@note If name changing is disallowed on the object, the method will fail with a console error." ) 2684{ 2685 object->assignName( newName ); 2686} 2687 2688//----------------------------------------------------------------------------- 2689 2690DefineEngineMethod( SimObject, getName, const char*, (),, 2691 "Get the global name of the object.\n" 2692 "@return The global name assigned to the object." ) 2693{ 2694 const char *ret = object->getName(); 2695 return ret ? ret : ""; 2696} 2697 2698//----------------------------------------------------------------------------- 2699 2700DefineConsoleMethod( SimObject, getClassName, const char*, (),, 2701 "Get the name of the C++ class which the object is an instance of.\n" 2702 "@return The name of the C++ class of the object." ) 2703{ 2704 const char *ret = object->getClassName(); 2705 return ret ? ret : ""; 2706} 2707 2708//----------------------------------------------------------------------------- 2709 2710DefineConsoleMethod( SimObject, isField, bool, ( const char* fieldName ),, 2711 "Test whether the given field is defined on this object.\n" 2712 "@param fieldName The name of the field.\n" 2713 "@return True if the object implements the given field." ) 2714{ 2715 return object->isField( fieldName ); 2716} 2717 2718//----------------------------------------------------------------------------- 2719 2720DefineConsoleMethod( SimObject, getFieldValue, const char*, ( const char* fieldName, S32 index ), ( -1 ), 2721 "Return the value of the given field on this object.\n" 2722 "@param fieldName The name of the field. If it includes a field index, the index is parsed out.\n" 2723 "@param index Optional parameter to specify the index of an array field separately.\n" 2724 "@return The value of the given field or \"\" if undefined." ) 2725{ 2726 char fieldNameBuffer[ 1024 ]; 2727 char arrayIndexBuffer[ 64 ]; 2728 2729 // Parse out index if the field is given in the form of 'name[index]'. 2730 2731 const char* arrayIndex = NULL; 2732 const U32 nameLen = dStrlen( fieldName ); 2733 if( fieldName[ nameLen - 1 ] == ']' ) 2734 { 2735 const char* leftBracket = dStrchr( fieldName, '[' ); 2736 const char* rightBracket = &fieldName[ nameLen - 1 ]; 2737 2738 const U32 fieldNameLen = getMin( U32( leftBracket - fieldName ), sizeof( fieldNameBuffer ) - 1 ); 2739 const U32 arrayIndexLen = getMin( U32( rightBracket - leftBracket - 1 ), sizeof( arrayIndexBuffer ) - 1 ); 2740 2741 dMemcpy( fieldNameBuffer, fieldName, fieldNameLen ); 2742 dMemcpy( arrayIndexBuffer, leftBracket + 1, arrayIndexLen ); 2743 2744 fieldNameBuffer[ fieldNameLen ] = '\0'; 2745 arrayIndexBuffer[ arrayIndexLen ] = '\0'; 2746 2747 fieldName = fieldNameBuffer; 2748 arrayIndex = arrayIndexBuffer; 2749 } 2750 2751 fieldName = StringTable->insert( fieldName ); 2752 2753 if( index != -1 ) 2754 { 2755 dSprintf( arrayIndexBuffer, sizeof( arrayIndexBuffer ), "%i", index ); 2756 arrayIndex = arrayIndexBuffer; 2757 } 2758 2759 return object->getDataField( fieldName, arrayIndex ); 2760} 2761 2762//----------------------------------------------------------------------------- 2763 2764DefineConsoleMethod( SimObject, setFieldValue, bool, ( const char* fieldName, const char* value, S32 index ), ( -1 ), 2765 "Set the value of the given field on this object.\n" 2766 "@param fieldName The name of the field to assign to. If it includes an array index, the index will be parsed out.\n" 2767 "@param value The new value to assign to the field.\n" 2768 "@param index Optional argument to specify an index for an array field.\n" 2769 "@return True." ) 2770{ 2771 char fieldNameBuffer[ 1024 ]; 2772 char arrayIndexBuffer[ 64 ]; 2773 2774 // Parse out index if the field is given in the form of 'name[index]'. 2775 2776 const char* arrayIndex = NULL; 2777 const U32 nameLen = dStrlen( fieldName ); 2778 if( fieldName[ nameLen - 1 ] == ']' ) 2779 { 2780 const char* leftBracket = dStrchr( fieldName, '[' ); 2781 const char* rightBracket = &fieldName[ nameLen - 1 ]; 2782 2783 const U32 fieldNameLen = getMin( U32( leftBracket - fieldName ), sizeof( fieldNameBuffer ) - 1 ); 2784 const U32 arrayIndexLen = getMin( U32( rightBracket - leftBracket - 1 ), sizeof( arrayIndexBuffer ) - 1 ); 2785 2786 dMemcpy( fieldNameBuffer, fieldName, fieldNameLen ); 2787 dMemcpy( arrayIndexBuffer, leftBracket + 1, arrayIndexLen ); 2788 2789 fieldNameBuffer[ fieldNameLen ] = '\0'; 2790 arrayIndexBuffer[ arrayIndexLen ] = '\0'; 2791 2792 fieldName = fieldNameBuffer; 2793 arrayIndex = arrayIndexBuffer; 2794 } 2795 2796 fieldName = StringTable->insert( fieldName ); 2797 2798 if( index != -1 ) 2799 { 2800 dSprintf( arrayIndexBuffer, sizeof( arrayIndexBuffer ), "%i", index ); 2801 arrayIndex = arrayIndexBuffer; 2802 } 2803 2804 object->setDataField( fieldName, arrayIndex, value ); 2805 2806 return true; 2807} 2808 2809//----------------------------------------------------------------------------- 2810 2811DefineConsoleMethod( SimObject, getFieldType, const char*, ( const char* fieldName ),, 2812 "Get the console type code of the given field.\n" 2813 "@return The numeric type code for the underlying console type of the given field." ) 2814{ 2815 U32 typeID = object->getDataFieldType( StringTable->insert( fieldName ), NULL ); 2816 ConsoleBaseType* type = ConsoleBaseType::getType( typeID ); 2817 2818 if( type ) 2819 return type->getTypeName(); 2820 2821 return ""; 2822} 2823 2824//----------------------------------------------------------------------------- 2825 2826DefineConsoleMethod( SimObject, setFieldType, void, ( const char* fieldName, const char* type ),, 2827 "Set the console type code for the given field.\n" 2828 "@param fieldName The name of the dynamic field to change to type for.\n" 2829 "@param type The name of the console type.\n" 2830 "@note This only works for dynamic fields. Types of static fields cannot be changed." ) 2831{ 2832 object->setDataFieldType( type, StringTable->insert( fieldName ), NULL ); 2833} 2834 2835//----------------------------------------------------------------------------- 2836 2837ConsoleMethod( SimObject, call, const char*, 3, 0, "( string method, string args... ) Dynamically call a method on an object.\n" 2838 "@param method Name of method to call.\n" 2839 "@param args Zero or more arguments for the method.\n" 2840 "@return The result of the method call." ) 2841{ 2842 argv[1] = argv[2]; 2843 return Con::execute( object, argc - 1, argv + 1 ); 2844} 2845 2846//----------------------------------------------------------------------------- 2847 2848DefineEngineMethod( SimObject, setInternalName, void, ( const char* newInternalName ),, 2849 "Set the internal name of the object.\n" 2850 "@param newInternalName The new internal name for the object." ) 2851{ 2852 object->setInternalName( newInternalName ); 2853} 2854 2855//----------------------------------------------------------------------------- 2856 2857DefineEngineMethod( SimObject, getInternalName, const char*, (),, 2858 "Get the internal name of the object.\n" 2859 "@return The internal name of the object." ) 2860{ 2861 return object->getInternalName(); 2862} 2863 2864//----------------------------------------------------------------------------- 2865 2866DefineConsoleMethod( SimObject, dumpClassHierarchy, void, (),, 2867 "Dump the native C++ class hierarchy of this object's C++ class to the console." ) 2868{ 2869 object->dumpClassHierarchy(); 2870} 2871 2872//----------------------------------------------------------------------------- 2873 2874DefineConsoleMethod( SimObject, isMemberOfClass, bool, ( const char* className ),, 2875 "Test whether this object is a member of the specified class.\n" 2876 "@param className Name of a native C++ class.\n" 2877 "@return True if this object is an instance of the given C++ class or any of its super classes." ) 2878{ 2879 AbstractClassRep* pRep = object->getClassRep(); 2880 while(pRep) 2881 { 2882 if( !dStricmp(pRep->getClassName(), className ) ) 2883 { 2884 //matches 2885 return true; 2886 } 2887 2888 pRep = pRep->getParentClass(); 2889 } 2890 2891 return false; 2892} 2893 2894//----------------------------------------------------------------------------- 2895 2896DefineConsoleMethod( SimObject, isInNamespaceHierarchy, bool, ( const char* name ),, 2897 "Test whether the namespace of this object is a direct or indirect child to the given namespace.\n" 2898 "@param name The name of a namespace.\n" 2899 "@return True if the given namespace name is within the namespace hierarchy of this object." ) 2900{ 2901 Namespace* nspace = object->getNamespace(); 2902 2903 while( nspace && dStricmp( nspace->mName, name ) != 0 ) 2904 nspace = nspace->mParent; 2905 2906 return ( nspace != NULL ); 2907} 2908 2909//----------------------------------------------------------------------------- 2910 2911DefineEngineMethod( SimObject, getId, S32, (),, 2912 "Get the underlying unique numeric ID of the object.\n" 2913 "@note Object IDs are unique only during single engine runs.\n" 2914 "@return The unique numeric ID of the object." ) 2915{ 2916 return object->getId(); 2917} 2918 2919//----------------------------------------------------------------------------- 2920 2921DefineEngineMethod( SimObject, getGroup, SimGroup*, (),, 2922 "Get the group that this object is contained in.\n" 2923 "@note If not assigned to particular SimGroup, an object belongs to RootGroup.\n" 2924 "@return The SimGroup object to which the object belongs." ) 2925{ 2926 return object->getGroup(); 2927} 2928 2929//----------------------------------------------------------------------------- 2930 2931DefineConsoleMethod( SimObject, delete, void, (),, 2932 "Delete and remove the object." ) 2933{ 2934 object->deleteObject(); 2935} 2936 2937//----------------------------------------------------------------------------- 2938 2939ConsoleMethod( SimObject,schedule, S32, 4, 0, "( float time, string method, string args... ) Delay an invocation of a method.\n" 2940 "@param time The number of milliseconds after which to invoke the method. This is a soft limit.\n" 2941 "@param method The method to call.\n" 2942 "@param args The arguments with which to call the method.\n" 2943 "@return The numeric ID of the created schedule. Can be used to cancel the call.\n" ) 2944{ 2945 U32 timeDelta = U32(dAtof(argv[2])); 2946 argv[2] = argv[3]; 2947 argv[3] = argv[1]; 2948 SimConsoleEvent *evt = new SimConsoleEvent(argc - 2, argv + 2, true); 2949 S32 ret = Sim::postEvent(object, evt, Sim::getCurrentTime() + timeDelta); 2950 // #ifdef DEBUG 2951 // Con::printf("obj %s schedule(%s) = %d", argv[3], argv[2], ret); 2952 // Con::executef( "backtrace"); 2953 // #endif 2954 return ret; 2955} 2956 2957//----------------------------------------------------------------------------- 2958 2959DefineConsoleMethod( SimObject, getDynamicFieldCount, S32, (),, 2960 "Get the number of dynamic fields defined on the object.\n" 2961 "@return The number of dynamic fields defined on the object." ) 2962{ 2963 S32 count = 0; 2964 SimFieldDictionary* fieldDictionary = object->getFieldDictionary(); 2965 for (SimFieldDictionaryIterator itr(fieldDictionary); *itr; ++itr) 2966 count++; 2967 2968 return count; 2969} 2970 2971//----------------------------------------------------------------------------- 2972 2973DefineConsoleMethod( SimObject, getDynamicField, const char*, ( S32 index ),, 2974 "Get a value of a dynamic field by index.\n" 2975 "@param index The index of the dynamic field.\n" 2976 "@return The value of the dynamic field at the given index or \"\"." ) 2977{ 2978 SimFieldDictionary* fieldDictionary = object->getFieldDictionary(); 2979 SimFieldDictionaryIterator itr(fieldDictionary); 2980 for (S32 i = 0; i < index; i++) 2981 { 2982 if (!(*itr)) 2983 { 2984 Con::warnf("Invalid dynamic field index passed to SimObject::getDynamicField!"); 2985 return NULL; 2986 } 2987 ++itr; 2988 } 2989 2990 static const U32 bufSize = 256; 2991 char* buffer = Con::getReturnBuffer(bufSize); 2992 if (*itr) 2993 { 2994 SimFieldDictionary::Entry* entry = *itr; 2995 dSprintf(buffer, bufSize, "%s\t%s", entry->slotName, entry->value); 2996 return buffer; 2997 } 2998 2999 Con::warnf("Invalid dynamic field index passed to SimObject::getDynamicField!"); 3000 return NULL; 3001} 3002 3003//----------------------------------------------------------------------------- 3004 3005DefineConsoleMethod( SimObject, getFieldCount, S32, (),, 3006 "Get the number of static fields on the object.\n" 3007 "@return The number of static fields defined on the object." ) 3008{ 3009 const AbstractClassRep::FieldList &list = object->getFieldList(); 3010 const AbstractClassRep::Field* f; 3011 U32 numDummyEntries = 0; 3012 3013 for(S32 i = 0; i < list.size(); i++) 3014 { 3015 f = &list[i]; 3016 3017 // The special field types do not need to be counted. 3018 if ( f->type >= AbstractClassRep::ARCFirstCustomField ) 3019 numDummyEntries++; 3020 } 3021 3022 return list.size() - numDummyEntries; 3023} 3024 3025//----------------------------------------------------------------------------- 3026 3027DefineConsoleMethod( SimObject, getField, const char*, ( S32 index ),, 3028 "Retrieve the value of a static field by index.\n" 3029 "@param index The index of the static field.\n" 3030 "@return The value of the static field with the given index or \"\"." ) 3031{ 3032 const AbstractClassRep::FieldList &list = object->getFieldList(); 3033 if( ( index < 0 ) || ( index >= list.size() ) ) 3034 return ""; 3035 3036 const AbstractClassRep::Field* f; 3037 S32 currentField = 0; 3038 for ( U32 i = 0; i < list.size() && currentField <= index; i++ ) 3039 { 3040 f = &list[i]; 3041 3042 // The special field types can be skipped. 3043 if ( f->type >= AbstractClassRep::ARCFirstCustomField ) 3044 continue; 3045 3046 if(currentField == index) 3047 return f->pFieldname; 3048 3049 currentField++; 3050 } 3051 3052 // if we found nada, return nada. 3053 return ""; 3054} 3055 3056//----------------------------------------------------------------------------- 3057 3058#ifdef TORQUE_DEBUG 3059 3060DefineEngineMethod( SimObject, getDebugInfo, ArrayObject*, (),, 3061 "Return some behind-the-scenes information on the object.\n" 3062 "@return An ArrayObject filled with internal information about the object." ) 3063{ 3064 ArrayObject* array = new ArrayObject(); 3065 array->registerObject(); 3066 3067 array->push_back( "C++|Address", String::ToString( "0x%x", object ) ); 3068 array->push_back( "C++|Size", String::ToString( object->getClassRep()->getSizeof() ) ); 3069 array->push_back( "Object|Description", object->describeSelf() ); 3070 array->push_back( "Object|FileName", object->getFilename() ); 3071 array->push_back( "Object|DeclarationLine", String::ToString( object->getDeclarationLine() ) ); 3072 array->push_back( "Object|CopySource", object->getCopySource() ? 3073 String::ToString( "%i:%s (%s)", object->getCopySource()->getId(), object->getCopySource()->getClassName(), object->getCopySource()->getName() ) : "" ); 3074 array->push_back( "Flag|EditorOnly", object->isEditorOnly() ? "true" : "false" ); 3075 array->push_back( "Flag|NameChangeAllowed", object->isNameChangeAllowed() ? "true" : "false" ); 3076 array->push_back( "Flag|AutoDelete", object->isAutoDeleted() ? "true" : "false" ); 3077 array->push_back( "Flag|Selected", object->isSelected() ? "true" : "false" ); 3078 array->push_back( "Flag|Expanded", object->isExpanded() ? "true" : "false" ); 3079 array->push_back( "Flag|ModStaticFields", object->canModStaticFields() ? "true" : "false" ); 3080 array->push_back( "Flag|ModDynamicFields", object->canModDynamicFields() ? "true" : "false" ); 3081 array->push_back( "Flag|CanSave", object->getCanSave() ? "true" : "false" ); 3082 3083 #ifndef TORQUE_DISABLE_MEMORY_MANAGER 3084 Memory::Info memInfo; 3085 Memory::getMemoryInfo( object, memInfo ); 3086 3087 array->push_back( "Memory|AllocNumber", String::ToString( memInfo.mAllocNumber ) ); 3088 array->push_back( "Memory|AllocSize", String::ToString( memInfo.mAllocSize ) ); 3089 array->push_back( "Memory|AllocFile", memInfo.mFileName ); 3090 array->push_back( "Memory|AllocLine", String::ToString( memInfo.mLineNumber ) ); 3091 array->push_back( "Memory|IsGlobal", memInfo.mIsGlobal ? "true" : "false" ); 3092 array->push_back( "Memory|IsStatic", memInfo.mIsStatic ? "true" : "false" ); 3093 #endif 3094 3095 return array; 3096} 3097 3098#endif 3099
