TouchDesigner tricks for the new year
To help ring in 2018, I thought it would be nice to share some little tricks that seem to always evade new users. Some of these things can even evade experienced users as they come quickly in new updates and over time it can be hard to keep track of them all. So I rounded up a handful that I use regularly and provide a quick run down of what it is and how to use it.
1. Custom parameters
Custom parameters are one of the best features to come to TouchDesigner in the last few years. We use them all the time to wrap more complex functionality inside of a component with some exposed parameters. The great thing is that any kind of parameter type already available in TouchDesigner can be used for your own custom components. Custom parameters can only be added to components. To get started, make any kind of component (although Container COMP and Base COMP are usually the most common hosts), and then right click on it and select Customize Component…
This will pop up a new window called the Component Editor. The first thing you’ll want to do is make a new parameter page by clicking inside the field to the left of the Add Page button and typing in the name of the page. I usually use something like “Settings” or “Controls”. Once you’ve entered the name, click Add Page. If you look at the parameter window of your component, you’ll see a second row now where your custom parameter page lives. You can click on it and it will be blank for now.
Now you can select the new parameter page on the left side of the Component Editor and begin adding new custom parameters to it. First, I enter a new parameter name just below where we entered the new page name. The drop down to the right of the parameter name field allows you to choose from one of the many types of parameters in TouchDesigner. This ranges from pulse buttons, toggles, to colour pickers and asset selectors that will pop open a Windows explorer window. The drop down to the right of that is a number between 1 and 4, which denotes the amount of values to add to a single parameter for parameters such as Floats or Ints. If you select Int and select 3 from that drop down, you’ll create an integer with 3 parts to it. Let’s make a simple Toggle for now. Select Toggle from the drop down and give it a name and click Add Par. Once you do that, you’ll see the new toggle button added to the parameter page you created.
Accessing this value is extremely easy. Go inside the component and create a Parameter CHOP. By default, it will only pick up custom parameters and you’ll see a single channel with the same name as your custom parameter. You can go ahead and connect this channel to anything you would normally use a CHOP channel for, but in this case you also have created a custom parameter that controls it. Most of the channel based operators can be accessed through the Parameter CHOP, but all of the data parameters (such as file paths or strings) need to be accessed through the Parameter DAT. It works like many of the other callbacks in TouchDesigner in that it has different functions where you add your code based on triggers. To access our same toggle button via the Parameter DAT we would add something like this under the onValueChange() callback:
if par.name == "Togglename": print(val)
This would parse the different customer parameters by name, find the toggle parameter by it’s scripting name (the name written in the box in dark grey when you hover over a parameter for a few seconds), and then prints it’s value.
2. TouchDesigner editor start position
When working on installations with huge displays or multiple kinds of displays, it can be tough to setup your working environment. In this trick, I’m speaking specifically about the network editor, which by default opens up and fills the whole main screen. If you’re using something like nVidia Quadro Mosaic, your whole screen could be any setup or number of screens connected to a single system. If you let TouchDesigner fill up a whole window, it might be too big or it might be too small or it might be covering the wrong screens that you want to work on. Luckily for us there’s a way to set a custom start position and size of editor window. To set this up, go to the Dialogs menu at the top of the screen and choose Window Placement. The bottom portion of this window contains the settings for the network editor. In situations with lots of screens or large setups, I’ll select Custom in the bottom left corner and this will activate the settings in the bottom right corner. You can set the X and Y position (in pixels) as well as the size of screen. Now you can setup your work environment and not have to worry about resizing the network editor every time you open TouchDesigner!
3. Operator snippets
One question I see all the time is “How do I use _____ operator?” Lucky for you, there’s something called the Operator Snippets. This is a project file that contains a myriad examples of many of the most common operators. The project even contains a few example techniques (like instancing and shadows) and some some less-common operators.
To access it, click on the Help menu at the top of the screen and select Operator Snippets. When the project is finished loading, you will see a menu on the left side of the screen that is split into three parts. The first looks like the operator creation menu (the popup when you double click on the network background), right underneath it are a few big buttons with different names, and then under that is a text portion. The section that looks like the operator creation menu is how you navigate between the operators and the different families. For example, you can click on CHOP at the top and then click on Rename in the operator list. The buttons below the operator creation menu will change to show the different examples available for the Rename CHOP. You’ll see rename patterns and check select. You can pick either of the examples and the whole network on the right hand side of the screen will change to show you that example in action. The text just below the example buttons will change to describe the example you’re looking at currently. This is extremely helpful and you can click through tons of different operators looking at all the different examples usages of them.
The best part about the operator snippets is that it is made of real running examples. You can see the example running in real-time, then you can update it or play with it, and most importantly, you can copy and paste it into your own project to continue using it. How helpful is that?
One final thing that a lot of new users miss are the Python examples. There is a simpler version of the Operator Snippets that exists for Python. To access this you go to the Help menu at the top of the screen and select Python Examples. This will similarly open up a new project with a bunch of different components that house many different real Python examples that you can experiment with to learn from.
4. Delay scripts
There are two methods of introducing delays in Python scripts. The first is the one most developers who’ve been using Python know; that is by splitting up their scripts into multiple Text DATs and then using something like:
op('text_dat_name').run(delayFrames = 30)
This would run the next script in 30 frames. At 60 fps, this would run 0.5 seconds later and at 30 fps it would run 1 second later. But what if you need to delay a bunch of quick single line commands, things like clicking on buttons or setting slider values or anything like that. It becomes a huge pain to start making new Text DATs with single lines in them like:
That doesn’t need a whole Text DAT to itself! This is where inline delays come in hand using the runs class and the run class (I know… they’re very similarly named…). The runs class holds a bunch of run commands, but that’s besides the point. How do you use it? Easy.
Let’s say you have a button named button1 and you want to click it 1 second after a print statement and you have slider named slider1 and you want to set it’s value to 0.5 another second after the button gets clicked. Instead of making a new Text DAT for each of these actions you can do something like this:
run("op('button1').click()", delayFrames = 1 * me.time.rate) run("op('slider1').interactMouse(0.5, 0.5, left=True)", delayFrames = 2 * me.time.rate)
Just like that you can add the delays to the scripts right inline next to each other without needing to make new Text DATs. The way this works is that you give it a Python command as a string (that means inside a pair of quotation marks), and then you can give it a delayFrames. You’ll notice in this example I used a trick where instead of specifying the amount of frames to wait, I calculate it by multiplying the time in seconds I want to wait by me.time.rate. This means that if I wanted something to wait for 1 second, it wouldn’t matter the frame rate, it would always calculate the correct amount of frames to wait. One thing to be aware of with this method is you use of double and single quotations marks. I usually wrap my whole statement in double quotation marks (“) because I prefer to write my Python statements with single quotation marks (‘) to denote strings.
You could take it a step farther and feed in variables that are your Python strings, such as:
script = "op('button1').click()" run(script, delayFrames = 1 * me.time.rate)
This is an overly simple example, but it shows you that you can compose the Python expression as a string separately and then just feed the variable to the run command. Since it’s just a string you can also do things like inject variables using string concatenation amongst many other things.
5. Override system hotkeys
This is a “feature” we’ve been using more and more recently. It’s very useful when you have projects that have a lot of keyboard usage while you’re still editing in the network editor. It’s also useful if you plan on creating some new hotkeys for a specific project. System hotkeys include everything from space bar that pauses and plays the timeline, all the up to hitting ‘b’ to bypass/unbypass operators. To get access to these hotkeys, you need to use Windows explorer to get to your TouchDesigner installation path (by default C:/Program Files/Derivative/TouchDesigner099). When here, enter the Config folder and you’ll see TouchShortcuts.txt. This is the file that you want to edit. Open it in your favourite code editor (like Sublime Text) and you’ll see it is a tab separated file with the first column being the command, the second is the key, and the third is the command. Before going any further:
Be aware that hotkeys may be set back to default if you upgrade your build and they only apply to your computer, and not just one project file. You also might create an issue with your TouchDesigner installation. So make a backup of your hotkeys file before you begin editing anything.
With that out the way, you’ll see all of your favourite shortcuts listed here. For example, if we wanted to remove the space bar hotkey that pauses the timeline, you can find this line (near the top):
general.pause space space
and delete it. If you reopen TouchDesigner, you’ll find the space bar won’t impact your timeline anymore and can be used for other hotkeys or for your own programming needs. If you’d like to change a hotkey, you need to find the key that you’d like to replace and enter a new key for it. It’s a bit of uncharted territory and you’ll learn more by just looking around as I don’t know of any documentation for this. If you wanted to mess with someone you could find the lines:
network.dive i network.jump.up u
which control the very familiar hotkeys to move in and out of components. You could switch these hotkeys around to:
network.dive u network.jump.up i
and save the text file. This would flip the buttons and cause some serious confusion for whomever was going to use the system next!
6. Global operator shortcuts
Global operator shortcuts are a great way to access important data from different areas of your network. As you work on larger and larger projects, you’ll begin to find the need to organize and compartmentalize all the different areas and features of the installation you’re building. You quickly find accessing data isn’t as easy as dragging a wire around. You start using more and more select operators and have to start remembering longer and longer paths that lead to important data operators (like the output of Kinect sensors or similar). Something that can save a ton of time in this regard are global operator shortcuts. These only work on components but they can make pathing to important areas extremely easy. For example if you have a Null CHOP operator named KINECT_DATA a few levels deep in your network, something like /PROJECT/INPUT/SENSORS/KINECT/OUT/KINECT_DATA. Accessing this data regularly might become a bit of a pain, and what happens in the off chance that you need to move that Kinect component somewhere else?
To create an operator shortcut for the component that holds your Kinect data, you open it’s parameters and go to the Common page. Here you’ll find a parameter named Global OP Shortcut. Whatever you enter into this field will become the operator shortcut. If you enter Kinect into this field, there are some nifty things you can do now. You can get a dynamic operator link to that component simply by typing:
Too simple?? It really is. op.Kinect can now replace you needing to do something like:
That’s pretty amazing if you ask me. Now back to our original problem, you need to access some data inside of that component, an operator named KINECT_DATA. To this you could use:
If you were to translate this line into plain english, it would read: go to Operator shortcut named Kinect and inside of it, find an operator named KINECT_DATA. The best part about this link is that it’s dynamic. It doesn’t matter where you move the component to, your paths will not need updating or fiddling, everything will keep working as is.
Hopefully these quick tips and tricks will help developers both new and old start off the new year with a bigger and stronger arsenal. Enjoy!