Expression Columns
In Harmony, you can use expressions to automate the calculation of effect values based on the values in another function. An expression is a mathematical formula that allows you to manipulate the value in the source function to create new values for the destination effect.
For example, in a scene with two characters, one is walking across the stage and the other is following the same path two steps behind. Without expressions, you would have to manually enter the values for the position of the peg to be one frame behind the original element. However, you can save time by building an expression that does it for you. Then, if you change the position of the element in the original column, Harmony automatically updates the Expression columns linked to it.
When you want to create an expression for an effect, you must add an Expression column to the Xsheet view, build the expression and then link the Expression column to the parameter you want to control.
Writing Expressions
Expressions are based on a JavaScript (JS) program. You can access the full capability of the JS language and write any type of program, as long as it executes relatively quickly.
The entire JavaScript must be defined within the expression code. There is no common repository of JS functions and services available to the expression column scripting environment. However, with the Harmony C++ SDK, you can extend the API of functions available to the expression scripting environment.
If you're working with an old project that contains expressions, they are converted to a JS program. Only simple expressions are updated. Complex expressions and expressions using non-ported services cannot be converted. For these type of expressions, you must convert them manually.
Expression Dialog Box
The Expression dialog box is where you write expressions. It's a simple text editor that can handle incomplete or invalid JS programs although they will not be evaluated. Harmony can save and load invalid JS programs.
The Expression editor evaluates the current script at the current global frame and reports any errors or returns the numerical result of the program.
Expression JavaScript Program
An expression JavaScript program can be any valid program. The only requirement is the last statement of the script must leave a number on the stack. The “return” statement is NOT needed as the script is not a function.
Valid Expression Column JS Program
Example 1
10
This is a simple program returning 10.
Example 2
currentFrame
This is another simple program returning the current frame. The variable “currentFrame” is one of the predefined variables and services available.
Example 3
value( “MyBezierFunction”, currentFrame - 1 );
A simple expression program that returns the value of the Bezier function “MyBezierFunction” at the previous frame. If this function does not exist in the scene, the expression column will be blank in the Xsheet. If this function does exist, the expression column will show the value of that function at the frame.
Example 4
This programs evaluates the Fibonacci series starting at the current frame. The value will be computed up to a certain frame. After that frame, the program is too complex and will be stopped by the engine before finishing.
Errors
Programs that take too long to execute, that don't generate a numerical value, or has syntax errors will not be compiled and will not compute a value. The scripting editor will show the condition that triggers this, but the Xsheet will display a blank field.
API
Using Column Names and Frame Numbers
To refer to the values in a column, use the column name and frame number. If you do not state the frame number, then Harmony uses the value of the current frame. You can refer to the frame numbers in the following ways:
• | currentFrame: Refers to the current frame number. |
• | numFrames: Refers to the total number of frames in a scene. |
Consider the expression: value ( “peg x”, currentFrame-1)
• | This expression says that the current frame value will be the same as the previous frame value of the element peg x. |
Now consider this expression: value ( “peg_angle”, currentFrame - 2] * 3
• | In this expression, Harmony is to look two frames before the current frame in the column "peg_angle" and multiply the value by 3 to derive the value for the current frame of the expression column. |
Predefined Functions
Most mathematic functions are obvious. They either take an angle or value, or return an angle or value. Angles are always specified in degrees. If the input argument is not valid, the function will log an error (which is visible in the script editor) and the Xsheet does not display anything.
The two variants of the function value() are used to get the value of 2D functions at the current frame or the specified frame. The first argument is always a string that identifies the function. The optional second argument is the frame to use.
For example: value( “myFavBezier”, currentFrame-1)
Function | Description |
sin (angle) | Returns the sinus from the angle specified in degrees. |
cos (cosine) | Returns the cosinus from the angle specified in degrees. |
tan (angle) | Returns the tangent from the angle specified in degrees. |
asin( v ) | Returns the arcs in degrees. |
acos( v ) | Returns the arccos in degrees. |
atan( v ) | Returns arctan as an angle in degrees from the first quadrant. |
atan2( x, y ) | Returns the arc tangent in degrees. |
int | Returns the integer value of the “v”. Undefined behaviour for negative number. |
ceil( v ) | Returns the next integer greater or equal than “v”. |
floor( v ) | Returns the integer value of v. Remove the fractional part. |
abs( v ) | Returns the absolute value. |
sqrt( v ) | Returns the square root for v >= 0. |
exp( v ) | Returns the “e” exponent v. (see c library exp( f )). |
ln( v ) | Returns the natural logarithmic of v for v > 0. |
ln | Logarithm of a value. |
value( columnName) | Value of the function specified by “columnName” at the current frame. |
value(columnName,frame) | Value of the function specified by “columnName” at the frame specified by “frame”. |
column( columnName ) |
Indentify the text wrapped by columnName to be renamed whenever the column named “columnName” is renamed. column() is a keyword that does nothing at runtime, but helps Harmony track which references to a function needs to be renamed in the script when a function is renamed. For example, if you have a function named “B” and this one gets renamed to “C” through some scripts or by the user, all expression scripts referencing “B” will automatically be updated to refer to “C” if their call was wrapped as column( “B” ). |
node( nodeName ) node( nodeName ) |
Identifies a node/node that is in the same group as another node which is using this expression column. node( nodeName) and node( nodeName ) are two functions that return a proxy to a node that must be in the same group as another node using that expression column. For this method to work, the expression must be connected to a node “A” and the script must refer to a node “B” in the same group as node “A”. The resulting object is a proxy to a node which cannot be converted to a number. This proxy object is only usable by an SDK plugin. |
numFrames | A constant that represents the number of frames in the current scene. |
currentFrame | A constant that represents the current frame (1 based). |
Building an Expression for an Effect
- In the Xsheet view menu, select Columns > Add Columns or press Shift + C.
The Add Column dialog box opens.
- In the Name field, type a name for the column.
- From the Type menu, select Expression and click OK.
- Double-click on the column's header to open the Expression dialog box.
- Type an expression in the dialog box.
- Click OK or Apply to activate the expression.
The cells in the Expression column are filled with values based on the expression you created.
- To apply the values in the Expression column to an effect, link the Expression column to the parameter values. In the drawing's layer properties, link the function to the new Expression column.