Finding an object in a SimSet or SimGroup collection using its internal name
SimObject
instances may optionally have a globally unique name. This makes it easy to work with a SimObject
instance from any script function or method. However, this can clutter up the global namespace and there is the possibility of
naming collisions. SimObject
instances may also have an internal name that need only be unique within its direct parent SimSet
or SimGroup
collection. We most often find internal names being used in Torque 3D's GUI system where all GuiControl
objects are also the SimGroup
collections, and they are always organized in a hierarchy. In this recipe we will retrieve a SimObject
instance from its collection based on its internal name.
Getting ready
We will be adding a new TorqueScript function to a project based on the Torque 3D Full
template and try it out using the Empty Terrain
level. If you haven't already, use the Torque Project Manager (Project Manager.exe
) to create a new project from the Full
template. It will be found under the My Projects
directory. Then start up your favorite script editor, such as Torsion, and let's get going!
How to do it...
We are going to write a TorqueScript function that will demonstrate how to find a SimObject
instance using its internal name as follows:
Open the
game/scripts/server/game.cs
script file and add the following code to the bottom:function getByInternalName1() { // Create a SimGroup new SimGroup(MyGroup); // Create some script objects with unique internal // names and add each one to our SimGroup. // The ScriptObject class is just a generic SimObject that // we can create in TorqueScript. %so = new ScriptObject() { internalName = "name1"; }; MyGroup.add(%so); %so = new ScriptObject() { internalName = "name2"; }; MyGroup.add(%so); %so = new ScriptObject() { internalName = "name3"; }; MyGroup.add(%so); // Find an object in the SimGroup using its internal name %object = MyGroup.findObjectByInternalName("name2"); // Print some information about the object to the console echo("Found object " @ %object.getId() @ " with internal name: " @ %object.internalName); // Clean up the SimGroup and all of the script objects MyGroup.delete(); }
Start up our game under the
My Projects
directory and load theEmpty Terrain
level. Open the console using the tilde (~) key and enter the following at the bottom of the screen:getByInternalName1();
In the console we will see the following output:
==>getByInternalName1(); Found object 4154 with internal name: name2
How it works...
So that we may see the internal name search in action, we first create some SimObject
instances and add them to a SimGroup
collection. In our previous example we use the ScriptObject
class for our SimObject
instance. The
ScriptObject
class is the most basic SimObject
derived class we can build from script,
and can come in handy when we want an object that can hold arbitrary data. We give a unique value to the internalName
property of each ScriptObject
class.
With all of the objects and a group collection set up, we use the findObjectByInternalName()
method of a SimGroup
collection. This method is also available in a SimSet
collection and has the following form:
foundObject = SimGroup.findObjectByInternalName( name, [searchChildren] );
Here, the name
parameter is the internal name we wish to search for in the SimGroup
collection, and the optional
searchChildren
parameter indicates the child collections should be searched when set to true
(it is false
by default). If a
SimObject
instance with its
internalName
property matches the requested name
, it is returned. If no SimObject
instance matches or there are none yet in the collection, 0
is returned.
There's more...
Let's look at some additional ways to search for a SimObject
class in a SimSet
or SimGroup
collection.
Including children SimSet and SimGroup collections in the search
The SimSet
and SimGroup
classes are derived from the
SimObject
class, and therefore may also be children of a SimSet
or SimGroup
collection. One place we come across this is with a Torque 3D level file. At the top is a SimGroup
collection named MissionGroup
. Under this group are a number of different objects, and usually a number of different SimGroup
objects in order to better organize objects of the level. The
Empty Terrain
level that we have been using in our examples has a child SimGroup
collection named PlayerDropPoints
that holds all the locations that a player may spawn at.
Another place we come across a hierarchy of SimGroup
objects is when working with Torque 3D's GUI system. All GUI objects are derived from the
GuiControl
class, which itself is a SimGroup
collection. This means that any GuiControl
class can be a child of another GuiControl
class. So as to not clutter up the global namespace with the names of GuiControl
objects, we often use the internalName
property as much as possible.
When we want to find a
GuiControl
class to work with (such as one of many radio buttons in a group), we perform an internal name search at some parent or grandparent GuiControl
. If you keep the
internalName
property unique among GuiControl
instances in a dialog window for example, we can start the search with the GuiControl
class of the window and need not worry about name collisions with other dialog windows.
To perform a search starting from a SimGroup
or SimSet
collection and include all of its children, we will set optional
searchChildren
parameter of the findObjectByInternalName()
method to true
. For example, consider the following line of code:
%object = MyGroup.findObjectByInternalName("name3", true);
Starting with MyGroup
this will search through all children SimGroup
and SimSet
objects until it comes across the first SimObject
instance with its internalName
property set to name3
. If no
SimObject
instance matches or there are no objects in the collection, a value of 0
is returned.
Using the special -> operator
Using findObjectByInternalName()
is very useful, especially if we pass-in a computed variable to its name
parameter. But if we know the exact name to search for, there is a much less verbose shortcut. We can use the special ->
operator. For example, look at the following code:
%object = MyGroup->name2;
The new code is equivalent to the following code:
%object = MyGroup.findObjectByInternalName("name2");
Just like this usage of
findObjectByInternalName()
the ->
operator will not search in child SimGroup
or SimSet
objects.
Another handy usage of the ->
operator occurs when we want to immediately call a method on the found object. In this case we can just append the method to the search call as follows:
MyGroup->name2.doSomething(true);
What happens here is, first a SimObject
instance with the internal name of name2
is found, and then the
doSomething()
method is called on that SimObject
instance.
Using the special --> operator
As with the ->
operator discussed in the previous section, the -->
operator is also a shortcut for using findObjectByInternalName()
. The only difference is that the -->
operator will also search in child SimGroup
and SimSet
instances when looking for a matching internal name on a SimObject
instance. For example, consider the following line of code:
%object = MyGroup-->name2;
This is equivalent to the following code, with the
searchChildren
parameter set to true
:
%object = MyGroup.findObjectByInternalName("name2", true);
Another handy usage of the -->
operator occurs when we want to immediately call a method on the found object. In this case we can just append the method to the search call as follows:
MyGroup-->name2.doSomething(true);
What happens here is first a SimObject
instance with the internal name of name2
is found in all the children SimGroup
and SimSet
objects, and then the doSomething()
method is called on that SimObject
instance. We often find this pattern when working with the GuiControl
objects.
See also
Iterating on objects in a SimSet or SimGroup collection
Getting a random object from a SimSet or SimGroup collection
Executing a method on a SimSet or SimGroup collection