A multidimensional array is an array where each item contains another array—an array of arrays. Such an array is called a two dimensional array. It is possible to have arrays of higher dimensions. A two dimensional array would look like this:
#(#(1,2),#(3,4))
You can assign any variable to it like so:
h = #(#(1,2),#(3,4))
You create a two dimensional array in the following exercise.
To create a two dimensional array:
1. Reset 3ds Max.
2. Open a new MAXScript Editor window with MAXScript menu > New Script. Type the following into the editor, and execute it with CTRL+E:
3. The Listener responds with a new 2D array filled with random numbers that range between one and 10.
array2D()
#(#(10, 1), #(10, 9), #(4, 5), #(9, 4))
In the next example, you’ll define an array that holds all of the information necessary to create an object. Then you will define an array of those arrays.
Collections ■
39
To use multidimensional arrays with mixed data types:
1. Type all the statements in this example into a MAXScript Editor window as they appear. You will execute the entire script at the end.
2. In a new MAXScript Editor window, create two arrays. These will become cylinder description arrays.
cylobj1 = #() cylobj2 = #()
3. Create some modifiers to use later:
tap = taper amount:-1.0 bnd = bend angle:30
4. Fill in array elements for the cylinder objects. You define the first element to be the cylinder height, the second its x position, the third to be the cylinder's name, and the fourth to be the modifier you are applying.
cylobj1[1] = 30.0 cylobj1[2] = 0.0
cylobj1[3] = "first cylinder"
cylobj1[4] = tap cylobj2[1] = 60.0 cylobj2[2] = 40.0
cylobj2[3] = "second cylinder"
cylobj2[4] = bnd
5. Build an array of cylinder description arrays.
my_cylinders = #(cylobj1, cylobj2)
To access an element from cylinders, you use cylinders[i][j], where the first index [i] refers to the cylinder description array, and the second index [j] indexes into the cylinder description array.
6. Build the two cylinders.
for i = 1 to my_cylinders.count do (
c = cylinder height:my_cylinders[i][1] \
pos:[my_cylinders[i][2], 0.0, 0.0] \ name:my_cylinders[i][3] \
heightsegs:10 addmodifier c my_cylinders[i][4]
)
A version of this script can be found on the application CD and is called 2_D_Arrays.ms. This is the result.
Wildcards
To add several objects to a collection at once, you can use the wildcard character, the asterisk (*). Earlier, you saw the asterisk used as the symbol for multiplication. The asterisk can also be used as a placeholder to signify one or more arbitrary alphanumeric characters. This is equivalent to doing a file search in Windows Explorer and using an asterisk, for example, searching for *.max locates all files with a .max extension. You can use the wildcard character in MAXScript loops in a variety of convenient ways, for example in combination with pathnames.
As you recall, each object created in 3ds Max is assigned a pathname in the object hierarchy. This is where the concept of a collection becomes convenient. You can consider all objects of a given type as a MAXScript collection of those objects. You can perform operations on each object in a collection by looping with a for loop, but there is an easier way—you can use wildcards.
Keep in mind that it is not necessary to provide a name or reference for each object that is created.
To use collections versus arrays:
1. Reset 3ds Max, and clear the Listener.
2. Create two teapots by any means. Allow 3ds Max to assign the default names; do not rename them.
3. In the Listener, type the following:
coll = $teapot*
arr = coll as array
The Listener shows you that the array consists of two teapots. The syntax as array is similar to as string, which you used earlier. The statement coll as array converts, or casts, the collection coll to an array.
4. Select and delete one of the teapots in your scene.
5. In the Listener, type and evaluate the following:
arr = coll
The Listener returns $$objects/.../teapot*.
The collection variable coll was automatically updated when you deleted the teapot.
You did not have to do anything special in your script. Likewise, if you create another new teapot, coll is updated internally.
Structures ■
41
6. Reset 3ds Max, and create two teapots again. Type and evaluate the following in the Listener:
coll = $teapot*
arr = coll as array
7. Delete one of the teapots, and type and evaluate the following in the Listener:
for i = 1 to arr.count do messagebox arr[i].name As you might expect, you get an error.
Once the array is created, it exists independently of the collection. If you delete a scene object, the array count does not change, nor do the values in the array. If you try to index through the array, you will be attempting to access properties of objects that no longer exist. If there is a possibility that objects in your array can be deleted, then simply construct the array again before using it.
8. Alternatively, you could use the isDeleted function to find out if an object has been deleted.
9. Type and evaluate the following into the Listener:
for i = 1 to arr.count do (
if not isDeleted arr[i] then messagebox arr[i].name )
You do not get an error with this code.
Note: You can use the $ character to denote the currently selected object. For example:
$.name
This statement returns the name of whatever is currently selected.