Accessing delimited fields within a string
When working with lists in TorqueScript, be it a list of scene object IDs or a set of Cartesian coordinates, we will invariably come across
space-delimited strings. For example, calling the
getPosition()
method on a scene object will return a three-field string such as 13.4 -2.1 96.35
that represents the world distance along the x, y, and z axes, respectively.
TorqueScript provides a number of functions that allows us to access and manipulate the fields within space-delimited strings. In this recipe we will learn how to use these functions when working with string variables.
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!
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com . If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
How to do it...
We are going to write a TorqueScript function that will parse a space-delimited string and output the results to the console. This is done as follows:
Open the
game/scripts/client/client.cs
script file and add the following code to the bottom:function operateOnFields1() { // Get the player's position in the world. // Will be a string in the form of "x y z". %position = ServerConnection.getControlObject().getPosition(); // Print out the player's position to the // console in its raw format echo("Raw player position: " @ %position); // Get the number of fields in the returned // position string %count = getWordCount(%position); // Print the value of each field to the console echo("Player position by field index:"); for (%i=0; %i<%count; %i++) { echo(" " @ %i @ ": " @ getWord(%position, %i)); } // Print out only the x and y fields echo("Player x and y position only: " @ getWords(%position, 0, 1)); // Set the 3rd field (the z value) to 0 %position = setWord(%position, 2, "0"); echo("Position variable with new z value: " @ %position); // Remove the z value (3rd field) to only be // left with "x y" %position = removeWord(%position, 2); echo("Position variable with no z value: " @ %position); }
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:operateOnFields1();
In the console we will see the following output:
==>operateOnFields1(); Raw player position: 0.121759 1.13497 240.67 Player position by field index: 0: 0.121759 1: 1.13497 2: 240.67 Player x and y position only: 0.121759 1.13497 Position variable with new z value: 0.121759 1.13497 0 Position variable with no z value: 0.121759 1.13497
How it works...
The previous code walks us through all of the functions used to access and manipulate the variables that contain space-delimited fields. We will now examine each of these functions and learn how to make use of them.
After obtaining the player's world position, our first
action in the previous example is to get the number of fields within the space-delimited string (the %position
variable). This is done using the
getWordCount()
function that has the following form:
amount = getWordCount( string );
In this form, string
is the space-delimited string that contains the number of fields we want to eventually parse. The
getWordCount()
function returns the number of fields counted. The previous code stores this value into the %count
variable. If there are no fields in the string, then 0
is returned.
With the number of fields now known, we can retrieve the individual x, y, and z values of the %position
variable based on an index. To do this we use the getWord()
function that has the following form:
field = getWord( string, index );
Here, the string
parameter is the space-delimited string to parse, and the index
parameter is the field number to retrieve. The
getWord()
function returns a string containing the single requested field. If the field index does not exist within the passed-in string, an empty string is returned.
The next action performed in the example code is to retrieve more than one field at a time. Specifically, the code extracts the x and y values from the player's position (the first and second field). We use the
getWords()
function to retrieve more than one field, which has the following form:
fields = getWords( string, startIndex, [endIndex] );
Here, the string
parameter is the space-delimited string to parse, the startIndex
parameter is the start of the range to retrieve, and the optional endIndex
parameter is the end of the field range. If endIndex
is not provided or has a value of -1
, then all of the fields at the end of the string are returned.
The getWords()
function returns a string containing all of the requested fields. If none of the requested fields exist within the passed-in string, an empty string is returned.
The example code then goes on to manipulate the %position
variable by changing its z value (the third field). This is done with the
setWord()
function that has the following form:
result = setWord( string, index, replacement );
Here, the string
parameter is the space-delimited string to modify, the index
parameter is the field index in the string to modify, and the
replacement
parameter is the string used to replace the current value of the field. The setWord()
function returns a new string with the modifications and doesn't change the passed-in string.
If we wanted to modify the original variable, we would just use the same variable name for the return value as we did for the passed-in string. For example, consider the following code:
%position = setWord(%position, 2, "0");
The new string will essentially replace the previous string stored in %position
.
If the index passed-in to setWord()
is larger than the number of fields in the given string, the returned string is padded with empty fields to make up the difference, essentially appending the replacement string on to the end. For example, the following code would print a count of six to the console (the fifth index accesses the sixth field):
%val1 = "1 2 3"; %val2 = setWord( %val1, 5, "4"); echo( getWordCount( %val2 ) );
The final action in the example code removes a field from the string variable. This is done using the
removeWord()
function that has the following form:
result = removeWord( string, index );
Here, the
string
parameter is the space-delimited string to modify, and the
index
parameter is the field index in the string to remove. The
removeWord()
function returns a new string with the modifications and doesn't change the passed-in string. If the given field index does not exist within the string, the original string is
returned unchanged.
As with the
setWord()
function, if we want to modify the original variable, we would need to pass it in as the string
parameter as well as use it to store the result. This is done in the example code with the %position
variable.
There's more...
While space-delimited strings are the most common type of list we will come across in TorqueScript, spaces are not the only way to delimit a string. Tabs and new lines may also be used. We could use tab delimiters when we want the fields to contain spaces, and new line delimiters when we want the fields to contain spaces or tabs.
The whole Word family of functions we just explored (getWord()
and so on) actually works with more than just spaces. They treat all the spaces, tabs, and new lines as valid delimiters. But what if we don't want to count spaces as a delimiter, such as with a list of peoples' combined first and last names ("John Smith")? There are two other families of functions that narrow the scope of what is a valid delimiter: Field and Record.
Skipping spaces (only tab and new line delimiters)
The Field family of functions performs all of the same operations as the Word family of functions, except they only use tabs and new lines as field delimiters. For example, put the following function at the end of the game/scripts/client/client.cs
script file:
function operateOnFields2() { // Build up a list of tab delimited name %list = "John Smith" TAB "Mary Contrary" TAB "Fido"; // Get the number of tab delimited fields %count = getFieldCount(%list); // Print out a list of fields by index for (%i=0; %i<%count; %i++) { echo("Field " @ %i @ ": " @ getField(%list, %i)); } }
Start up our game under the My Projects
directory and load the Empty Terrain
level. Open the console using the tilde (~) key and enter the following at the bottom of the screen:
operateOnFields2();
The following will be output to the console:
==>operateOnFields2(); Field 0: John Smith Field 1: Mary Contrary Field 2: Fido
With the Field family of functions, any field that contains spaces is treated as a single field.
Skipping spaces and tabs (only new line delimiters)
The Record family of functions performs all of the same operations as the Word family of functions, except they only use new lines as field delimiters. For example, put the following function at the end of the game/scripts/client/client.cs
script file:
function operateOnFields3() { // Build up a list of new line delimited items %list = "0" TAB "First item" NL "1" TAB "Second item" NL "2" TAB "Third item"; // Get the number of tab delimited fields %count = getRecordCount(%list); // Print out a list of fields by index for (%i=0; %i<%count; %i++) { echo("Field " @ %i @ ": '" @ getRecord(%list, %i) @ "'"); } }
Start up our game under the My Projects
directory and load the Empty Terrain
level. Open the console using the tilde (~) key and enter the following at the bottom of the screen:
operateOnFields3();
The following will be output to the console:
==>operateOnFields3(); Field 0: '0^First item' Field 1: '1^Second item' Field 2: '2^Third item'
In the console, the output above the caret (^
) symbol represents a tab. With the Record family of functions, any field that contains spaces and tabs is treated as a single field.
See also
Iterating on words in a string list
Retrieving components of a variable using accessors