Using ArrayObject and custom script sorting callbacks
The
ArrayObject
class provides a true key/value pair dictionary in TorqueScript. It allows for easy searching and counting of key/value pairs and can optionally remove duplicates by either key or value. An ArrayObject
class may also sort by key or value using standard algorithms, but it also supports custom sorting using script callbacks. In this recipe, we will see how to set up a custom sort callback that will be used by an ArrayObject
instance.
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 custom sort an ArrayObject
as follows:
Open the
game/scripts/server/game.cs
script file and add the following code to the bottom:function sortArrayObject1() { // Create a new ArrayObject %array = new ArrayObject(); // Fill the array with any SceneObject in the // MissionGroup SimGroup. foreach (%obj in MissionGroup) { if (%obj.isInNamespaceHierarchy("SceneObject")) { // This is a SceneObject so add it to the array %array.add(%obj.getId(), %obj.getClassName()); } } // Fill the array with any SceneObject in the // MissionCleanup SimGroup. foreach (%obj in MissionCleanup) { if (%obj.isInNamespaceHierarchy("SceneObject")) { // This is a SceneObject so add it to the array %array.add(%obj.getId(), %obj.getClassName()); } } // Sort the array's keys in ascending order using our // custom sort function. This function will sort // all objects according to their world y position. %array.sortfk(arraySortFunction1); // Now output the list of objects to the console %count = %array.count(); for (%i=0; %i<%count; %i++) { // The key holds the SimObject ID %key = %array.getKey(%i); // The value hold the class name %value = %array.getValue(%i); // Get the object's position %pos = %key.getPosition(); // Print to the console echo(%value @ " [" @ %key @ "] Y Position: " @ %pos.y); } } // Our array sort function. %a and %b hold the // SimObject ID's of the objects to sort (the keys). function arraySortFunction1(%a, %b) { %posA = %a.getPosition(); %posB = %b.getPosition(); if (%posA.y < %posB.y) return -1; else if (%posA.y > %posB.y) return 1; else return 0; }
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:sortArrayObject1();
In the console we will see the following output:
==>sortArrayObject1(); TerrainBlock [4277] Y Position: -1024 ScatterSky [4276] Y Position: 0 Camera [4289] Y Position: 0.250583 Player [4290] Y Position: 5.14696
How it works...
The example code begins by creating the
ArrayObject
instance that will be used to store some objects. It then steps through all the MissionGroup
and
MissionCleanup
objects and stores any SceneObject
instances it finds onto the array. The SimObject
ID of the object is used as the key, and the class name of the object is used as the value.
With the array populated, we do an ascending sort using our custom sorting function, arraySortFunction1()
as follows:
// Sort the array's keys in ascending order using our // custom sort function. This function will sort // all objects according to their world y position. %array.sortfk(arraySortFunction1);
The code then steps through the sorted array and prints the results to the console.
The critical component here is our custom sorting function, arraySortFunction1()
. Each time the function is called, it passes two items to compare. As we're doing a key-based sort, the key of each item is passed to our sort function. When we created the array we placed SimObject
ID of each SceneObject
instance into the key, so we may now use the key to retrieve information about the SceneObject
instance. In our case we get the world position of each object as follows:
%posA = %a.getPosition(); %posB = %b.getPosition();
The rule for the sorting function is that if item A is less than item B then return a value of -1
. If item A is greater than B then return a value of 1
. And if items A and B are equal, return a value of 0
. It is up to our sorting function to determine what makes item A lesser than or greater than item B. In our example we're using world Y position of each object as follows:
if (%posA.y < %posB.y) return -1; else if (%posA.y > %posB.y) return 1; else return 0;
We then end up with a nicely sorted list from the lowest Y position to highest Y position that we output to the console.
See also
Using script arrays as dictionaries