simObject.cpp

Engine/source/console/simObject.cpp

More...

Classes:

Namespaces:

namespace

Public Variables

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>" )
DefineEngineMethod(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." )
DefineEngineMethod(SimObject , assignPersistentId , void , () , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> persistent ID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it does not already have one." )
DefineEngineMethod(SimObject , clone , SimObject * , () , "Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 , delete , void , () , "Delete and remove the object." )
DefineEngineMethod(SimObject , dump , void , (bool detailed) , (false) , "Dump <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 , 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." )
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 , 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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">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." )
DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object will be saved; false otherwise." )
DefineEngineMethod(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." )
DefineEngineMethod(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." )
DefineEngineMethod(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()" )
DefineEngineMethod(SimObject , getDynamicField , const char * , (S32 index) , "Get <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the dynamic field at the given index or \"\"." )
DefineEngineMethod(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." )
DefineEngineMethod(SimObject , getField , const char * , (S32 index) , "Retrieve the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the static field with the given index or \"\"." )
DefineEngineMethod(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." )
DefineEngineMethod(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." )
DefineEngineMethod(SimObject , getFieldValue , const char * , (const char *fieldName, S32 index) , (-1) , "Return the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the given field or \"\" <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> undefined." )
DefineEngineMethod(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." )
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 , 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." )
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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child of the given group or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> group that the given group is directly or indirectly <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child to." )
DefineEngineMethod(SimObject , isEditorOnly , bool , () , "Return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object exists only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the sake of editing." )
DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is marked expanded." )
DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object implements the given field." )
DefineEngineMethod(SimObject , isInNamespaceHierarchy , bool , (const char *name) , "Test whether the namespace of this object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given namespace name is within the namespace hierarchy of this object." )
DefineEngineMethod(SimObject , isMemberOfClass , bool , (const char *className) , "Test whether this object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member of the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@param className Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object is an instance of the given C++ class or any of its super classes." )
DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object implements the given method." )
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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is currently selected." )
DefineEngineMethod(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." )
DefineEngineMethod(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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be included in saves;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> false, it will be excluded." )
DefineEngineMethod(SimObject , setClassNamespace , void , (const char *name) , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )
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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object is marked as existing only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the editor." )
DefineEngineMethod(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." )
DefineEngineMethod(SimObject , setFieldValue , bool , (const char *fieldName, const char *value, S32 index) , (-1) , "Set the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <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." )
DefineEngineMethod(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." )
DefineEngineMethod(SimObject , setHidden , void , (bool value) , (true) , "Hide/unhide the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be hidden;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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 , 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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )
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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be locked;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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_1a4e4fa7e3399708e0777b5308db01278c">if</a> false, trying <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change the name of the object will generate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> console error." )
DefineEngineMethod(SimObject , setSuperClassNamespace , void , (const char *name) , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )
DefineEngineStringlyVariadicMethod(SimObject , call , const char * , 3 , 0 , "( string method, string args... ) Dynamically call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )
DefineEngineStringlyVariadicMethod(SimObject , schedule , S32 , 4 , 0 , "( float time, string method, string args... ) Delay an invocation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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>" )
IMPLEMENT_CALLBACK(SimObject , onInspectPostApply , void , (SimObject *obj) , (obj) , "Generic callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> when an object is edited" )

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>" )

DefineEngineMethod(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." )

DefineEngineMethod(SimObject , assignPersistentId , void , () , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> persistent ID <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it does not already have one." )

DefineEngineMethod(SimObject , clone , SimObject * , () , "Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 , delete , void , () , "Delete and remove the object." )

DefineEngineMethod(SimObject , dump , void , (bool detailed) , (false) , "Dump <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 , 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." )

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 , 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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">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." )

DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object will be saved; false otherwise." )

DefineEngineMethod(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." )

DefineEngineMethod(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." )

DefineEngineMethod(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()" )

DefineEngineMethod(SimObject , getDynamicField , const char * , (S32 index) , "Get <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the dynamic field at the given index or \"\"." )

DefineEngineMethod(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." )

DefineEngineMethod(SimObject , getField , const char * , (S32 index) , "Retrieve the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the static field with the given index or \"\"." )

DefineEngineMethod(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." )

DefineEngineMethod(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." )

DefineEngineMethod(SimObject , getFieldValue , const char * , (const char *fieldName, S32 index) , (-1) , "Return the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the given field or \"\" <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> undefined." )

DefineEngineMethod(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." )

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 , 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." )

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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child of the given group or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> group that the given group is directly or indirectly <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> child to." )

DefineEngineMethod(SimObject , isEditorOnly , bool , () , "Return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object exists only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the sake of editing." )

DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is marked expanded." )

DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object implements the given field." )

DefineEngineMethod(SimObject , isInNamespaceHierarchy , bool , (const char *name) , "Test whether the namespace of this object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the given namespace name is within the namespace hierarchy of this object." )

DefineEngineMethod(SimObject , isMemberOfClass , bool , (const char *className) , "Test whether this object is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member of the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">class.\n</a>" "@param className Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object is an instance of the given C++ class or any of its super classes." )

DefineEngineMethod(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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object implements the given method." )

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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is currently selected." )

DefineEngineMethod(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." )

DefineEngineMethod(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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be included in saves;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> false, it will be excluded." )

DefineEngineMethod(SimObject , setClassNamespace , void , (const char *name) , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )

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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object is marked as existing only <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the editor." )

DefineEngineMethod(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." )

DefineEngineMethod(SimObject , setFieldValue , bool , (const char *fieldName, const char *value, S32 index) , (-1) , "Set the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <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." )

DefineEngineMethod(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." )

DefineEngineMethod(SimObject , setHidden , void , (bool value) , (true) , "Hide/unhide the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be hidden;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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 , 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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">if</a> not." )

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_1a4e4fa7e3399708e0777b5308db01278c">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_1a4e4fa7e3399708e0777b5308db01278c">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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> If true, the object will be locked;<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> 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_1a4e4fa7e3399708e0777b5308db01278c">if</a> false, trying <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change the name of the object will generate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> console error." )

DefineEngineMethod(SimObject , setSuperClassNamespace , void , (const char *name) , "Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )

DefineEngineStringlyVariadicMethod(SimObject , call , const char * , 3 , 0 , "( string method, string args... ) Dynamically call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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." )

DefineEngineStringlyVariadicMethod(SimObject , schedule , S32 , 4 , 0 , "( float time, string method, string args... ) Delay an invocation of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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>" )

IMPLEMENT_CALLBACK(SimObject , onInspectPostApply , void , (SimObject *obj) , (obj) , "Generic callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> when an object is edited" )

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