simSet.cpp

Engine/source/console/simSet.cpp

More...

Public Functions

ConsoleDocClass(SimGroup , "@brief A collection of SimObjects that are owned by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n\n</a>" "A <a href="/coding/class/classsimgroup/">SimGroup</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> stricter form of SimSet. SimObjects may only be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member " "of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single <a href="/coding/class/classsimgroup/">SimGroup</a> at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> time. The <a href="/coding/class/classsimgroup/">SimGroup</a> will automatically enforce " "the single-group-membership rule (ie. adding an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> will " "cause it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be removed from its current <a href="/coding/class/classsimgroup/">SimGroup</a>, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> any).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "Deleting <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> will also delete all SimObjects in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimGroup.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> particle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">emitters\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classsimgroup/">SimGroup</a>(Emitters)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "   <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classparticleemitternode/">ParticleEmitterNode</a>(CrystalEmmiter) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      active = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      emitter = \"dustEmitter\";\n" "      velocity = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      dataBlock = \"GenericSmokeEmitterNode\";\n" "      position = \"-61.6276 2.1142 4.45027\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      scale = \"1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   };\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "   <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classparticleemitternode/">ParticleEmitterNode</a>(Steam1) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      active = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      emitter = \"SlowSteamEmitter\";\n" "      velocity = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      dataBlock = \"GenericSmokeEmitterNode\";\n" "      position = \"-25.0458 1.55289 2.51308\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      scale = \"1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   };\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" "@ingroup Scripting" )
ConsoleDocClass(SimSet , "@brief A collection of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObjects.\n\n</a>" "It is often necessary <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep track of an arbitrary set of SimObjects. " "For instance, Torque 's networking code needs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> not only keep track of " "the set of objects which need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be ghosted, but also the set of objects " "which must< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >always</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > be ghosted. It does this by working with two " "sets. The first of these is the RootGroup(which is actually <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a>) " "and the second is the GhostAlwaysSet, which contains objects which must " "always be ghosted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "Some general notes on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets:\n\n</a>" "- Membership is not exclusive. A <a href="/coding/class/classsimobject/">SimObject</a> may be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member of multiple " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets.\n\n</a>" "- A <a href="/coding/class/classsimset/">SimSet</a> does not destroy subobjects when it is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">destroyed.\n\n</a>" "- A <a href="/coding/class/classsimset/">SimSet</a> may hold an arbitrary number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" " @ingroup Scripting" )
DEFINE_CALLIN(fnSimSet_getCountRecursive , getCountRecursive , SimSet , U32 , (SimSet *set) , "Get the number of direct and indirect child objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )
DefineEngineMethod(SimSet , acceptsAsChild , bool , (SimObject *obj) , "Test whether the given object may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> test <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> potential <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">membership.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the set, false otherwise." )
DefineEngineMethod(SimSet , bringToFront , void , (SimObject *obj) , "Make the given object the first object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bring <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the frontmost position. Must be contained in the set." )
DefineEngineMethod(SimSet , clear , void , () , "Remove all objects from the set." )
DefineEngineMethod(SimSet , deleteAllObjects , void , () , "() Delete all objects in the set." )
DefineEngineMethod(SimSet , findObjectByInternalName , SimObject * , (const char *internalName, bool searchChildren) , (false) , "Find an object in the set by its internal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param internalName The internal name of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param searchChildren If true, SimSets contained in the set will be recursively searched <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @return The object with the given internal name or 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no match was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">found.\n</a>" )
DefineEngineMethod(SimSet , getCount , S32 , () , "Get the number of objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set." )
DefineEngineMethod(SimSet , getFullCount , S32 , () , "() Get the number of direct and indirect child objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )
DefineEngineMethod(SimSet , getObject , SimObject * , (U32 index) , "Get the object at the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@return The object at the given index or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> index is out of range." )
DefineEngineMethod(SimSet , getObjectIndex , S32 , (SimObject *obj) , "Return the index of the given object in this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> return the index. Must be contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The index of the object or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is not contained in the set." )
DefineEngineMethod(SimSet , getRandom , SimObject * , () , "Return <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> random object from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return A randomly selected object from the set or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the set is empty." )
DefineEngineMethod(SimSet , isMember , bool , (SimObject *obj) , "Test whether the given object belongs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The <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 contained in the set; false otherwise." )
DefineEngineMethod(SimSet , listObjects , void , () , "Dump <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> list of all objects contained in the set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )
DefineEngineMethod(SimSet , pushToBack , void , (SimObject *obj) , "Make the given object the last object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bring <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the last position. Must be contained in the set." )
DefineEngineMethod(SimSet , reorderChild , void , (SimObject *child1, SimObject *child2) , "Make sure child1 is ordered right before child2 in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param child1 The first child. The object must already be contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param child2 The second child. The object must already be contained in the set." )
DefineEngineMethod(SimSet , sort , void , (const char *callbackFunction) , "( string callbackFunction ) Sort the objects in the set using the given comparison <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">function.\n</a>" "@param callbackFunction Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> function that takes two object arguments A and B and returns -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> A is less, 1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> B is less, and 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> both are equal." )
DefineEngineStringlyVariadicMethod(SimSet , add , void , 3 , 0 , "( SimObject objects... ) Add the given objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param objects The objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the set." )
DefineEngineStringlyVariadicMethod(SimSet , callOnChildren , void , 3 , 0 , "( string method, string args... ) Call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> method on all objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@param method The name of 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 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n\n</a>" "@note This method recurses into all SimSets that are children <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@see callOnChildrenNoRecurse" )
DefineEngineStringlyVariadicMethod(SimSet , callOnChildrenNoRecurse , void , 3 , 0 , "( string method, string args... ) Call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> method on all objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@param method The name of 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 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n\n</a>" "@note This method does not recurse into child <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets.\n\n</a>" "@see callOnChildren" )
DefineEngineStringlyVariadicMethod(SimSet , remove , void , 3 , 0 , "( SimObject objects... ) Remove the given objects from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param objects The objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove from the set." )
IMPLEMENT_CALLBACK(SimSet , onObjectAdded , void , (SimObject *object) , (object) , "Called when an object is added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param object The object that was added." )
IMPLEMENT_CALLBACK(SimSet , onObjectRemoved , void , (SimObject *object) , (object) , "Called when an object is removed from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param object The object that was removed." )

Detailed Description

Public Functions

ConsoleDocClass(SimGroup , "@brief A collection of SimObjects that are owned by the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group.\n\n</a>" "A <a href="/coding/class/classsimgroup/">SimGroup</a> is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> stricter form of SimSet. SimObjects may only be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member " "of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single <a href="/coding/class/classsimgroup/">SimGroup</a> at <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> time. The <a href="/coding/class/classsimgroup/">SimGroup</a> will automatically enforce " "the single-group-membership rule (ie. adding an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> will " "cause it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be removed from its current <a href="/coding/class/classsimgroup/">SimGroup</a>, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> any).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "Deleting <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> will also delete all SimObjects in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimGroup.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> particle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">emitters\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classsimgroup/">SimGroup</a>(Emitters)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "   <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classparticleemitternode/">ParticleEmitterNode</a>(CrystalEmmiter) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      active = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      emitter = \"dustEmitter\";\n" "      velocity = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      dataBlock = \"GenericSmokeEmitterNode\";\n" "      position = \"-61.6276 2.1142 4.45027\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      scale = \"1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   };\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "   <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classparticleemitternode/">ParticleEmitterNode</a>(Steam1) {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      active = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      emitter = \"SlowSteamEmitter\";\n" "      velocity = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      dataBlock = \"GenericSmokeEmitterNode\";\n" "      position = \"-25.0458 1.55289 2.51308\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      scale = \"1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "      canSaveDynamicFields = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   };\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" "@ingroup Scripting" )

ConsoleDocClass(SimSet , "@brief A collection of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObjects.\n\n</a>" "It is often necessary <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep track of an arbitrary set of SimObjects. " "For instance, Torque 's networking code needs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> not only keep track of " "the set of objects which need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be ghosted, but also the set of objects " "which must< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >always</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > be ghosted. It does this by working with two " "sets. The first of these is the RootGroup(which is actually <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsimgroup/">SimGroup</a>) " "and the second is the GhostAlwaysSet, which contains objects which must " "always be ghosted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n\n</a>" "Some general notes on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets:\n\n</a>" "- Membership is not exclusive. A <a href="/coding/class/classsimobject/">SimObject</a> may be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> member of multiple " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets.\n\n</a>" "- A <a href="/coding/class/classsimset/">SimSet</a> does not destroy subobjects when it is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">destroyed.\n\n</a>" "- A <a href="/coding/class/classsimset/">SimSet</a> may hold an arbitrary number of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">objects.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Console\n</a>" " @ingroup Scripting" )

DEFINE_CALLIN(fnSimSet_getCountRecursive , getCountRecursive , SimSet , U32 , (SimSet *set) , "Get the number of direct and indirect child objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )

DefineEngineMethod(SimSet , acceptsAsChild , bool , (SimObject *obj) , "Test whether the given object may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> test <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> potential <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">membership.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the set, false otherwise." )

DefineEngineMethod(SimSet , bringToFront , void , (SimObject *obj) , "Make the given object the first object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bring <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the frontmost position. Must be contained in the set." )

DefineEngineMethod(SimSet , clear , void , () , "Remove all objects from the set." )

DefineEngineMethod(SimSet , deleteAllObjects , void , () , "() Delete all objects in the set." )

DefineEngineMethod(SimSet , findObjectByInternalName , SimObject * , (const char *internalName, bool searchChildren) , (false) , "Find an object in the set by its internal <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name.\n</a>" "@param internalName The internal name of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> look <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">for.\n</a>" "@param searchChildren If true, SimSets contained in the set will be recursively searched <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @return The object with the given internal name or 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no match was <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">found.\n</a>" )

DefineEngineMethod(SimSet , getCount , S32 , () , "Get the number of objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set." )

DefineEngineMethod(SimSet , getFullCount , S32 , () , "() Get the number of direct and indirect child objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )

DefineEngineMethod(SimSet , getObject , SimObject * , (U32 index) , "Get the object at the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param index The object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@return The object at the given index or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> index is out of range." )

DefineEngineMethod(SimSet , getObjectIndex , S32 , (SimObject *obj) , "Return the index of the given object in this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> which <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> return the index. Must be contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return The index of the object or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is not contained in the set." )

DefineEngineMethod(SimSet , getRandom , SimObject * , () , "Return <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> random object from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@return A randomly selected object from the set or -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the set is empty." )

DefineEngineMethod(SimSet , isMember , bool , (SimObject *obj) , "Test whether the given object belongs <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The <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 contained in the set; false otherwise." )

DefineEngineMethod(SimSet , listObjects , void , () , "Dump <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> list of all objects contained in the set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console." )

DefineEngineMethod(SimSet , pushToBack , void , (SimObject *obj) , "Make the given object the last object in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param obj The object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bring <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the last position. Must be contained in the set." )

DefineEngineMethod(SimSet , reorderChild , void , (SimObject *child1, SimObject *child2) , "Make sure child1 is ordered right before child2 in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param child1 The first child. The object must already be contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param child2 The second child. The object must already be contained in the set." )

DefineEngineMethod(SimSet , sort , void , (const char *callbackFunction) , "( string callbackFunction ) Sort the objects in the set using the given comparison <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">function.\n</a>" "@param callbackFunction Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> function that takes two object arguments A and B and returns -1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> A is less, 1 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> B is less, and 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> both are equal." )

DefineEngineStringlyVariadicMethod(SimSet , add , void , 3 , 0 , "( SimObject objects... ) Add the given objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param objects The objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the set." )

DefineEngineStringlyVariadicMethod(SimSet , callOnChildren , void , 3 , 0 , "( string method, string args... ) Call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> method on all objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@param method The name of 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 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n\n</a>" "@note This method recurses into all SimSets that are children <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@see callOnChildrenNoRecurse" )

DefineEngineStringlyVariadicMethod(SimSet , callOnChildrenNoRecurse , void , 3 , 0 , "( string method, string args... ) Call <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> method on all objects contained in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n\n</a>" "@param method The name of 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 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">method.\n\n</a>" "@note This method does not recurse into child <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimSets.\n\n</a>" "@see callOnChildren" )

DefineEngineStringlyVariadicMethod(SimSet , remove , void , 3 , 0 , "( SimObject objects... ) Remove the given objects from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param objects The objects <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove from the set." )

IMPLEMENT_CALLBACK(SimSet , onObjectAdded , void , (SimObject *object) , (object) , "Called when an object is added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param object The object that was added." )

IMPLEMENT_CALLBACK(SimSet , onObjectRemoved , void , (SimObject *object) , (object) , "Called when an object is removed from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" "@param object The object that was removed." )

IMPLEMENT_CONOBJECT(SimGroup )

IMPLEMENT_CONOBJECT_CHILDREN(SimSet )

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platform.h"
  25#include "console/simSet.h"
  26
  27#include "core/stringTable.h"
  28#include "console/console.h"
  29#include "console/engineAPI.h"
  30#include "core/stream/fileStream.h"
  31#include "sim/actionMap.h"
  32#include "core/fileObject.h"
  33#include "console/consoleInternal.h"
  34#include "console/engineAPI.h"
  35#include "platform/profiler.h"
  36#include "console/typeValidators.h"
  37#include "core/frameAllocator.h"
  38#include "math/mMathFn.h"
  39
  40
  41IMPLEMENT_CONOBJECT_CHILDREN( SimSet );
  42IMPLEMENT_CONOBJECT( SimGroup );
  43
  44ConsoleDocClass( SimSet,
  45   "@brief A collection of SimObjects.\n\n"
  46
  47   "It is often necessary to keep track of an arbitrary set of SimObjects. "
  48   "For instance, Torque's networking code needs to not only keep track of "
  49   "the set of objects which need to be ghosted, but also the set of objects "
  50   "which must <i>always</i> be ghosted. It does this by working with two "
  51   "sets. The first of these is the RootGroup (which is actually a SimGroup) "
  52   "and the second is the GhostAlwaysSet, which contains objects which must "
  53   "always be ghosted to the client.\n\n"
  54
  55   "Some general notes on SimSets:\n\n"
  56   "- Membership is not exclusive. A SimObject may be a member of multiple "
  57   "SimSets.\n\n"
  58   "- A SimSet does not destroy subobjects when it is destroyed.\n\n"
  59   "- A SimSet may hold an arbitrary number of objects.\n\n"
  60
  61   "@ingroup Console\n"
  62   "@ingroup Scripting"
  63);
  64ConsoleDocClass( SimGroup,
  65   "@brief A collection of SimObjects that are owned by the group.\n\n"
  66   
  67   "A SimGroup is a stricter form of SimSet. SimObjects may only be a member "
  68   "of a single SimGroup at a time. The SimGroup will automatically enforce "
  69   "the single-group-membership rule (ie. adding an object to a SimGroup will "
  70   "cause it to be removed from its current SimGroup, if any).\n\n"
  71
  72   "Deleting a SimGroup will also delete all SimObjects in the SimGroup.\n\n"
  73
  74   "@tsexample\n"
  75   "// Create a SimGroup for particle emitters\n"
  76   "new SimGroup(Emitters)\n"
  77   "{\n"
  78   "   canSaveDynamicFields = \"1\";\n\n"
  79   "   new ParticleEmitterNode(CrystalEmmiter) {\n"
  80   "      active = \"1\";\n"
  81   "      emitter = \"dustEmitter\";\n"
  82   "      velocity = \"1\";\n"
  83   "      dataBlock = \"GenericSmokeEmitterNode\";\n"
  84   "      position = \"-61.6276 2.1142 4.45027\";\n"
  85   "      rotation = \"1 0 0 0\";\n"
  86   "      scale = \"1 1 1\";\n"
  87   "      canSaveDynamicFields = \"1\";\n"
  88   "   };\n\n"
  89   "   new ParticleEmitterNode(Steam1) {\n"
  90   "      active = \"1\";\n"
  91   "      emitter = \"SlowSteamEmitter\";\n"
  92   "      velocity = \"1\";\n"
  93   "      dataBlock = \"GenericSmokeEmitterNode\";\n"
  94   "      position = \"-25.0458 1.55289 2.51308\";\n"
  95   "      rotation = \"1 0 0 0\";\n"
  96   "      scale = \"1 1 1\";\n"
  97   "      canSaveDynamicFields = \"1\";\n"
  98   "   };\n"
  99   "};\n\n"
 100   "@endtsexample\n\n"
 101   "@ingroup Console\n"
 102   "@ingroup Scripting"
 103);
 104
 105IMPLEMENT_CALLBACK( SimSet, onObjectAdded, void, ( SimObject* object ), ( object ),
 106   "Called when an object is added to the set.\n"
 107   "@param object The object that was added." );
 108IMPLEMENT_CALLBACK( SimSet, onObjectRemoved, void, ( SimObject* object ), ( object ),
 109   "Called when an object is removed from the set.\n"
 110   "@param object The object that was removed." );
 111   
 112
 113//=============================================================================
 114//    SimSet.
 115//=============================================================================
 116// MARK: ---- SimSet ----
 117
 118//-----------------------------------------------------------------------------
 119
 120SimSet::SimSet()
 121{
 122   VECTOR_SET_ASSOCIATION(mObjectList);
 123   mMutex = Mutex::createMutex();
 124}
 125
 126//-----------------------------------------------------------------------------
 127
 128SimSet::~SimSet()
 129{
 130   Mutex::destroyMutex( mMutex );
 131}
 132
 133//-----------------------------------------------------------------------------
 134
 135void SimSet::addObject( SimObject* obj )
 136{
 137   // Prevent SimSet being added to itself.
 138   if( obj == this )
 139      return;
 140      
 141   lock();
 142   
 143   const bool added = mObjectList.pushBack( obj );
 144   if( added )
 145      deleteNotify( obj );
 146   
 147   unlock();
 148
 149   if( added )
 150   {
 151      getSetModificationSignal().trigger( SetObjectAdded, this, obj );
 152      if( obj->isProperlyAdded() )
 153         onObjectAdded_callback( obj );
 154   }
 155}
 156
 157//-----------------------------------------------------------------------------
 158
 159void SimSet::removeObject( SimObject* obj )
 160{
 161   lock();
 162   
 163   const bool removed = mObjectList.remove( obj );
 164   if( removed )
 165      clearNotify( obj );
 166   
 167   unlock();
 168
 169   if( removed )
 170   {
 171      getSetModificationSignal().trigger( SetObjectRemoved, this, obj );
 172      if( obj->isProperlyAdded() )
 173         onObjectRemoved_callback( obj );
 174   }
 175}
 176
 177//-----------------------------------------------------------------------------
 178
 179void SimSet::pushObject( SimObject* obj )
 180{
 181   if( obj == this )
 182      return;
 183      
 184   lock();
 185   
 186   bool added = mObjectList.pushBackForce( obj );
 187   if( added )
 188      deleteNotify( obj );
 189      
 190   unlock();
 191
 192   if( added )
 193   {
 194      getSetModificationSignal().trigger( SetObjectAdded, this, obj );
 195      if( obj->isProperlyAdded() )
 196         onObjectAdded_callback( obj );
 197   }
 198}
 199
 200//-----------------------------------------------------------------------------
 201
 202void SimSet::popObject()
 203{
 204   if(mObjectList.empty() )
 205   {
 206      AssertWarn(false, "Stack underflow in SimSet::popObject");
 207      return;
 208   }
 209
 210   lock();
 211   SimObject* object = mObjectList.last();
 212   mObjectList.pop_back();
 213
 214   clearNotify( object );
 215   unlock();
 216   
 217   getSetModificationSignal().trigger( SetObjectRemoved, this, object );
 218   if( object->isProperlyAdded() )
 219      onObjectRemoved_callback( object );
 220}
 221
 222//-----------------------------------------------------------------------------
 223
 224void SimSet::scriptSort( const String &scriptCallbackFn )
 225{
 226   lock();
 227   mObjectList.scriptSort( scriptCallbackFn );
 228   unlock();
 229}
 230
 231//-----------------------------------------------------------------------------
 232
 233void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValueRef argv[], bool executeOnChildGroups )
 234{
 235   // Prep the arguments for the console exec...
 236   // Make sure and leave args[1] empty.
 237   ConsoleValueRef args[21] = { };
 238   ConsoleValue name_method;
 239   name_method.setStackStringValue(method.c_str());
 240   args[0] = ConsoleValueRef::fromValue(&name_method);
 241
 242   for (S32 i = 0; i < argc; i++)
 243      args[i + 2] = argv[i];
 244
 245   for( iterator i = begin(); i != end(); i++ )
 246   {
 247      SimObject *childObj = static_cast<SimObject*>(*i);
 248
 249      if( childObj->isMethod( method.c_str() ) )
 250         Con::execute(childObj, argc + 2, args);
 251
 252      if( executeOnChildGroups )
 253      {
 254         SimSet* childSet = dynamic_cast<SimSet*>(*i);
 255         if ( childSet )
 256            childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
 257      }
 258   }
 259}
 260
 261//-----------------------------------------------------------------------------
 262
 263U32 SimSet::sizeRecursive()
 264{
 265   U32 count = 0;
 266
 267   for ( iterator i = begin(); i != end(); i++ )
 268   {
 269      count++;
 270
 271      SimSet* childSet = dynamic_cast<SimSet*>(*i);
 272      if ( childSet )
 273         count += childSet->sizeRecursive();
 274   }
 275
 276   return count;
 277}
 278
 279//-----------------------------------------------------------------------------
 280
 281bool SimSet::reOrder( SimObject *obj, SimObject *target )
 282{
 283   MutexHandle handle;
 284   handle.lock(mMutex);
 285
 286   iterator itrS, itrD;
 287   if ( (itrS = find(begin(),end(),obj)) == end() )
 288   {
 289      // object must be in list
 290      return false; 
 291   }
 292
 293   if ( obj == target )
 294   {
 295      // don't reorder same object but don't indicate error
 296      return true;   
 297   }
 298
 299   if ( !target )    
 300   {
 301      // if no target, then put to back of list
 302
 303      // don't move if already last object
 304      if ( itrS != (end()-1) )
 305      {
 306         // remove object from its current location and push to back of list
 307        mObjectList.erase(itrS);
 308        mObjectList.push_back(obj);
 309      }
 310   }
 311   else
 312   {
 313      // if target, insert object in front of target
 314      if ( (itrD = find(begin(),end(),target)) == end() )
 315         // target must be in list
 316         return false;
 317
 318     mObjectList.erase(itrS);
 319
 320      // once itrS has been erased, itrD won't be pointing at the 
 321      // same place anymore - re-find...
 322      itrD = find(begin(),end(),target);
 323     mObjectList.insert(itrD, obj);
 324   }
 325
 326   return true;
 327}   
 328
 329//-----------------------------------------------------------------------------
 330
 331void SimSet::onDeleteNotify(SimObject *object)
 332{
 333   removeObject(object);
 334   Parent::onDeleteNotify(object);
 335}
 336
 337//-----------------------------------------------------------------------------
 338
 339void SimSet::onRemove()
 340{
 341   MutexHandle handle;
 342   handle.lock( mMutex );
 343
 344   if( !mObjectList.empty() )
 345   {
 346      mObjectList.sortId();
 347      
 348      // This backwards iterator loop doesn't work if the
 349      // list is empty, check the size first.
 350      
 351      for( SimObjectList::iterator ptr = mObjectList.end() - 1;
 352            ptr >= mObjectList.begin(); ptr -- )
 353         clearNotify( *ptr );
 354   }
 355
 356   handle.unlock();
 357
 358   Parent::onRemove();
 359}
 360
 361//-----------------------------------------------------------------------------
 362
 363void SimSet::write(Stream &stream, U32 tabStop, U32 flags)
 364{
 365   MutexHandle handle;
 366   handle.lock(mMutex);
 367
 368   // export selected only?
 369   if((flags & SelectedOnly) && !isSelected())
 370   {
 371      for(U32 i = 0; i < size(); i++)
 372         (*this)[i]->write(stream, tabStop, flags);
 373
 374      return;
 375
 376   }
 377
 378   stream.writeTabs( tabStop );
 379   char buffer[ 2048 ];
 380   const U32 bufferWriteLen = dSprintf( buffer, sizeof( buffer ), "new %s(%s) {\r\n", getClassName(), getName() && !( flags & NoName ) ? getName() : "" );
 381   stream.write( bufferWriteLen, buffer );
 382   writeFields( stream, tabStop + 1 );
 383
 384   if(size())
 385   {
 386      stream.write(2, "\r\n");
 387      for(U32 i = 0; i < size(); i++)
 388      {
 389         SimObject* child = ( *this )[ i ];
 390         if( child->getCanSave() )
 391            child->write(stream, tabStop + 1, flags);
 392      }
 393   }
 394
 395   stream.writeTabs(tabStop);
 396   stream.write(4, "};\r\n");
 397}
 398
 399//-----------------------------------------------------------------------------
 400
 401void SimSet::clear()
 402{
 403   lock();
 404   
 405   while( !empty() )
 406      popObject();
 407      
 408   unlock();
 409
 410   getSetModificationSignal().trigger( SetCleared, this, NULL );
 411}
 412
 413//-----------------------------------------------------------------------------
 414
 415//UNSAFE
 416void SimSet::deleteAllObjects()
 417{
 418   lock();
 419   while( !empty() )
 420   {
 421      SimObject* object = mObjectList.last();
 422     mObjectList.pop_back();
 423
 424      object->deleteObject();
 425   }
 426   unlock();
 427}
 428
 429//-----------------------------------------------------------------------------
 430
 431SimObject* SimSet::findObject( SimObject* object )
 432{
 433   bool found = false;
 434   lock();
 435   for( SimSet::iterator iter = begin(); iter != end(); ++ iter )
 436      if( *iter == object )
 437      {
 438         found = true;
 439         break;
 440      }
 441   unlock();
 442   
 443   if( found )
 444      return object;
 445      
 446   return NULL;
 447}
 448
 449//-----------------------------------------------------------------------------
 450
 451SimObject* SimSet::findObject( const char *namePath )
 452{
 453   // find the end of the object name
 454   S32 len;
 455   for(len = 0; namePath[len] != 0 && namePath[len] != '/'; len++)
 456      ;
 457
 458   StringTableEntry stName = StringTable->lookupn(namePath, len);
 459   if(!stName)
 460      return NULL;
 461
 462   lock();
 463   for(SimSet::iterator i = begin(); i != end(); i++)
 464   {
 465      if((*i)->getName() == stName)
 466      {
 467         unlock();
 468         if(namePath[len] == 0)
 469            return *i;
 470         return (*i)->findObject(namePath + len + 1);
 471      }
 472   }
 473   unlock();
 474   return NULL;
 475}
 476
 477//-----------------------------------------------------------------------------
 478
 479SimObject* SimSet::findObjectByInternalName(StringTableEntry internalName, bool searchChildren)
 480{
 481   iterator i;
 482   for (i = begin(); i != end(); i++)
 483   {
 484      SimObject *childObj = static_cast<SimObject*>(*i);
 485      if(childObj->getInternalName() == internalName)
 486         return childObj;
 487      else if (searchChildren)
 488      {
 489         SimSet* childSet = dynamic_cast<SimSet*>(*i);
 490         if (childSet)
 491         {
 492            SimObject* found = childSet->findObjectByInternalName(internalName, searchChildren);
 493            if (found) return found;
 494         }
 495      }
 496   }
 497
 498   return NULL;
 499}
 500
 501//-----------------------------------------------------------------------------
 502
 503SimObject* SimSet::findObjectByLineNumber(const char* fileName, S32 declarationLine, bool searchChildren)
 504{
 505   if (!fileName)
 506      return NULL;
 507
 508   if (declarationLine < 0)
 509      return NULL;
 510
 511   StringTableEntry fileEntry = StringTable->insert(fileName);
 512
 513   for (iterator i = begin(); i != end(); i++)
 514   {
 515      SimObject *childObj = static_cast<SimObject*>(*i);
 516
 517      if(childObj->getFilename() == fileEntry && childObj->getDeclarationLine() == declarationLine)
 518         return childObj;
 519      else if (searchChildren)
 520      {
 521         SimSet* childSet = dynamic_cast<SimSet*>(*i);
 522
 523         if (childSet)
 524         {
 525            SimObject* found = childSet->findObjectByLineNumber(fileName, declarationLine, searchChildren);
 526            if (found)
 527               return found;
 528         }
 529      }
 530   }
 531
 532   return NULL;
 533}
 534
 535//-----------------------------------------------------------------------------
 536
 537SimObject* SimSet::getRandom()
 538{
 539   if (size() > 0)
 540      return mObjectList[mRandI(0, size() - 1)];
 541
 542   return NULL;
 543}
 544
 545//-----------------------------------------------------------------------------
 546
 547SimSet* SimSet::clone()
 548{
 549   // Clone the set object.
 550   
 551   SimObject* object = Parent::clone();
 552   SimSet* set = dynamic_cast< SimSet* >( object );
 553   if( !set )
 554   {
 555      object->deleteObject();
 556      return NULL;
 557   }
 558   
 559   // Add all object in the set.
 560   
 561   for( iterator iter = begin(); iter != end(); ++ iter )
 562      set->addObject( *iter );
 563   
 564   return set;
 565}
 566
 567//-----------------------------------------------------------------------------
 568
 569inline void SimSetIterator::Stack::push_back(SimSet* set)
 570{
 571   increment();
 572   last().set = set;
 573   last().itr = set->begin();
 574}
 575
 576//-----------------------------------------------------------------------------
 577
 578SimSetIterator::SimSetIterator(SimSet* set)
 579{
 580   VECTOR_SET_ASSOCIATION(stack);
 581
 582   if (!set->empty())
 583      stack.push_back(set);
 584}
 585
 586//-----------------------------------------------------------------------------
 587
 588SimObject* SimSetIterator::operator++()
 589{
 590   SimSet* set;
 591   if ((set = dynamic_cast<SimSet*>(*stack.last().itr)) != 0)
 592   {
 593      if (!set->empty())
 594      {
 595         stack.push_back(set);
 596         return *stack.last().itr;
 597      }
 598   }
 599
 600   while (++stack.last().itr == stack.last().set->end())
 601   {
 602      stack.pop_back();
 603      if (stack.empty())
 604         return 0;
 605   }
 606   return *stack.last().itr;
 607}
 608
 609//=============================================================================
 610//    SimGroup.
 611//=============================================================================
 612// MARK: ---- SimGroup ----
 613
 614//-----------------------------------------------------------------------------
 615
 616SimGroup::~SimGroup()
 617{
 618   for( iterator itr = begin(); itr != end(); itr ++ )
 619      mNameDictionary.remove(*itr);
 620}
 621
 622//-----------------------------------------------------------------------------
 623
 624void SimGroup::_addObject( SimObject* obj, bool forcePushBack )
 625{
 626   // Make sure we aren't adding ourself.  This isn't the most robust check
 627   // but it should be good enough to prevent some self-foot-shooting.
 628   if( obj == this )
 629   {
 630      Con::errorf( "SimGroup::addObject - (%d) can't add self!", getIdString() );
 631      return;
 632   }
 633   
 634   if( obj->getGroup() == this )
 635      return;
 636
 637   lock();
 638   
 639   obj->incRefCount();
 640   
 641   if( obj->getGroup() )
 642      obj->getGroup()->removeObject( obj );
 643      
 644   if( forcePushBack ? mObjectList.pushBack( obj ) : mObjectList.pushBackForce( obj ) )
 645   {
 646      mNameDictionary.insert( obj );
 647      obj->mGroup = this;
 648      
 649      obj->onGroupAdd();
 650      
 651      getSetModificationSignal().trigger( SetObjectAdded, this, obj );
 652      if( obj->isProperlyAdded() )
 653         onObjectAdded_callback( obj );
 654   }
 655   else
 656      obj->decRefCount();
 657   
 658   unlock();
 659
 660   // SimObjects will automatically remove them from their group
 661   // when deleted so we don't hook up a delete notification.
 662}
 663
 664//-----------------------------------------------------------------------------
 665
 666void SimGroup::addObject( SimObject* obj )
 667{
 668   _addObject( obj );
 669}
 670
 671//-----------------------------------------------------------------------------
 672
 673void SimGroup::removeObject( SimObject* obj )
 674{
 675   lock();
 676   _removeObjectNoLock( obj );
 677   unlock();
 678}
 679
 680//-----------------------------------------------------------------------------
 681
 682void SimGroup::_removeObjectNoLock( SimObject* obj )
 683{
 684   if( obj->mGroup == this )
 685   {
 686      obj->onGroupRemove();
 687      
 688      mNameDictionary.remove( obj );
 689     mObjectList.remove( obj );
 690      obj->mGroup = 0;
 691
 692      getSetModificationSignal().trigger( SetObjectRemoved, this, obj );
 693      if( obj->isProperlyAdded() )
 694         onObjectRemoved_callback( obj );
 695      obj->decRefCount();
 696   }
 697}
 698
 699//-----------------------------------------------------------------------------
 700
 701void SimGroup::pushObject( SimObject* object )
 702{
 703   _addObject( object, true );
 704}
 705
 706//-----------------------------------------------------------------------------
 707
 708void SimGroup::popObject()
 709{
 710   MutexHandle handle;
 711   handle.lock( mMutex );
 712
 713   if(mObjectList.empty() )
 714   {
 715      AssertWarn( false, "SimGroup::popObject - Stack underflow" );
 716      return;
 717   }
 718
 719   SimObject* object = mObjectList.last();
 720   mObjectList.pop_back();
 721
 722   object->onGroupRemove();
 723   object->mGroup = NULL;
 724
 725   clearNotify( object );
 726   mNameDictionary.remove( object );
 727      
 728   getSetModificationSignal().trigger( SetObjectAdded, this, object );
 729   if( object->isProperlyAdded() )
 730      onObjectRemoved_callback( object );
 731   
 732   object->decRefCount();
 733}
 734
 735//-----------------------------------------------------------------------------
 736
 737void SimGroup::onRemove()
 738{
 739   lock();
 740   if( !mObjectList.empty() )
 741   {
 742      mObjectList.sortId();
 743      clear();
 744   }
 745   SimObject::onRemove();
 746   unlock();
 747}
 748
 749//-----------------------------------------------------------------------------
 750
 751void SimGroup::clear()
 752{
 753   lock();
 754   while( size() > 0 )
 755   {
 756      SimObject* object = mObjectList.last();
 757      object->onGroupRemove();
 758      
 759     mObjectList.pop_back();
 760      mNameDictionary.remove( object );
 761      object->mGroup = 0;
 762
 763      getSetModificationSignal().trigger( SetObjectRemoved, this, object );
 764      if( object->isProperlyAdded() )
 765         onObjectRemoved_callback( object );
 766
 767      if( engineAPI::gUseConsoleInterop )
 768         object->deleteObject();
 769      else
 770         object->decRefCount();      
 771   }
 772   unlock();
 773
 774   getSetModificationSignal().trigger( SetCleared, this, NULL );
 775}
 776
 777//-----------------------------------------------------------------------------
 778
 779SimObject *SimGroup::findObject(const char *namePath)
 780{
 781   // find the end of the object name
 782   S32 len;
 783   for(len = 0; namePath[len] != 0 && namePath[len] != '/'; len++)
 784      ;
 785
 786   StringTableEntry stName = StringTable->lookupn(namePath, len);
 787   if(!stName)
 788      return NULL;
 789
 790   SimObject *root = mNameDictionary.find( stName );
 791   if( !root )
 792      return NULL;
 793
 794   if(namePath[len] == 0)
 795      return root;
 796
 797   return root->findObject(namePath + len + 1);
 798}
 799
 800//-----------------------------------------------------------------------------
 801
 802SimGroup* SimGroup::clone()
 803{
 804   // Skip SimSet::clone since we do not want to steal the child objects
 805   // from this group.
 806   
 807   SimObject* object = SimObject::clone();
 808   SimGroup* group = dynamic_cast< SimGroup* >( object );
 809   if( !group )
 810   {
 811      object->deleteObject();
 812      return NULL;
 813   }
 814   
 815   return group;
 816}
 817
 818//-----------------------------------------------------------------------------
 819
 820SimGroup* SimGroup::deepClone()
 821{
 822   // Clone the group object.
 823   
 824   SimObject* object = Parent::deepClone();
 825   SimGroup* group = dynamic_cast< SimGroup* >( object );
 826   if( !group )
 827   {
 828      object->deleteObject();
 829      return NULL;
 830   }
 831   
 832   // Clone all child objects.
 833   
 834   for( iterator iter = begin(); iter != end(); ++ iter )
 835      group->addObject( ( *iter )->deepClone() );
 836   
 837   return group;
 838}
 839
 840//-----------------------------------------------------------------------------
 841
 842bool SimGroup::processArguments(S32, ConsoleValueRef *argv)
 843{
 844   return true;
 845}
 846
 847
 848SimObject* SimGroup::getObject(const S32& index)
 849{
 850   if (index < 0 || index >= size())
 851   {
 852      Con::errorf("Set::getObject - index out of range.");
 853      return NULL;
 854   }
 855
 856   return (*this)[index];
 857}
 858//-----------------------------------------------------------------------------
 859
 860SimObject* SimGroupIterator::operator++()
 861{
 862   SimGroup* set;
 863   if ((set = dynamic_cast<SimGroup*>(*stack.last().itr)) != 0)
 864   {
 865      if (!set->empty())
 866      {
 867         stack.push_back(set);
 868         return *stack.last().itr;
 869      }
 870   }
 871
 872   while (++stack.last().itr == stack.last().set->end())
 873   {
 874      stack.pop_back();
 875      if (stack.empty())
 876         return 0;
 877   }
 878   return *stack.last().itr;
 879}
 880
 881//=============================================================================
 882//    API.
 883//=============================================================================
 884// MARK: ---- API ----
 885
 886//-----------------------------------------------------------------------------
 887
 888DefineEngineMethod( SimSet, listObjects, void, (),,
 889   "Dump a list of all objects contained in the set to the console." )
 890{
 891   object->lock();
 892   SimSet::iterator itr;
 893   for(itr = object->begin(); itr != object->end(); itr++)
 894   {
 895      SimObject *obj = *itr;
 896      bool isSet = dynamic_cast<SimSet *>(obj) != 0;
 897      const char *name = obj->getName();
 898      if(name)
 899         Con::printf("   %d,\"%s\": %s %s", obj->getId(), name,
 900         obj->getClassName(), isSet ? "(g)":"");
 901      else
 902         Con::printf("   %d: %s %s", obj->getId(), obj->getClassName(),
 903         isSet ? "(g)" : "");
 904   }
 905   object->unlock();
 906}
 907
 908//-----------------------------------------------------------------------------
 909
 910DefineEngineStringlyVariadicMethod( SimSet, add, void, 3, 0,
 911   "( SimObject objects... ) Add the given objects to the set.\n"
 912   "@param objects The objects to add to the set." )
 913{
 914   for(S32 i = 2; i < argc; i++)
 915   {
 916      SimObject *obj = Sim::findObject( argv[ i ] );
 917      if(obj)
 918         object->addObject( obj );
 919      else
 920         Con::printf("Set::add: Object \"%s\" doesn't exist", (const char*)argv[ i ] );
 921   }
 922}
 923
 924//-----------------------------------------------------------------------------
 925
 926DefineEngineStringlyVariadicMethod( SimSet, remove, void, 3, 0,
 927   "( SimObject objects... ) Remove the given objects from the set.\n"
 928   "@param objects The objects to remove from the set." )
 929{
 930   for(S32 i = 2; i < argc; i++)
 931   {
 932      SimObject *obj = Sim::findObject(argv[i]);
 933      object->lock();
 934      if(obj && object->find(object->begin(),object->end(),obj) != object->end())
 935         object->removeObject(obj);
 936      else
 937         Con::printf("Set::remove: Object \"%s\" does not exist in set", (const char*)argv[i]);
 938      object->unlock();
 939   }
 940}
 941
 942//-----------------------------------------------------------------------------
 943
 944DefineEngineMethod( SimSet, clear, void, (),,
 945   "Remove all objects from the set." )
 946{
 947   object->clear();
 948}
 949
 950//-----------------------------------------------------------------------------
 951
 952//UNSAFE; don't want this in the new API
 953DefineEngineMethod( SimSet, deleteAllObjects, void, (), , "() Delete all objects in the set." )
 954{
 955   object->deleteAllObjects();
 956}
 957
 958//-----------------------------------------------------------------------------
 959
 960DefineEngineMethod( SimSet, getRandom, SimObject*, (),,
 961   "Return a random object from the set.\n"
 962   "@return A randomly selected object from the set or -1 if the set is empty." )
 963{
 964   return object->getRandom();
 965}
 966
 967//-----------------------------------------------------------------------------
 968
 969DefineEngineStringlyVariadicMethod( SimSet, callOnChildren, void, 3, 0,
 970   "( string method, string args... ) Call a method on all objects contained in the set.\n\n"
 971   "@param method The name of the method to call.\n"
 972   "@param args The arguments to the method.\n\n"
 973   "@note This method recurses into all SimSets that are children to the set.\n\n"
 974   "@see callOnChildrenNoRecurse" )
 975{
 976   object->callOnChildren( (const char*)argv[2], argc - 3, argv + 3 );
 977}
 978
 979//-----------------------------------------------------------------------------
 980
 981DefineEngineStringlyVariadicMethod( SimSet, callOnChildrenNoRecurse, void, 3, 0,
 982   "( string method, string args... ) Call a method on all objects contained in the set.\n\n"
 983   "@param method The name of the method to call.\n"
 984   "@param args The arguments to the method.\n\n"
 985   "@note This method does not recurse into child SimSets.\n\n"
 986   "@see callOnChildren" )
 987{
 988   object->callOnChildren( (const char*)argv[2], argc - 3, argv + 3, false );
 989}
 990
 991//-----------------------------------------------------------------------------
 992
 993DefineEngineMethod( SimSet, reorderChild, void, ( SimObject* child1, SimObject* child2 ),,
 994   "Make sure child1 is ordered right before child2 in the set.\n"
 995   "@param child1 The first child.  The object must already be contained in the set.\n"
 996   "@param child2 The second child.  The object must already be contained in the set." )
 997{
 998   SimObject* pObject = child1;
 999   SimObject* pTarget = child2;
1000
1001   if(pObject && pTarget)
1002   {
1003      object->reOrder(pObject,pTarget);
1004   }
1005}
1006
1007//-----------------------------------------------------------------------------
1008
1009DefineEngineMethod( SimSet, getCount, S32, (),,
1010   "Get the number of objects contained in the set.\n"
1011   "@return The number of objects contained in the set." )
1012{
1013   return object->size();
1014}
1015
1016//-----------------------------------------------------------------------------
1017
1018DEFINE_CALLIN( fnSimSet_getCountRecursive, getCountRecursive, SimSet, U32, ( SimSet* set ),,,
1019   "Get the number of direct and indirect child objects contained in the set.\n"
1020   "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )
1021{
1022   return set->sizeRecursive();
1023}
1024
1025DefineEngineMethod( SimSet, getFullCount, S32, (), , "() Get the number of direct and indirect child objects contained in the set.\n"
1026   "@return The number of objects contained in the set as well as in other sets contained directly or indirectly in the set." )
1027{
1028   return object->sizeRecursive();
1029}
1030
1031//-----------------------------------------------------------------------------
1032
1033DefineEngineMethod( SimSet, getObject, SimObject*, ( U32 index ),,
1034   "Get the object at the given index.\n"
1035   "@param index The object index.\n"
1036   "@return The object at the given index or -1 if index is out of range." )
1037{
1038   if( index < 0 || index >= object->size() )
1039   {
1040      Con::errorf( "Set::getObject - index out of range." );
1041      return NULL;
1042   }
1043   
1044   return ( *object )[ index ];
1045}
1046
1047//-----------------------------------------------------------------------------
1048
1049DefineEngineMethod( SimSet, getObjectIndex, S32, ( SimObject* obj ),,
1050   "Return the index of the given object in this set.\n"
1051   "@param obj The object for which to return the index.  Must be contained in the set.\n"
1052   "@return The index of the object or -1 if the object is not contained in the set." )
1053{
1054   if( !obj )
1055      return -1;
1056
1057   object->lock();
1058   S32 count = 0;
1059   for( SimSet::iterator i = object->begin(); i != object->end(); i++)
1060   {
1061      if( *i == obj )
1062      {
1063         object->unlock();
1064         return count;
1065      }
1066
1067      ++count;
1068   }
1069   object->unlock();
1070
1071   return -1;
1072}
1073
1074//-----------------------------------------------------------------------------
1075
1076DefineEngineMethod( SimSet, isMember, bool, ( SimObject* obj ),,
1077   "Test whether the given object belongs to the set.\n"
1078   "@param obj The object.\n"
1079   "@return True if the object is contained in the set; false otherwise." )
1080{
1081   if( !obj )
1082      return false;
1083
1084   return ( object->find( object->begin(), object->end(), obj ) != object->end() );
1085}
1086
1087//-----------------------------------------------------------------------------
1088
1089DefineEngineMethod( SimSet, findObjectByInternalName, SimObject*, ( const char* internalName, bool searchChildren ), ( false ),
1090   "Find an object in the set by its internal name.\n"
1091   "@param internalName The internal name of the object to look for.\n"
1092   "@param searchChildren If true, SimSets contained in the set will be recursively searched for the object.\n"
1093   "@return The object with the given internal name or 0 if no match was found.\n" )
1094{
1095   StringTableEntry pcName = StringTable->insert( internalName );
1096   return object->findObjectByInternalName( pcName, searchChildren );
1097}
1098
1099//-----------------------------------------------------------------------------
1100
1101DefineEngineMethod( SimSet, bringToFront, void, ( SimObject* obj ),,
1102   "Make the given object the first object in the set.\n"
1103   "@param obj The object to bring to the frontmost position.  Must be contained in the set." )
1104{
1105   if( obj )
1106      object->bringObjectToFront( obj );
1107}
1108
1109//-----------------------------------------------------------------------------
1110
1111DefineEngineMethod( SimSet, pushToBack, void, ( SimObject* obj ),,
1112   "Make the given object the last object in the set.\n"
1113   "@param obj The object to bring to the last position.  Must be contained in the set." )
1114{
1115   if( obj )
1116      object->pushObjectToBack( obj );
1117}
1118
1119//-----------------------------------------------------------------------------
1120
1121DefineEngineMethod( SimSet, sort, void, ( const char * callbackFunction ), , "( string callbackFunction ) Sort the objects in the set using the given comparison function.\n"
1122   "@param callbackFunction Name of a function that takes two object arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." )
1123{
1124   object->scriptSort( callbackFunction );
1125}
1126
1127//-----------------------------------------------------------------------------
1128
1129DefineEngineMethod( SimSet, acceptsAsChild, bool, ( SimObject* obj ),,
1130   "Test whether the given object may be added to the set.\n"
1131   "@param obj The object to test for potential membership.\n"
1132   "@return True if the object may be added to the set, false otherwise." )
1133{
1134   if( !obj )
1135      return false;
1136   
1137   return object->acceptsAsChild( obj );
1138}
1139