Skip to content

Expression backward compatibility

In release r27.10, a number of backwardly-incompatible changes were made to the expressions system. This page provides a reference for any projects which used expressions (specifically variable assignment) before that release.

r27.10 changes

  • Expression variables are cleared at the start of every frame. This ensures that variables are never stale values from other parts of the timeline or the results of previous frames evaluation.
  • It is no longer possible to redefine a variable multiple times within the same frame - this is now an error and the expression error will inform you which object defined it earlier in the frame.
  • Expressions are no longer case-insensitive - variables, fields and functions are looked up in a case-sensitive manner, and the identifiers test and Test are different.
  • Expressions which format strings now require a format:: prefix (which is automatically added during upgrades of previous projects, and added when dragging arrows to populate expressions.)
  • It is now possible to call functions on Resources within expressions. This is an advanced feature and not intended for normal use. For example you can use the expression track:track_1.sectionToBeat(1) to return the time in beats for the second section on track 1. These functions are not documented due to the internal and potential for change in future.

Handling undefined variables

The most-impactful change described above is the change to the lifetime of variables. Previously, it was possible to define a variable at the start of an early checkout track and leave it active for the rest of the show run. This was dangerous for a number of reasons, including stale data, extra latency, failure if machines left & rejoined the session, etc.

To work around cases where variables were used this way, Disguise recommends the following:

Using an expression variables device

Expression variables devices define variables and ensure they are always available. This is useful to ensure the variables are always available, but for dynamically changing values, this can pose some issues. To get started, create an expression variables device.

  • For static values, select the type (usually float) and enter the desired value.
  • For dynamic (e.g. externally controlled) values, select the function type, and enter the expression which controls the dynamic value. Everywhere the variable was previously used, it now needs to be called (since it is a function.) i.e. myvar becomes myvar()

Using an expression variables layer

Expression variables layers define variables for the duration they exist on the timeline. This can be easy to work with in a multi-transport or a single-track show during the upgrade process. To get started, create an expression variables layer.

Expression variables layers need to be below all uses of the variables in the composition stack.

The variables are only available while the layer is under the the playhead.

Updating existing assignments in other layer types

Variable assignment continues to work, but care must be taken to ensure the variables are defined before they are used.

Variables are defined in layer composition order, and from top to bottom in field order within each layer. Therefore a layer which uses a variable which it defines itself must define that variable in a field closer to the top of its layer editor.

Note composition order is bottom to top for Layers and Transports (when using multi-transport.) Within layers, the fields are evaluated top-to-bottom.

In addition to the changes to the core expression system, the new expression variables layer and device was added. This allows you to:

  • Create any number of groupings of global variables within multiple expression variable devices within the device manager. These variables will be available across all timelines.
  • Create time-dependent variables using any number of expression variable layers on tracks. The variables are available to layers above the expression variable layer in the compositing order.
  • Create string variables which contain predefined text values which you want to refer to elsewhere.
  • Create float variables which contain predefined numeric values which you want to refer to elsewhere.
  • Create function variables which can be called using myVariable() calling syntax, which are evaluated at the point they are called at, to provide shared expression logic.