NOTES ON PARENTING
There are different ways to control one node's value from another one in Nuke.
This is a list of as many ways of doing as I could just think of with simplified examples.
Also, because you just don't know when the need for some good parenting skills parades in!
I also wanted to put this tutorial together because very recently we had our
wonderful little baby boy - Teodor!
​
My wife said I should start working on my parenting skills so I thought
working on parenting expressions
would help. 😅
Also, as a personal note wanted to mention our never-ending gratitude for the wonderfully patient & kind midwifes at the Croydon University Hospital!
Anyone who'll meet them, be kind and bring them at least a big box of chocolate for their hard work! 💗
Manually create expression link
1 - Press Ctrl + Right Click on the knob's Animation menu and without releasing it drag and drop it to either on the other knob's where it shows the value (1) or Animation menu (2).
2 - That's it! If you did succesfully you should see the value with a blue overlay which is a sign that the knob is animated ( also that it controlled by an expression ).
3 - You should also see a green line between the two nodes with an arrow that is showing which is a parent and a child node. And also a green circle with an E in the corner of the node that has the expression.
You can also Right click / Edit Expression... on the knob ( or use the = hotkey )
To see that a new value is defined by an expression parent.Blur1.size .
Congratulations! Now you know how to put parenting expression to its place!
Codes that create expression lines between two nodes
These are the codes that you can type in the expression dialog to get another knob's value as a result.
1 - This is what you get automatically following a manual way but it has certain shortcomings when it comes to building a gizmo or a template but more about that later.
parent.Blur1.size
2 - The easiest and the quickest.
Blur3.size
3 - Using the same value function that many using on the label to feature certain results
works here too!
[value Blur5.size]
4 - Using the knob function will feature a value in this case but if you add another value to it like
[knob Blur11.size 20] that will set Blur20's size knob to 20 instead of just show a value.
[knob Blur7.size]
5 - This is a python code using toNode() that requires to switch to python mode on the Expression Dialog by clicking on the Py button.
nuke.toNode('Blur9')['size'].value()
6 - It is a very similar code to the previous one but using a knob function instead of calling a knob as a list item.
nuke.toNode('Blur11').knob('size').value()
7 - Despite that this is a python code you don't need to turn on the python mode but you can tell by typing [python {your py code}] to read it as a python code!
[python {nuke.toNode('Blur13')['size'].value()} ]
8 - It is a very similar code to the previous one but using a getValue instead of the value function.
You can find out more about the differences of value and getValue here!
[python {nuke.toNode('Blur16')['size'].getValue()} ]
Linking channel knobs
In order to link channel knobs you need to click on the Link menu - the little button with
two lines on it - and hit Set link as they don't have animation knob.
You can use a any form of the previous examples, butthis might be the simplest one:
Blur18.channels
When successfully added the code you'll see that the channel knob turned grey and
clicking on the Link menu the options now are Edit link and Remove link.
Useful snippets to deal with Expressions via Python
The following codes can be run from the Script Editor.
Linking with input values
Using the input function to set value from another node doesn't create expression line on the Node Graph which makes it visually more difficult to keep track of. Despite that in certain cases, mostly in templates and gizmos it can still be very useful. But be careful, with this function as it might cause issues when scripts are getting reassigned and the new artists would have a hard time why
certain values vanished when they change something else. So make sure your script is always tidy!
Here are a few more variations that you can use with the input to get the same result.
input.size
[value input.size]
[knob input.size]
[value this.input.size]
Other thing you can do with input is to move up multiple steps!
You need to use as many input. as many nodes would like to move up.
input.input.input.input.translate.x
As a next step let's see what happens if we don't want to move up on the main pipe only!
For this to work you need to add the serial number of the input.
By not using a serial number ( as we did before ) it takes the first which is 0 but you can add the number too if want to.
input.input1.input2.input2.size
Let's see how can we do the same with python. ( Don't forget the Py button )
Notice that by using input() function you need to give an argument ( serial number ) in order to work.
nuke.thisNode().input(0)['size'].value()
We can also move up the node tree using python in a similar way.
Notice that the getting the translate.x value I had to give an argument to a .value() function as that knob holds two values. ( So, it is 0 for x and 1 for y )
nuke.thisNode().input(0).input(0).input(0)['translate'].value(0)
Not so surprisingly, you can also use the .input() argument to switch between inputs.
nuke.thisNode().input(0).input(1).input(0).input(2)['size'].value()
Another useful function here worth keeping in mind is dependencies() which returns a list of nodes that are connected so you can pick the item based on its place on the list.
nuke.thisNode().input(0).dependencies()[-1]['size'].value()
Getting values from the topnode
This is a very useful function in many cases and it's worth knowing few tricks to be able to reach the right topnode in the template!
Also, there's another article I made about TCL functions in general that are performed on the topnode.
So let's start at the beginning here. By simply calling a topnode it goes up on the main pipe.
[value [topnode].size]
Here's one way to choose which input's topnode you are interested in.
[value [topnode input1].name]
You can combine the topnode and the parent functions to choose which input on which node's topnode you are interested in! After all - there can be sooo many nodes on top!
[value [topnode parent.Merge8.input1].size]
Unfortunately, in python there is no equivalent to topnode but as always there are certain ways to get around this issue. The easiest probably is that you can use nuke.tcl() which is the next example.
For more a creative solution I highly recommend to check out Anthony Tan's video on how to re-create the topnode! ( Also to check out his whole py training bcz it is very very useful! )
nuke.tcl("value [topnode].translate.y")
Getting values from outside the Group
Often, when you are working on new gizmos you need to get certain values from outside the Group. Luckily, there are some ways to do that!
​
Probably, the most useful parenting expression in a gizmo is when checking if the input has something connected or not. This is often useful added to the disable knob. This code also contains ! and exists which are conditional expression - you can find out more about those here.
​
When you are using parent.input1 it is looking "above" the Input node for the first node outside
the Group.
![exists parent.input1]
TIP - As people usually rename the Input nodes to make it easier to know what needs to be connected here is an easy way to find out the serial number of the node. You can select the Input node and
press i which is a hotkey for nukescripts.getallnodeinfo(). A new window will pop up and at the bottom you will find the node number.
Of course, can also check the same thing with python but use thisGroup() instead of thisNode().
This function will look for the Group's input.
0 if nuke.thisGroup().input(0) else 1
To access a value outside the Group the shortest code is parent.input which is checking the first node connected right outside the Group.
parent.input.size
Can also check the name of the topnode from inside the Group.
[value [topnode parent.input0].name]
One interesting thing here is that when you are using the parent.input command that will refer to what is connected outside the Group to a certain Input so you can also reach nodes that aren't connected directly! Remember that in programming the numbers start at 0 so that's why when I am calling in the example input2 it is returning the node's value connected to Input3, but if you will check the info of the Input node you will find that number 2 at the bottom.
[value parent.input2.size] or parent.input2.size
Can still move up step by step too.
[value this.parent.input.input.input.input1.input.name]
And can do a same thing with python.
[python {nuke.thisGroup().input(0).input(0).input(0).input(1).input(0).name()}]
So we know that parent.input moves up a level, what happens if we need to move up multiple levels?
Obviously, we can stack up this commend! Only thing to be aware of that the Group inside a Group now need to be connected to the input!
[value parent.input.parent.input.parent.input.size]
Here, you can also use python and applying a similar approach using parent().input().
nuke.thisNode().parent().input(0).parent().input(0).parent().input(0)['size'].value()
Getting values from inside the Group
Looking inside a Group for a value needed much less often then looking for a value outside the Group for good reason. Mainly, because Groups can contain any type of nodes and therefore it just isn't too user-friendly. Only reason I can imagine doing it is for scripts that are running automated or in strict templates but as LiveGroups are getting more of a norm and part of pipeline processes this one might be useful too.
Probably, the easiest way to use TCL here is the following approach:
​input.Blur1.size
This approach can also be used if need to go down multiple levels!
input.Group_level1.Group_level2.Blur20.size
As a slightly different approach you can call the node inside a Group by its name!
[value Group_root.Blur1.size]
If you need to assign Python code as TCL the with function is still a safest way to look inside a Group and we can combine that with a python -exec here.
[python -exec {
with nuke.toNode('Blur86').input(0).input(0):
new_val = nuke.toNode('Blur1')['size'].value()
}] [python new_val]
Probably, the easiest with python is to use the node()
With this function you can call the node by name inside the Group.
nuke.thisNode().input(0).node('Blur1')['size'].value()
You can use this method to go down multiple levels.
nuke.thisNode().input(0).node('Group_level1').node('Group_level2').node('Blur1')['size'].value()
It isn't recommended much to use this approach but you can also use the nodes() function which returns a list of nodes within a Group!
​
Warning - Be aware that when you are calling a node based on its position on the list that the list can get updated and re-arranged not just by creating or deleting nodes but by simply rearranging inputs so this approach is not very flexible!
nuke.thisNode().input(0).nodes()[-1]['size'].value()
You can also move down multiple levels using this method!
nuke.thisNode().input(0).nodes()[1].nodes()[-1].nodes()[1]['size'].value()
Let's try something much simpler with a little preparation!
The point here is that you can add the knobs from the Group to the node which is easier to call.
Do it step by step!
​
So first let's go to Manage User Knobs... on the Group.
Next, let's go to Pick and select the knob that has the value we are interested in.
After hitting Ok the knob is added to the Group and you can see on the list size {Blur1.size}!
The first information ( size ) is the name of the knob as you can rename it and the information within the curly brackets are the origin of the value ( {Blur1.size} ).
And now you can add a very simple expression to get the input value!
input.size
In case, you don't want people to have easy access to this value ( like in a template ) you can hide the value from the Group!
This you can do by selecting the knob and go Edit then tick the Hide checkbox.
As a result you will see that on the list it will say [INVISIBLE] before the knob but you can still call the value with the same input expression!
😬 Bad parenting 😬
There are certain issues with parenting that worth to be aware of before jumping on making gizmos!
​
You surely don't want random expression lines flying around in your script!
So, first thing to be aware of that if there is an expression calling a node inside a Group it will look outside the Group if it can't find it inside!
​
To test this here's a simple expression where Blur_that is getting a value from Blur_this and note that
there is also a Blur_this outside the Group.
Blur_this.size
Next, let's delete Blur_this inside the Group!
We get a warning but let's proceed by hitting Yes.
After a little time you will see that if there is a node with a same name on root level it will connect to that which might not be what we want so be careful with expressions connecting to
not existing values inside the Group!
Unfortunately, if you delete the animation / expression from the knob, the Group remains connected to the node on root level (visually) despite that there is no expression calling it now!
You need to copy/paste the Group to don't see that expression line.
So one interesting thing to note here, is that when making an expression link inside the Group that looks at higher levels too! BUT when you write an expression on root that won't look into Groups!
One good allie to spot such mistakes is the Error Console that will let you know when an expression is missing an input value.
( stating here that ERROR: Blur103.size: Nothing is named "parent.Group11.Blur102" after I deleted
the Blur102 node where the Blur103's size value was coming from )
CONGRATULATIONS!
You just learned a lot of new tricks about parenting!
Use it well!
Hope you will find it useful!