PYTHON EXTENSIONS 101

Creative Programming
TouchDesigner

Python extensions in TouchDesigner, as the name implies, is a way to extend the functionality of our Component operators. With extensions we define and call our own functions which is a key factor for writing clean and easy to read code, design larger systems, and reuse our code in different projects. If you are familiar with Python in TouchDesigner (for example, using execute operators for triggering code), you will probably find easy to start using extensions.

Python Extensions:

  • Clean code with functions, key for collaboration and sharing project files
  • Abstract functions can easily imported in different projects, reusable code
  • Easier to design more complex networks

If you plan to build a project with a modular approach, meaning that you want each of your Components to complete a specific unique task, writing extensions will help you a lot and save you time and effort. On the other hand, writing extensions for everything is for sure not ideal! If you want to execute a few lines of code and don't care about the three bullet points above, you don't have to define custom functions for every line of code.

Every Component operator has an Extensions page. That means that every Component operator can hold its own classes and functions. TouchDesigner helps us create a default extension code from the Component Editor.

Let's create a Base COMP named base_comp, and open its Component Editor. By writing an extension name (myClass) and clicking Add, TouchDesigner automatically creates a Text DAT inside our COMP and fills the Extension Object parameter in the Extensions page, linking in that way the Text DAT (the extension code) with the COMP. Also, inside of the extension, TD creates a class with the name given (myClass):

In case you want to change the name of the class or the name of the Text DAT that holds the class it is useful to show the name dependencies:

By opening the Text DAT in a code editor the default class definition looks exactly like this:

Let's assume that we want to create three custom parameters for our COMP functionality, Param 1, Param 2 and Param 3. We create these parameters only for showing a good practice of using them inside the extension below:

Now let's re-organize the extension code to clarify what TD gives us as a default extension:

The first two lines of code are used for importing two modules; for storing items in the Component and using Properties (explanation below). If you want to store python variables into the Component or you want to use Properties leave these two lines as they are.

Next, we have our class definition. Inside the class we we always need to have the __init__ function and after the __init__ function out custom functions. This function is where all initialization happen and it's called when:

  • We open the project that holds the extension
  • We modify and save the extension
  • When we drag n' drop the COMP with the extension into a project

Also, we have to pass as an argument the ownerComp (or whatever name you give) into the __init__ function. This is necessary because we are passing the Component that holds the extension with the code that was automatically written in the Extension Object parameter of the Component (op('./text_myClassEXT').module.myClassEXT(me)) with the word me.

For good practice, we can divide the __init__ function (also called the constructor of the class) into sections; First, we have a section for our COMP and parameter definitions. This is useful because we can reference the parameters and the ownerComp from our functions by only typing self. and the name of the parameter. The word self is not a keyword in Python, it's not necessary. We use it to increase the readability of our code. Every time we see it it means that the variable that is following is part of the class and not from anywhere else.

Attributes & Properties

Attributes and properties are variables that are shared to all our functions and are reset every time the extension initializes. If the attribute or property stats with capital letter it can be accessed from outside the extension as well.

For example, the attribute B can be referenced in the Evaluate DAT while the attribute b cannot:

What is the difference between attributes and properties? The difference is that the attributes can hold a dependable flag while the attribute cannot. To understand dependency let's see an example.

We have initialized an attribute B with the value 1, and a property MyProperty with the value 0. Inside our custom function PromotedFunction we make two new assignments for the attribute B and the property MyProperty. Let's reference B and MyProperty into a Constant CHOP:

Let's run our custom function PromotedFunction using a Text DAT. We see that B did not change when we run the function, but MyProperty changed. If we now force cook the Constant CHOP, then the value 100 is replacing the value 1.

This is difference between attributes and properties with dependable flag True. Properties will automatically update any references in our network when we run our extension code, while attributes won't.

Storage

The last section is the storage. We can store python variables as attributes or properties (int, float, list, dict) using the StorageManager method. Here is the simplest example of initializing an item to store (we don't know if it's the type) which then we assign a list with the function PromotedFunction:

Conclusion

That was all theory about extensions in TouchDesigner. By using custom parameters together, creating your own function and call them, you can make your own custom functionality of your components and start to write clean, readable and reusable code. To see the extensions in practice, here are some videos and documentation to help you get started:

Extensions

TouchDesigner 202 Berlin, Custom Parameters, Python and Extensions

Building a MoviePlayer - TouchDesigner 202 Workshop Berlin 15th of December 2018

Python In TouchDesigner with Noah Norman

Written By
Vassilis Malamas
SHARE