simObject.cpp
Engine/source/console/simObject.cpp
Classes:
class
Namespaces:
namespace
Public Variables
notifyChunker (128000)
Public Functions
ConsoleDocClass(SimObject , "@brief Base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> almost all objects involved in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">simulation.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" )
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