The struct object constructors in the language takes positional argument initializers as well as keyword initializers. The elements of the new struct are filled-in in order from any positional arguments and then by name from any keyword arguments.
For example, given the following struct definition,
struct foo (name, age, height, hair="brown")
you can create instances, in several ways:
f1 = foo "bill" 23 72 -- fills in name, age, height in order
f2 = foo age:45 name:"sam" -- random named initializers
f3 = foo "mary" hair:"red" -- first name, then keywords
You can now create your own structured objects in MAXScript using the new 'struct' definition construct. This lets you define the layout of new 'classes' of compound objects that you can then create and work with. For example,
struct person (name, height, age, sex)
defines a new 'person' class. You create values of this class using the 'person' constructor:
bill = person name:"Bill" height:72 age:34 sex:#male
joe = person name:"Joseph" sex:#male
You access structured objects using the standard property accessing syntax in MAXScript:
bill.age -> 34
joe.age -> undefined
joe.age = bill.age - 4
...
The classOf() function returns the struct class when applied to these objects:
classOf bill -> person
MAXScript further provides simple exception-handling. This takes the form of some new syntax, similar to C++ exception-handling, that lets you bracket a piece of code and catch any runtime errors in it, as follows:
try <protected_expr> catch <on_err_expr>
The <protected_expr> is executed and any errors that occur are trapped and the <on_err_expr> is executed. If there are no errors, the catch expression is not executed. This is a very simple error-trapping scheme, limited heavily by the fact that you cannot get at any error codes.
try
(
f = openFile "foo.dat"
while not eof f do read_some_data f
close f
)
catch
(
messageBox "bad data in foo.dat"
results = undefined
close f
)
In this example, any errors in reading or processing the data in the read_some_data() function are trapped and a message box is displayed and a some cleanup done. This is a good example of a use for the simple error-trapping.
There is also a new associated function, throw(), which can be used to generate your own runtime error, pass on an error that you've caught when doing some interim clean-up, or to do a non-local jump. It has the form:
throw <error_message_string> [<value>]
throw ()
Calling throw with error message arguments will cause a runtime error to be signaled and, if you have no intervening catches in your scripts, will stop the currently running script. MAXScript will then report the error message using its standard error reporting. The optional second argument can be any value you want printed with the error message, perhaps the object involved in the error.
If you want to catch an error, perhaps to do some cleanup processing, and then pass the error on to outer handlers or MAXScript for error reporting, you can call throw() with no arguments. This throws the current error again and so must only be done inside a catch expression.
Added a case statement to the MAXScript language. It can be used to select an expression to be evaluated from a set a labeled expressions based on a test value that is compared against the labels.
The syntax is:
case [<expr>] of ( <cases> )
where <cases> is a sequence of labeled expressions:
<factor>: <expr>
For example:
new_obj = case copy_type.state of
(
1: copy $foo
2: instance $foo
3: reference $foo
)
The expression with the label that matches the test expression is evaluated. All labels must be comparable to the test expression. Labeled expressions can, of course, be block expressions, so you can use the case expression as a case statement, choosing between blocks of code to execute. A special label, default, can be optionally used to tag the expression that will be evaluated if none of the other labels match the test expression.
The labels are <factors>, elements such as number literals, name literals, string literals, or variables. You can use an arbitrary expression as a label by surrounding it in parentheses. When a case expression is evaluated, the test expression is evaluated once, then each label expression is evaluated in order until one is found that compares equal to the test expression value. The expression it labels is then evaluated and this becomes the result of the whole case expression. No further labels are evaluated or tested.
The test expression is optional. If it is not supplied, the labels are expected to all be boolean values or expressions, and the first label that is evaluated as true determines the chosen case. In this variant it is common to use expressions as labels, so be sure to parenthesize them, for example:
case of
(
(a > b): print "a is big"
(b < c): print "b is little"
(c <= d *3): ...
default: ...
)