THE POWER OF ITERATION
Before I started to learn python I heard that it can be useful for many aspects of compositing to speed up the workflow and to create all sort of cool/useful things. So I watched my first tutorials about strings, variables, integers, lists, functions...
It was a lot of theory and seemed like this part just never ends.
I stopped learning python because it was exhausting, not getting to the "interesting part".
I started and stopped at least three times until I managed to push myself through the "boring part" and started to see some practical use python as a compositor.
Because of that ( and because I heard a same frustration from others ) I would like to try to help a bit those compositors who wants to learn python but would like to start at somewhere "interesting"! For me For Loops was the first part with the "gotcha" moment when I started to see the real benefits.
For Loops are very common and very efficient ways of dealing with boring tasks.
Obviously, this DOESN'T mean that the theory can be skipped but it might be easier once the benefit of learning is in sight!
My goal here is to pave you a less bumpy road to a place where you can already use the Script Editor to speed up your workflow and where theories will seem less painful when you decide to go deeper into the rabbit hole!
Now, join the dark side and let the python be with you!
The Script Editor
Let's assume that this is your first time using the Script Editor and give you a brief tour!
First, you can find the Script Editor under Windows.
There are more buttons to use at the top of the Script Editor and if you hover your mouse over you will know what each one does but to be honest I only use the Ctrl+Enter shortcut to run the selected code.
TIP: Yes, if you don't want to run all the codes that is in the input window, you can select the part that you'd like to run and that will be the only part that will get interpreted. It also means that if you don't have any parts selected it will run everything that is in the input window.
This is the Preferences setup for the Script Editor that I like to work with so that:
1 I can see how things I do manually translates into python in the output window
2 I like to keep my Script Editor history ( it's stored in the .nuke folder as ScriptEditorHistory.xml ),
and also this way everytime you launch Nuke the input window will have the same content
when you closed it!
Setting value with iteration AKA "for" loop
With For Loops here we iterate through a sequence and apply certain statements on its elements. To put it simply, we apply the same settings on multiple nodes. So let's say that you don't want to set up the same value for 50 nodes. Luckily, you don't need to! It's much easier to write 4 lines of codes that will do it for you!
Okay, let's run some code!
Copy paste the code below to your input window in a fresh Nuke and create some Blur Nodes!
TIP: You can notice that the codes I am sharing has a title but the line starts with the # symbol. It is called commenting and for python it means to skip that line which is useful to leave notes and keep your codes more organized and readable for others.
With running this code you just managed to change multiple Blur nodes size value at once!
Let's try to modify one thing here:
You can see that the allNodes('Blur') got only updated to selectedNodes('Blur')!
Now you need to select some Blur nodes before running the code.
Let's try to modify the channels instead of the size now!
Spot that in order to do that I also changed the values from 5 to rgb and it got quotation marks!
You need to use quotation marks if you use letters instead of digits as values.
Let's try to change multiple values now!
TIP: If you are not sure what's the name of the knob you can hover your mouse over it and a text box appear with the correct name as it isn't always what you see on the node!
Cool! So we can modify now as many Blur nodes as we'd like to at once!
Let's try what happens if we want to modify different type of nodes!
Noticed that for this I just removed the 'Blur' from the selectedNodes's brackets!
So it means I am not specifying what type of nodes I'd like to run the code on.
See what happens if we want set up a value but certain selected nodes doesn't have that kind of knob!
Ouch! We just got our first Error! It says:
# Result: Traceback (most recent call last):
File "<string>", line 3, in <module>
NameError: knob size does not exist
That's very helpful! It tells us that we made a mistake in line 3 and that knob size doesn't exist as Merge and Transform doesn't have a knob called size! Error messages are mostly very helpful for us to find out what went wrong.
Let's see the solution for such problem as you might not always have the luxury to individually select the nodes you'd like to adjust!
Nice! This time no errors! By introducing try/except we are asking to run it on each selected nodes but move on to the next item if it can't complete the task. Keep in mind that it is a handy way of handling such problem but in many cases it is better to get errors in order to find out what went wrong!
Checking the Class
In most places this step will definitely go before the previous one but now you already can set up
basic values on any number of nodes! Yay!
Let's talk about Classes! Every type of nodes are technically a Class for python.
These Classes are expecially useful when you would like to apply certain changes on just one or multiple Classes.
In the previous examples you might noticed that in the first ones we used allnodes('Blur') and selectedNodes('Blur') - By adding the 'Blur' into the brackets we are definining the Class we want to run the code on!
With Blur it is easy to know which node are we talking about but certain nodes has their previous versions in Nuke too so we need to be more careful with them and check the correct Class to make sure that we are modifying the right nodes!
The manual way is to
1 Select a single node
2 Hit "i" ( as for "information")
You can see here that the current Tracker node is already the 4th so calling it looks like this:
But since we are just learning coding let's see how can we check the selected node's Class with python:
Checking the knob's value
Let's assume that you got many assets for a shot and they are ALL in the wrong colorspace. Horrible!
Also assume that the colrospace is a pain to write all down so it's easier to print it out with
using one of these snippets:
Let's say that it is getting boring to always select the nodes you want to check! There's a way to call a specific node by its name to check.
To do this you can see that we needed to replace the selectedNodes() with toNode() and call the node in the brackets!
Since we have already learned how to iterate let's see what happens if you need to check multiple nodes certain value.
Set boolean values
Every node has boolean knobs, but you might be familiar with them as checkboxes.
Let's see how many ways we can set their values!
In practice people mostly use the True / False or 0 / 1 values but as you can see there are
other options too.
Set expression values
Every now and then we need to use some expression and we might even need to set them on multiple nodes. For this we can simply use the setExpression() instead of setValue().
If need some help with expressions you can visit this page.
Connect multiple nodes
Time to time we got a boring task to connect multiple nodes to a certain place, like when making a contact sheet. Let's see how can we do it easier.
Ooookay! A few things has changed here compared to the previous formula so let's go through them:
1 - Our first snippet including Variables which is a SUPER SUPER IMPORTANT concept in python ( and in coding in general ). In the first 2 lines that starts with t = and nodes = we are storing the values with an arbitrary word.
It is very useful if you are running a longer code and want to call for example the selected nodes multiple times but don't want to type nuke.selectedNodes() all the time so now you only need to type nodes instead and python will know what you mean
( as long as the variable defining is part of the code that you are running ).
So it is mostly needed for speeding up the coding workflow and to make codes easier to read, but you are also welcome to write the same code like this:
2 - There is another variable in this code and actually in most of the codes we ran so far! It is called loop variable and before this step we called it node but in this step it is just i which is probably the most common loop variable that stands for iteration and it is quick to call just a single letter.
It is also an arbitrary value and people are usually using a word that makes sense in the given context as we did with node when we were running the task on nodes, but if you feel like that you can also just run it on kittens!
Obviously, I am not recommending to run for loops on kittens and connect them with toys but it gave me a good excuse to include this adorable gif that hopefully helps you to understand variables better and scroll further. ( sorry if not as this gif is really all you need to do so! )
3 - We use a setInput() function here that is - shockingly - set the input of the node but for some reasons in the bracket we have (0, t). It is because depending on how the function was designed it can take zero, a single or multiple arguments (= what you put in the brackets) separated by a comma. In this case we need two to run the setInput(). The first one is the serial number of the input which each input has as most nodes has multiple inputs you need to define which one you want to connect.
Create some nodes
So far we have been playing with nodes that has already been created but we can also use the power of a for loop to create multiple nodes which sometimes just what we need.
There are a few new things here again that is better to get familiar with.
1 Instead of selectedNodes() or allNodes() we run our task on range(5). When you call the range function for python it means a sequence of numbers instead of just the number 5 so it knows that it needs to count them for a task like this.
2 createNode() is a new magic function we are learning which surprisingly creates a node using a Class that you add as argument. ( remember how to check the Class? )
TIP: You can notice that I cheekily used a double quotation to add the "Blur" argument to the function. where as before I used single quotation 'Blur'. The reason is that there is NONE. Python takes both types of quotation marks just as well so it depends on you what you are more comfortable to use.
Now let's imagine that you got a bunch of elements for your shot but they are starting on different frames! You can create a Retime node and copy paste to all of them or just use this snippet.
Hopefully, most of this code is familiar by now but let's go through on the new things.
1 All nodes has a certain position on the NodeGraph which is stored in the xpos and the ypos value. These values are not knobs on the node but you can set their value as such. We needed these to define the position of the Retime nodes. The xpos is the same as the Read node's so it is in the same column but to the ypos we added 200 to place it puts under the Read node. Feel free to put it closer or further if need so.
2 If it made you wonder just how many knobs each node might have ( both that you can and can't see )
that you can modify now there is - again - a snippet for you to check it. You can run it on a single selected node.
You took the first 8 steps to learn python!
I hope that what you learned so far will be good for you to handle some tasks that otherwise would take much longer doing manually!
To carry on with your journey I recommend to start to get familiar with the "boring stuff" too that I hope will be easier to digest. For that Conrad Olson put together a very useful python resources page.
I would also add:
Erwan Leroy / Getting started with Python for Nuke
Gianluca Dentici / Python scripting for Smart and Curious compositor
Andrea Geremia / Python & TCL
There is a LOT MORE that you can do with python to speed up and customize your workflow but the theories can't be skipped if you really want to understand what gives you more power.
Hope you will find it useful!