When writing the code of scripted operators, there are several specific issues to be aware of. These issues are described below.
Restrictions on Scripted Operator Code
Scripted operator code has a few restrictions:
You can only use object model statements. You cannot use scripting commands.
You are restricted to a subset of methods and properties. These are specially marked in the Scripting Reference section of the SDK Guide.
You can only access data for which you have explicitly created a connection.
In general, you cannot do anything that may cause an evaluation cycle. This includes getting the value of a parameter at another frame.
Subroutines, Variables, and Name Collisions
You can use the bottom pane of the scripted operator editor to write subroutines that hold global variables. These subroutines are helper functions you can use to organize your code. You can call them multiple times from your main update routine or from other subroutines.
However, for reasons of speed and efficiency, Softimage maintains only one instance of the scripting engine per language for all scripted operators. This means that if two subroutines or variables in different operators have the same name, then whichever was parsed or set last will be used for both. This is called name collision and can cause incorrect updates or broken operators.
To avoid problems, it's a good idea to prepend your names with a distinctive identifier such as your initials and/or an operator-specific prefix, particularly if you are working with multiple operators, merging scenes, or sharing files with other users. For example:
me_MyDeform_CalculateVals(i_par1, i_par2, o_par)
Different scripted operators can be written in different scripting languages in the same scene. However, you can use only one language within the same scripted operator. The language that is used to parse a particular scripted operator is the language that is set on the Scripting page in the Preferences window when the scripted operator is first created.
You can declare scripting variables that are global to your scripted operator in the bottom pane of the editor. However these variables are available only when your scripted operator is called to update its output connections, so you can't, for example, use them in expressions and so on.
In addition, you may experience problems with name collisions as described in Subroutines, Variables, and Name Collisions. If you need to use persistent data, it may be better to create a custom variable for your scripted operator as described in Adding New Variables and make it read-only. You can still set the value of a read-only custom variable through script commands.
Combining Scripted Operators and Constraints
Like expressions, scripted operators are evaluated before constraints on the same object. If you use the value of a constrained parameter in a scripted operator, you may not get the results you wanted.
For example, suppose you want to write a scripted operator to control an object's orientation based on its position; if the object has a path constraint, the orientation is evaluated before the position is updated at each frame so the operator uses stale values.
To achieve the desired result, constrain an intermediate object like a null to the path, then constrain the object's position to the null. When calculating the new orientation, use the null's position instead of the object's position.
Combining Scripted Operators and Other Animation
You can combine scripted operators with other animation, such as keys and expressions. However, if you make a specific parameter both an input and output connection of an operator and then later animate the parameter, the input connection will retrieve the parameter value from the function curve or expression before it has been updated for the current frame.
Using Enumerated Values in Scripted Operators
Enumerated values defined in the object model are not evaluated properly in scripted operator. Therefore, you should use the integer value directly.
LogMessage "Closed in U: " & bClosed(0)(0) LogMessage "Closed in V: " & bClosed(1)(0)
LogMessage "Closed in U: " & bClosed(siUDirection)(0) LogMessage "Closed in V: " & bClosed(siVDirection)(0)