Reference Expressions
=====================

A *reference expression* is a form of parameter expression that can be
evaluated without the overhead of a Python interpreter. These types of
expressions are particularly useful when building custom SuperTools where
performance is key. Reference expressions can be added using the usual
parameter expression user interface, and are identified by the first character
of the expression being either ``@`` (for a node reference) or ``=`` (for a
parameter reference)

Node References
---------------

Parameter expressions beginning with ``@`` evaluate to the text following the
``@``. The text is considered to be the name of a node, and Katana retargets
node references when a referenced node is renamed.

Parameter References
--------------------

Parameter Expressions beginning with ``=`` are used to retrieve the value
of another parameter. The general format of a parameter reference is:

1. A ``=`` character
2. An optional ``/``-terminated target node specifier
3. A target parameter specifier

If a target node specifier is not given, the target parameter is looked up on
the current node, i.e. the node that owns the expressioned parameter.
Otherwise, the target node specifier can take one of three forms:

* The name of a node followed by ``/`` looks up the target parameter on the
  node with the given name.
* At least one ``^`` character followed by ``/`` looks up the target parameter
  on an ancestor (enclosing) node. Each instance of ``^`` moves up one
  ancestor.
* ``~/`` looks up the target parameter on the current node. This is equivalent
  to omitting the target node specifier.

The target parameter specifier can take one of three forms:

* A dotted path to the target parameter looks it up relative to the root
  parameter of the target node.
* At least one ``^`` character followed by ``.`` and the dotted path looks up
  the target parameter relative to an enclosing group parameter. Each instance
  of ``^`` moves up one parameter ancestor.
* ``~`` looks up the target parameter using the same path as the expressioned
  parameter. To avoid cyclical expressions when using this form, ensure that
  the target node specifier points to another node.

Parameter Reference Expressions with string values also support the use of
string literals and concatenation using the ``+`` operator.

* A string literal must be surrounded by either single- or double-quotes, for
  example ``"literal"`` or ``'literal'``.
* If quotes are required in a string literal, they can be escaped with a
  backslash, for example ``"this is an \"example\""``.
* If a backslash character is required in a string literal, it must be escaped
  with another backslash, for example ``"\\"``.
* Strings may be concatenated using ``+``, for example
  ``"prefix_" + user.static1``.
* Parameter Expressions may be build from a combination of string literals and
  parameter reference terms using the previously defined syntax.
* There is no limit on the number of strings that may be concatenated.

See the table below for examples of Parameter Expressions using literals and
concatenation.

Examples
~~~~~~~~

In these examples we assume the node graph consists of two Group nodes -
"GroupOuter" and "GroupInner", where the former encloses the latter. Both
of these nodes have user parameters set as follows::

    GroupOuter
    `-- user
        `-- static1 = "foo"

    GroupInner
    `-- user
        |-- static2 = "bar"
        `-- expr1

To reference the "static1" parameter from "expr1", we could use either of the
following:

============================  =================================================
Reference Expression          Equivalent Python Expression
============================  =================================================
``=GroupOuter/user.static1``  ``getNode("GroupOuter").user.static1``
``=^/user.static1``           ``getParent().user.static1``
============================  =================================================

To reference the "static2" parameter from "expr1", we could use any of the
following:

============================  =================================================
Reference Expression          Equivalent Python Expression
============================  =================================================
``=GroupInner/user.static2``  ``getNode("GroupInner").user.static2``
``=~/user.static2``           ``getNode(self.getNodeName()).user.static2``
``=user.static2``             ``user.static2``
``=^.static2``                ``getParamRelative(self, "../static2")``
============================  =================================================

In this case, both "static1" and "static2" are string parameters, so may be
concatenated with other values:

=========================================  ==================================================
Reference Expression                       Equivalent Python Expression
=========================================  ==================================================
``=GroupInner/user.static2 + "_suffix"``   ``getNode("GroupInner").user.static2 + "_suffix"``
``="prefix_" + user.static2``              ``"prefix_" + user.static2``
``="first" + "_" + "second"``              ``"first" + "_" + "second"``
``=^/user.static1 + user.static2``         ``getParent().user.static1 + user.static2``
``=user.static2 + "\\" + ^/user.static1``  ``user.static2 + "\\" + getParent().user.static1``
=========================================  ==================================================

Graph State Queries
-------------------

Graph State Variables
~~~~~~~~~~~~~~~~~~~~~

|sparkles| **New in Katana 4.5v1**

Graph State Variables can be queried using the ``$`` token followed by the name of the Graph State Variable.

This functionality is equivalent to `getVar() <PythonExpressions.html#getVar>`_ in Python Expressions, though limited to
string values.

Examples:

=========================================  ==============================================
Reference Expression                       Equivalent Python Expression
=========================================  ==============================================
``='/root/world/geo/shape_' + $shape``     ``'/root/world/geo/shape_' + getVar('shape')``
=========================================  ==============================================

Frame Time
~~~~~~~~~~

|sparkles| **New in Katana 4.5v1**

The ``#`` symbol is used to query the integer frame time of the Local Graph State. If Local Graph State is not
available, it falls back to the Global Graph State.

Consecutive ``#`` symbols can be appended for padding the value with zeros.

This functionality matches the value that `getFrameTime() <PythonExpressions.html#getFrameTime>`_ in Python Expressions
returns, with the exception that the value is rounded down to the nearest integer toward negative infinity.

Examples:

=========================================  =======================================================================
Reference Expression                       Equivalent Python Expression
=========================================  =======================================================================
``='/media/show/house_' + #### + '.abc'``  ``'/media/show/house_' + str(int(floor(frameTime))).zfill(4) + '.abc'``
=========================================  =======================================================================

.. |sparkles| unicode:: U+2728