.. _ogn_tutorial_tokens:

Tutorial 20 - Tokens
====================

Tokens are a method of providing fast access to strings that have fixed contents. All strings with the same contents
can be translated into the same shared token. Token comparison is as fast as integer comparisons, rather than the more
expensive string comparisons you would need for a general string.

One example of where they are useful is in having a fixed set of allowable values for an input string. For example you
might choose a color channel by selecting from the names "red", "green", and "blue", or you might know that a mesh
bundle's contents always use the attribute names "normals", "points", and "faces".

Tokens can be accessed through the database methods ``tokenToString()`` and ``stringToToken()``. Using the ``tokens``
keyword in a .ogn file merely provides a shortcut to always having certain tokens available. In the color case then
if you have a token input containing the color your comparison code changes from this:

.. code-block:: c++

    const auto& colorToken = db.inputs.colorToken();
    if (colorToken == db.stringToToken("red"))
    {
        // do red stuff
    }
    else if (colorToken == db.stringToToken("green"))
    {
        // do green stuff
    }
    else if (colorToken == db.stringToToken("blue"))
    {
        // do blue stuff
    }

to this, which has much faster comparison times:

.. code-block:: c++

    const auto& colorToken = db.inputs.colorToken();
    if (colorToken == db.tokens.red)
    {
        // do red stuff
    }
    else if (colorToken == db.tokens.green)
    {
        // do green stuff
    }
    else if (colorToken == db.tokens.blue)
    {
        // do blue stuff
    }

In Python there isn't a first-class object that is a token but the same token access is provided for consistency:

.. code-block:: python

    color_token = db.inputs.colorToken
    if color_token == db.tokens.red:
        # do red stuff
    elif color_token == db.tokens.green:
        # do green stuff
    elif color_token == db.tokens.blue:
        # do blue stuff

OgnTutorialTokens.ogn
---------------------
The *ogn* file shows the implementation of a node named "omni.graph.tutorials.Tokens", which contains some hardcoded
tokens to use in the compute method.

.. literalinclude:: ../../../../../source/extensions/omni.graph.tutorials/tutorials/tutorial20/OgnTutorialTokens.ogn
    :linenos:
    :language: json

OgnTutorialTokens.cpp
---------------------
The *cpp* file contains the implementation of the compute method. It illustrates how to access the hardcoded tokens
to avoid writing the boilerplate code yourself.

.. literalinclude:: ../../../../../source/extensions/omni.graph.tutorials/tutorials/tutorial20/OgnTutorialTokens.cpp
    :linenos:
    :language: c++

OgnTutorialTokensPy.py
----------------------
The *py* file contains the implementation of the compute method in Python. The .ogn file is the same as the above,
except for the addition of the implementation language key ``"language": "python"``. The compute follows the same
algorithm as the *cpp* equivalent.

.. literalinclude:: ../../../../../source/extensions/omni.graph.tutorials/tutorials/tutorial20/OgnTutorialTokensPy.py
    :linenos:
    :language: python
