<< Click to Display Table of Contents >> Navigation: Advanced Features > Scripting > Advanced Scripting > Variables - Advanced Documentation |
What is a variable?
A variable is a scripting token that allows you to access a value using a custom name of your choice.
Examples:
//assign 1.23 to a global variable name Variable1
Variable1 = 1.23
//define a local variable named MyName and assign the value John
Set MyName = John
There are several types of variables within Vertex that differ in the way they are created, assigned, or used.
•Global variables are managed just like other so-called “core objects”: they can be created via the Create menu and are listed in the Project Explorer where they can be organized into collections or selected for editing in the Inspector.
•The generic name of global variables in the Project is “Variable”.
•The value of a global variable is synchronized between alle Session Members, just like the properties of other core objects.
•This is called a “global scope” because the variable’s value can be accessed/shared globally between all scripts and Session Members. In contrast to “local scope variables” that are only accessible within the script for which they have been defined.
Global variables cannot be created within a script, they must be added to the Project manually. Once they have been created, they can be accessed as follows:
Assumptions: Project contains Variable1 with the custom name “MyValue”, Variable2
//assign a value using the `Value` member of the Variable object:
Variable1.Value = First Value
//assign a value using the shorthand-syntax
Variable2 = Second Value
//log the value using the full syntax
Log Variable1.Value
//log the value using the shorthand-syntax
Log Variable2
//assign the value using the custom name and the full syntax
MyValue.Value = First Value Override
//log the value using the custom name and the shorthand-syntax
Log MyValue
The value of a global variable is essentially always a String because it must be synchronized between Session Members and be easily editable in the Inspector – it cannot contain a reference to a core object, e.g. Sequence.
Every value assigned to a global variable will be converted to its String representation – in the case of a Sequence, the sequence’s name. Consider this example:
Assumption: Project contains Sequence1 with the custom name “MySequence”, Variable1
Variable1 = Sequence1
Log Variable1
Output:
MySequence
While object references cannot be resolved, several other “value types” can be converted to Strings and back again. This includes but is not limited to Numeric, Json, Array and Dictionary values.
Notes for upcoming chapters:
•Global variables can be used in Indexers because their value is available during the pre-processing stage of a Script in which the Indexers are evaluated.
•Global variables support type-specific features by using the “As…” members of the variable.
Local variables are variables that are defined within a script and that can only be used/accessed during the execution of that script.
Local variables are defined using the `Set` method:
Assumption: Project contains Sequence1 with the custom name “MySequence”
//define a local variable and assign a value
Set MyVar = 1.23
//change the value to string
MyVar = Example Text
//assign Sequence1
MyVar = Sequence1
Log MyVar
Output:
MySequence
In contrast to global variables, local variables are not restricted by their String representation: local variables can reference any type of object; when the value is consumed it will be converted if and as required.
In the above example, using `Set`, a local variable is declared without specifying a type. Later, Sequence1 is assigned to the variable and the value is logged: the result is “MySequence” which is the default string representation of a Sequence (custom or default name).
It is also possible to specify the type using one of the `Set` members as in this example:
Set.Text a = 0001.23000
Log a
Set.Numeric b = 002.3400
Log b
Output:
0001.23000
2.34
As you can see, specifying the type during declaration changes the way the value is parsed and stored.
Local variables declared with a specific type will always convert all input into that type (if possible) and return a value of that type. These variables also have type-specific members, e.g.:
Set.Text a = 0001.23000
Log a
Log a.Contains 23
Set.Numeric b = 002.3400
Log b
Log b.Ceiling
Output:
0001.23000
True
2.34
3
Local variables are available within the scope of the script once they have been defined. If used before, they will be parsed as literal values as shown here:
log a
set a = 123
log a
Output:
a
123
Notes from upcoming chapters:
•Local variables cannot be used in Indexers because their value is not available during the pre-processing stage of a Script in which the Indexers are evaluated.
•Local variables declared without a specific type support type-specific features by using the “As…” members of the variable.
•Local variables declared with a specific type only support the type-specific features of that type.
Script Parameter Variables are variables with a „slightly larger than local” scope: they are only valid within the script for which they are defined, but are initially set from the outside – via parameters that are passed to a custom Script.
Once the parameters have been defined for a Script, the associated variables can be used just like normal local variables that were defined without a specific type.
Script Parameter Variables are only available for custom Scripts that define one or more parameters. This can be done in the Inspector when inspecting a custom Script or in the Script Editor: when the script is selected, an input box for specifying the parameters is shown in the status bar at the bottom of the editor.
Consider the following when defining parameters:
•The parameters are entered into a single-line text input box, with multiple parameters separated by a non-word character, e.g. space, comma, semicolon.
•The names are case-insensitive (as all script processing is).
•You can enclose a parameter name in double-quotes to declare the parameter will not be parsed, but instead used as a literal string; see the output in the following example:
Script1, without parameters:
Set V1 = 1.234
Set V2 = 5.678
Script2 V1, V2
Script2, with parameters "Para1", Para2:
Log Para1
Log Para2
Output when running Script1:
V1
5.678
Due to the first parameter being defined by a name in double quotes, "Para1", not like Para2, the parameter (here: V1) is not parsed, but used as a literal for the value of the script parameter variable.
Notes from upcoming chapters:
•Script parameter Variables can be used in Indexers because their value is available during the pre-processing stage of a Script in which the Indexers are evaluated.
•Script parameter variables support type-specific features by using the “As…” members of the variable.
Certain value types are supported by offering type-specific methods and properties for evaluating or modifying values because, e.g., a method for splitting strings is not useful for numeric values.
These are the types currently supported:
Array |
several items that can be accessed by the 0-based-index position within the items. |
Dictionary |
several key-value-pairs, i.e. values that can be accessed by their associated key. |
Json |
a JObject or JArray instance. |
Numeric |
a numeric value; internally stored as `double`. |
Url |
a string that represents a Url (http://...). |
Xml |
a string that represents a Xml element. |
As described before, these types can be assigned when declaring a local variable as also shown in this example:
Assumption: Project contains Sequence1 with the custom name “MySequence”, Sequence2
set.Array a = Sequence1, Sequence2
log a
set.Dictionary d = one:1,two:2,three:3
log d
set.Json j = {"Name":"John", "Age":23}
log j
set.Numeric n = 0123.456000
log n
set.Text t = 0123.45600
log t
set.Url u = http://www.google.de/search?q=ioversal
log u
set.Xml x = <root><item id="1"/><dawg test="3"/> <item id="2"/></root>
log x
Output:
MySequence, Sequence2
one: 1, two: 2, three: 3
{"Name":"John","Age":23}
123.456
0123.45600
http://www.google.de/search?q=ioversal
<root>\r\n <item id="1" />\r\n <dawg test="3" />\r\n <item id="2" />\r\n</root>
Note how converting the values to loggable strings effects the output:
-Sequence1 is logged as “MySequence”.
-Numeric types do not store leading/trailing zeros.
-Text type maintains leading/trailing zeros.
-Xml elements are formatted when serialized.
For local variables without a specific type or global variables there are helper methods that convert the value to the required type and offer the same methods as type-specific local variables, e.g. “AsJson”:
set.Json a = [{"Name":"John", "Age":23}, {"Name":"Bob", "Age":24}, {"Name":"Pete", "Age":20}]
log a.Get 0/Name
log a.Get 0/Age
set b = a
log b.AsJson.Get 1/Name
log b.AsJson.Get 1/Age
Output:
John
23
Bob
24
Local variables that do not have a specific type, including Script Parameter Variables, offer a helper method, DynamicValue, for accessing members of the value referenced by the variable:
Assumptions: Project has Sequence1 with ClipContainer1
set s = Sequence1.ClipContainer1
log s.DynamicValue.Opacity
set p = Sequence1.ClipContainer1.Transform.Position
log p.DynamicValue.X
log p.DynamicValue.Y
log p.DynamicValue.Z
As you can see, you can assign any object or property to a local variable and then access that instance using `DynamicValue`.
Notes from upcoming chapters:
-DynamicValue is often used when working with Loops.
Consider these examples that demonstrate the difference between local variables (incl. script parameter variables) and global variables.
Example1: Storing a core object in a global.
Assumptions: Project contains Variable1, Sequence1
Variable1 = Sequence1
Set s = Variable1
//since the dynamic value cannot be resolved for the string stored within Variable1, the literal expression will be logged
Log s.DynamicValue.AudioOffset
Set s = Sequence1
//the dynamic value can be resolved because a local variable can reference the actual object
Log s.DynamicValue.AudioOffset
Set s2 = s
//the dynamic value can be resolved because a local variable can reference the actual object
Log s2.DynamicValue.AudioOffset
Output:
s.DynamicValue.AudioOffset
0
0
The above example demonstrates that an object reference cannot be stored and retrieved from a global variable: when assigning Sequence1 to Variable1 only the string representation is stored – and this is not converted back to an object when being used.
During the processing of `Set s = Variable1` the assignment expression (`Variable1`) is parsed resulting in the stored string (“Sequence1”). A recursive/nested parsing of the string result is not done at this point.
Example2: Storing a Dictionary in a global variable.
Assumptions: Project contains Variable1
//the expression is parsed and stored as an actual dictionary
set.Dictionary d = a:1,b:2,c:3
//a string representation of the dictionary is stored
Variable1 = d
//an actual dictionary is parsed from the value
set.Dictionary d2 = Variable1
log d2.Count
//the actual value is maintained (not converted) when assigning to an unspecific local variable
set d3 = d2
//use the AsDictionary member to access the methods for this type
log d3.AsDictionary.Count
Output:
3
3
The above example demonstrates that certain supported types, e.g., a Dictionary, can be converted to and from a global variable successfully.
Enumerable values, represented by Array, Dictionary and JSON have a few special methods that are worth looking into.
Note: Enumerable values are commonly used in connection with Loops (s. below) and the DynamicValue member (s. above). This chapter focuses solely on the special methods available for enumerables.
These methods are Where, OrderByAsc, OrderByDesc, and Select as shown in the following example (details will be explained further below):
Assumptions: Project contains contents RedPng, GreenPng, BluePng
set.Array items = RedPng, GreenPng, BluePng
log items
set a = items.Select i => i.UserProperties.Id
log a
set b = items.OrderByAsc i => i.UserProperties.Id
log b
set c = items.OrderByDesc i => i.UserProperties.Id
log c
set d = items.Where i => i.UserProperties.Id < 33
log d
Output (example):
Red.png, Green.png, Blue.png
34, 32, 2
Blue.png, Green.png, Red.png
Red.png, Green.png, Blue.png
Green.png, Blue.png
What makes these methods “special” is the use of a so-called “anonymous function”, e.g.: i => i.UserProperties.Id
In the Vertex Scripting context “anonymous functions” are nameless, single-line functions that have one parameter and a return value:
•The name of the parameter (that is to be used in the function) is an arbitrary custom name, specified on the left-hand side of `=>`, in the example above: `i`
•The function is defined by the remaining text on the right-hand-side of `=>`, in the example above: `i.UserProperties.Id`
These functions, used by the methods mentioned above, which are all only applicable to variables representing enumerable items (Array, Dictionary, JObject, JArray) are called for each item, assigning the item to the defined parameter (in the example above: `i`) so that it can be used for evaluation. The way, in which the functions are evaluated, and their results used, depends on the method context.
In all cases, the methods do not alter the source variable, but instead return a new enumerable instance:
•Where: The result is expected to be true or false, and only items for which the result was true will be added to the result set.
•OrderByAsc, OrderByDesc: The results (of all items) are used to return a version of the original items, sorted in ascending or descending order, respectively.
•Select: A new Array is created, using the function results as items.
Since the contents of the enumerable variables can be of any (and different) types, the Script Editor cannot offer Code Completion support. All members of the anonymous function parameter (in the example above: `UserProperties.Id`) will be parsed as if they had been amended to the source of the parameter (here: a content core-object).
Note: There are other members (e.g. Count, Take, Skip, ByIndex, ByKey) that also only apply to enumerable variables, but they do not require anonymous functions.