In this tutorial you will find some tips and tricks that I've wrote and catch up from other websites. It will be really useful for all the Nuke artist because it's a complete guide by categories. I've also created a Gizmo to check directly inside Nuke the various commands in Python and the TCL expressions.
You can download the Gizmo for Nuke here:
Download from Nukepedia
Index
- 00. Python and TCL Overview
- 01. Create Node
- 02. Select Node
- 03. Connect nodes
- 04. Read from a knob
- 05. Write into a knob
- 06. Create a new knob
- 07. Animation and Curve
- 08. Expressions
- 09. Math functions and Wave Generator
- 10. Functions def()
- 11. Callbacks
- 12. Customs Panels
- 13. Tricks
- 14. Color Nodes
- 15. PySide & PySide2
- 16. Qt
00. Python and TCL Overview
https://www.tutorialspoint.com/python/index.htm
http://learn.foundry.com/nuke/developers/63/pythondevguide/basics.html
http://learn.foundry.com/nuke/developers/63/pythondevguide/index.html
http://www.nukepedia.com/tcl/tcl-reference
http://www.nukepedia.com/reference/Tcl/group__tcl__builtin.html
http://www.lookinvfx.com/nuke-tcl-snippets
http://thoughtvfx.blogspot.de/2012/12/nuke-tcl-tips.html
- PYTHON:
#-------------------------------------------------------
#PRINT and VARIABLES
print 'Hello World'
name = 'Andrea'
print 'Hello' + name
#-------------------------------------------------------
#VARIABLES TYPES
int(x)
long(x)
float(x)
str(x)
#convert string o int
int (stringa)
#convert int to string
str(integer)
#-------------------------------------------------------
#STRINGS
var1 = 'Hello World!'
print "Updated String : ", var1[:6] + 'Python'
#Result: Updated String : Hello Python
var2 = "Hello, Ciao, Halo,"
list = var2.split(',')
for x in list:
print(x)
#RESULT Hello
# Ciao
# Halo
#-------------------------------------------------------
#IF CONDITION
if expression:
statement(s)
else:
statement(s)
#EXAMPLE 01
if var == 200:
print 'ciao'
elif var<200:
print 'ok'
#EXAMPLE 02
answer = 'y'
if answer is 'y':
print("answer is equal to 'y'")
#EXAMPLE 03
if answer in ['y', 'Y', 'yes', 'Yes', 'YES']:
print("answer is in this list")
#-------------------------------------------------------
#IF CONDITION IN 1 LINE
("some string" if expression else "another string")
#if size > 100 then print 'big', otherwise print 'small'
(' big!' if nuke.thisNode()['size'].value()>100 else ' small')
#-------------------------------------------------------
#FOR LOOP
#simple structure
for x in range(0, 3):
print x
#Lists as an iterable
collection = ['hey', 5, 'd']
for x in collection:
print x
#-------------------------------------------------------
#WHILE LOOP
count = 0
while (count < 9):
print 'The count is:', count
count = count + 1
print "Good bye!"
# RESULT: The count is: 0
#The count is: 1
#The count is: 2
#The count is: 3
#The count is: 4
#The count is: 5
#The count is: 6
#The count is: 7
#The count is: 8
#Good bye!
- TCL:
#GETTING A KNOB’S VALUE OF A SPECIFIC NODE:
#First frame of current read/write:
[value Read1.first]
#Getting a knob’s value of current node:
[value this.first_frame]
#Return label value of the input node:
[value this.size]
#Name of the input node:
[value this.input0.label]
#Name of the node before the group (Outside):
[value this.input.name]
#Return 1 if the node is on error otherwise 0:
[value this.parent.input.name]
#Get the bounding Box from the input of the node:
[value error]
#Here some expression for the Format
format.x
format.y
width
height
bbox.x
bbox.y
bbox.w
bbox.h
#Get the format from the input of the node:
#left boundary
[value input.bbox.x]
#right boundary
[value input.bbox.r]
#Get the format from the input of the node:
#width
[value input.format.r]
#height
[value input.format.t]
#Get the x position of the point #3 of the Bezier1 of the Roto1 node:
[value Roto1.curves.Bezier1.curve_points.3.main.x]
#Return sample pixel value of the node Add1 reading in the red at position of knob Center:
[sample Add1 Red Center.x Center.y]
#Get the value of the channel of a node, at a specific pixelcoordinates (e.g.: 10,10):
[sample [node input] red 10 10]
#---------------------------------------------------------------------
#SET VALUES
#Setting a knob’s value of a specific node:
[knob Read1.first 10]
#Setting a variable, without returning that (useful in a textnode):
[set seq [value Read1.file]; return]
#---------------------------------------------------------------------
#STRING
#Replace string in current node file knob with regex (string “proj” to “projects” in all occurences):
[regsub -all "proj" [value [node this].file] "projects"]
#String map (replace multiple stringpairs) (this returns: xxffffxxyy):
[string map {"aa" "xx" "bb" "yy"} "aaffffaabb" ]
#Compare strings:
[string equal [value Text1.message] "bla"]
#Regexp matching:
[regexp -inline "_v\[0-9]{3}" [value Read2.file]]
#Evaluating string
[python os.getenv('rotate') == 'xavierb']
#---------------------------------------------------------------------
#IF CONDITION
[if {condition} {expr1} else {expr2}]
#Example:
[if {[value blackpoint]==1} {return 2} {return 3}]
[if {[value blackpoint]==1} {return True} {return False}]
[if {[value blackpoint]==1} {return blackpoint} {return whitepoint}]
[if {[value filter]=="gaussian"} {return filter} {return False}]
#OTHER METHOD
condition ? then : else
#Example:
#if (r==1)? return 0: else (return r*2)
r ==1 ? 0 : r*2
#---------------------------------------------------------------------
#PATH MANIPULATIONS:
#Filepath without extension:
[file rootname [value [topnode].file]]
#Filename only:
[basename [value [topnode].file ]]
#Filename only without extension:
[basename[file rootname [value [topnode].file]]]
#---------------------------------------------------------------------
#RELATIVE PATH
#In the Read node you can use the relative path for your footage/Obj
#In your Read Node in the knob "file", use this:
#Read file "render.exe" in the same folder of your file nuke
[python {nuke.script_directory()}]/render.exr
#Read file "render.exe" in the subfolder where your file nuke is
[python {nuke.script_directory()}]/folder/render.exr
#Read file "render.exe" in the subfolder of your .nuke folder
[python {"/Users/gere/.nuke} ]/folder/render.exr
01. CREATE NODE
https://learn.foundry.com/nuke/developers/63/pythondevguide/basics.html
List of all the nodes in Nuke: http://nukexexperts.blogspot.de/2013/05/nuke-node-reference-image-nodes.html
- PYTHON:
#CREATE NODE WITH NUKE.NODES.XXX()
nuke.nodes.Blur()
nuke.createNode("Grade")
#CREATE 3 BLUR NODES
for x in range(0, 3):
nuke.nodes.Blur()
#----------------------------------------------------------------------------------
#PYTHON BUTTON IN A GROUP CREATE A BLUR NODE OUTSIDE THE GROUP
#COPY THIS IN A PYTHON BUTTON IN A GROUP
#EXAMPLE01
nuke.root().begin()
stickyNote = nuke.createNode('Blur')
#PYTHON BUTTON IN A GROUP CREATE A STICKYNODE OUTSIDE THE GROUP, READING THE VALUE IN THE KNOB 'PYTHON'
#EXAMPLE02
n=nuke.thisNode()
name = n.name()
text=nuke.toNode(name)['python'].getValue()
nuke.root().begin()
stickyNote = nuke.createNode('StickyNote')
stickyNote["label"].setValue(text)
02. SELECT NODE
- PYTHON:
#GET SELECTED NODE
nuke.selectedNode()
#GET MULTIPLE NODES SELECTED
nuke.selectedNodes()
#SELECT NODE BY NAME
node = nuke.toNode("Blur1")
node.knob('selected').setValue(True)
#SELECT ALL THE NODES
#The 'for loop'
for node in nuke.allNodes():
#Attribute 'selected' becomes True
node['selected'].setValue(True)
#-------------------------------------------------------------------------------------
#SELECT NODES THAT START WITH A SPECIFIC "STRING"
for node in nuke.allNodes():
#Instead of 'ColorCor' put the name that you want
if node['name'].value().startswith("ColorCor"):
node['selected'].setValue(True)
#-------------------------------------------------------------------------------------
#SELECT NODE BY CLASS
for node in nuke.allNodes():
#Select all the Blur nodes
if node.Class() == "Blur":
node['selected'].setValue(True)
#-------------------------------------------------------------------------------------
#RUN A SCRIPT FOR EVERY SELECTED NODE
# The list of nodes.
sn = nuke.selectedNodes()
for node in sn:
# Put your code here.
print nodes['name'].getValue()
#-------------------------------------------------------------------------------------
#ADD NAME OF NODES INTO A ARRAY (LIST). SELECT NODES AND CREATE A LIST OF ALL THE NAMES
array = [] #create the array
for node in nuke.selectedNodes():
n = node['name'].value()
#Add the value to the list
array.append(n)
#print the list
print array
#---------------------------------------------------------------------------------------
#DESELECT ALL SELECTED NODES
if nuke.selectedNodes():
for i in nuke.selectedNodes():
i['selected'].setValue(False)
#---------------------------------------------------------------------------------------
#####################################################
############GET NODES FROM A GROUP:##################
#####################################################
#1. FIRST EXAMPLE
myGroup = nuke.selectedNode()
if myGroup.Class() == "Group":
for j in myGroup.selectedNodes():
print j.name()
#2. OR ANOTHER WAY IS:
with nuke.toNode( 'MyGroup' ):
print nuke.allNodes()
#3. THIS IS THE WAY I USED IN MY ColorPanel code:
#nuke.selectedNode().selectedNodes()
try:
nodeSelected = nuke.selectedNode()
if (nodeSelected.Class() == "Group" and nodeSelected.selectedNodes()):
#if node selected is a group, then check if anything is selected inside
nuke.message("Changing color of Nodes inside Group: " + nodeSelected.name())
nodeSelected = nodeSelected.selectedNodes()
else:
nodeSelected = nuke.selectedNodes()
except:
nuke.message("SELECT A NODE.\nIf you want to change color of Nodes inside a Group, please select also the Group in the Node Graph.")
03. CONNECT NODE
- PYTHON:
#CONNECT THE OUTPUT OF THE SELECT NODE TO THE INPUT 0 OF COLORCORRECT
nuke.toNode('ColorCorrect3').setInput( 0, nuke.selectedNode() )
#CONNECT THE OUTPUT OF THE SELECT NODE TO THE INPUT 1 (MASK) OF COLORCORRECT
nuke.toNode('ColorCorrect3').setInput( 1, nuke.selectedNode() )
#CONNECT OUTPUT OF COLORCORRECTION TO ALL THE SELECTED NODES
for i in nuke.selectedNodes():
i.setInput( 0, nuke.toNode('ColorCorrect3'))
#-------------------------------------------------------------------------------------
#CREATE A MERGE NODE E CONNECT THE INPUTS TO THE SELECTED NODES
a = nuke.createNode('Merge')
b = nuke.selectedNodes()
x=0
for i in b:
if x==2:
x+=1
continue
a.setInput(x,i)
x+=1
#-------------------------------------------------------------------------------------
#DISCONNECT INPUT
nuke.selectedNode().setInput(1, None)
#DISCONNECT ALL THE INPUTS OF THE SELECTED NODE
for i in range(0, nuke.selectedNode().maxInputs()):
nuke.selectedNode().setInput(i, None)
#-------------------------------------------------------------------------------------
#DEPENDENT AND DEPENDENCIES
#LIST OF NODES DEPENDENT AND DEPENDENCIES
nuke.selectedNode().dependent()
nuke.selectedNode().dependencies()
#PRINT THE NAME OF THE NODES
for i in nuke.selectedNode().dependencies():
print i.name()
#-------------------------------------------------------------------------------------
#CONNECT knob inside a Group with a knob in the Group
knob = nuke.toNode("NameGroup.NameNode").knob("KnobNode")
knob.setExpression("parent.knobGroup", 0)
#CONNECT Pulldown Choice (for example Filter) inside a Group
knob = nuke.toNode("NameGroup.NameNodeDestination").knob("filter")
knob.setExpression("NameNodeOrigin.filter", 0)
04. READ FROM KNOB
- PYTHON:
# LIST ALL KNOBS FOR SELECTED NODE
print( nuke.toNode('Read1') )
# LIST ALL KNOBS FOR SPECIFIC NODE
print( nuke.selectedNode() )
# GET VALUE FROM SPECIFIC NODE, METHOD 01
value = nuke.toNode('Read1').knob('file').getValue()
#PRINT VALUE FROM SPECIFIC NODE, METHOD 02
node = nuke.toNode("Blur1")
print node['size'].value()
# GET VALUE FROM SELECTED NODE
value = nuke.selectedNode().knob('file').getValue()
#GET DEFAULT VALUE
nuke.toNode('Blur6').knob('size').defaultValue()
# GET VALUE FROM SPECIFIC NODE AND EVALUATE IT (GOOD FOR EXPRESSIONS)
value = nuke.toNode('Read1').knob('file').evaluate()
#GET THE EXPRESSION OF A KNOB
if nuke.toNode('Blur6').knob('size').hasExpression():
print nuke.toNode('Blur6').knob('size').toScript()
#GET VALUE XY_KNOB INDIVIDUALLY
nuke.toNode('Transform1').knob('scale').getValue(0) #w
nuke.toNode('Transform1').knob('scale').getValue(1) #h
#GET ME THE HEIGHT AND WIDTH FROM A SELECTED NODE
nuke.selectedNode().height()
nuke.selectedNode().width()
nuke.selectedNode().pixelAspect
#--------------------------------------------------------------------------------
#DROPDOWN MENU / PULLDOWN CHOICE
#GET VALUE FROM PULLDOWN CHOICE (NAME)
nuke.selectedNode()['attribute'].value()
#GET INDEX FROM PULLDOWN CHOICE (NAME)
int(nuke.toNode('Blur6').knob('filter').getValue())
int(nuke.selectedNode().knob('filter').getValue())
#--------------------------------------------------------------------------------
#CHECK THE NAME OF A KNOB (WILL BE USEFUL LATER)
node = nuke.selectedNode()
knob = node['filter']
if('filter' in knob.name()):
print "found it!"
#CALCULATE THE MAX AND MIN VALUE IN A FRAMERANGE
ret = nuke.getFramesAndViews('get range', '1-100')
frame_range = ret[0].split('-')
min=0
max=0
for i in range(int(frame_range[0]), int(frame_range[1])+1):
knob = nuke.selectedNode()['size'].getValueAt(i)
print 'value: ' + knob
print 'frame: ' + i
if (knob > max):
max = knob
if (knob < min):
min = knob
print 'max is', max
print 'min is', min
#--------------------------------------------------------------------------------
#GET FRAME RANGE FROM NODE
first_frame = nuke.selectedNode().firstFrame()
last_frame = nuke.selectedNode().lastFrame()
#-------------------------------------------------------------------------------
#READ KNOB INSIDE GROUP
#GET A KNOB OF A NODE INSIDE A GROUP. THIS WORKS ONLY INTO A PYTHON BUTTON OF THE GROUP
n=nuke.thisNode()
name = n.name()
print nuke.toNode('StickyNote_PythonOverview')['label'].getValue()
#-------------------------------------------------------------------------------
#READ / EXECUTE KNOB OF A NODE INSIDE GROUP
n=nuke.thisNode()
n.node('CurveTool')['go'].execute()
05. WRITE INTO KNOB
- PYTHON:
#SET DEFAULT VALUE FOR A KNOB
nuke.knobDefault( 'Blur.size', '77' )
nuke.knobDefault( 'channels', 'rgba' )
# SET SPECIFIC NODE'S VALUE
nuke.toNode('Read1').knob('file').setValue('c:/hello.tif')
nuke.toNode('Transform2').knob('scale').setValue(2)
# SET SELECTED NODE'S VALUE
nuke.selectedNode().knob('file').setValue('c:/hello.tif')
nuke.selectedNode()['scale'].setValue(3)
# SET THIS NODE'S VALUE
nuke.thisNode().knob('file').setValue('c:/hello.tif')
#SET KNOB WITH 4 VALUES (x, y, w, h)
n = nuke.selectedNode()
n['box'].setValue((0, 150, 4096, 2010))
#SET KNOB WITH 2 VALUES (w, h)
nuke.selectedNode()['scale'].setValue(1250, 0)
#WHEN A NODE HAS XY KNOB, USE THIS CODE TO SPLIT VALUES AND ASSIGN 2 DIFFERENT VALUES
nuke.selectedNode()['scale'].setSingleValue(False)
nuke.selectedNode()['scale'].setExpression('scale.w*2',1)
# SET SPECIFIC NODE'S KNOB TO DEFAULT VALUE
nuke.toNode('Grade1').knob('gamma').setValue( nuke.toNode('Grade1').knob('gamma').defaultValue() )
#SET EXPRESSION IN A KNOB
node = nuke.selectedNode()
node.knob('mix').setExpression('size + 5')
#DISABLE A NODE
nuke.toNode('Blur7')['disable'].setValue(True)
#SINGLE OR MULTIPLE VALUES IN A KNOB
nuke.toNode('Transform2')['scale'].setSingleValue(True)
#SET A CHECKBOX
nuke.toNode('Transform2')['invert_matrix'].setValue(True)
nuke.toNode('Transform2')['invert_matrix'].setValue(1)
#--------------------------------------------------------------------------------
#DROPDOWN MENU / PULLDOWN CHOICE
#SET A PULLDOWN CHOICE
nuke.toNode('Transform2')['filter'].setValue(2)
#POPULATE PULLDOWN CHOICE (DROPDOWN MENU)
pulldown = nuke.toNode('Group1')
pulldown['id'].setValues(['a', 'b', 'c'])
#EXPRESSION IN PULLDOWN CHOICE
#TCL:
in Transform1.filter {set_expression {Transform2.filter}}
#PYTHON:
k=nuke.toNode('Transform1')['filter']
k.setExpression('Transform2.filter',0)
#--------------------------------------------------------------------------------
#SET A KNOB AS THE CURRENT FRAME
nk = nuke.thisNode()
nk.knob('translate').setValue(nuke.frame())
#--------------------------------------------------------------------------------
#Knob VISIBLE/INVISIBLE
n = nuke.selectedNode()
n['knob'].setVisible(False)
06. CREATE A NEW KNOB
- PYTHON:
#FORMULA
node = nuke.toNode('Name Node')
knob = nuke.nuke.Double_Knob('name', 'Label')
node.addKnob(knob)
#CREATE A SLIDER KNOB
node = nuke.selectedNode()
knob = nuke.nuke.Double_Knob('slider', 'Slider')
knob.setRange(1,100)
knob.setValue(10)
node.addKnob(knob)
#------------------------------------------------------------------------------
#CREATE A INTEGER KNOB with SLIDER
n = nuke.selectedNode()
knob = nuke.Double_Knob("test","test")
#This is a Flag
#http://www.nukepedia.com/python/some-flags
knob.setFlag(0x0000000000000008)
n.addKnob(knob)
#------------------------------------------------------------------------------
# CREATE A CHECKBOX
sn = nuke.selectedNode()
uk = nuke.nuke.Boolean_Knob('checkbox', 'Checkbox')
uk.setValue(True)
sn.addKnob(uk)
07. ANIMATION and CURVE
http://www.nukepedia.com/python/animationcurve-and-animationkey-objects
https://learn.foundry.com/nuke/developers/63/pythondevguide/animation.html
https://learn.foundry.com/nuke/developers/80/pythonreference/nuke.Knob-class.html
https://learn.foundry.com/nuke/developers/63/pythondevguide/basics.html#copying-an-animation-curve-between-nodes
- PYTHON:
#CURRENT FRAME
print nuke.frame()
#GO TO FRAME x
nuke.frame(x)
#GET VALUE OF KNOB AT FRAME 5
knob = nuke.selectedNode()['size'].getValueAt(5)
#IF KNOB IS ANIMATED
node = nuke.createNode( 'Blur' )
k = node['size']
k.isAnimated()
#IF HAS AN EXPRESSION
k.hasExpression()
#RETURN TRUE IF THERE IS A KEYFRAME AT THE CURRENT FRAME
k.isKey()
#RETURN TRUE IF THERE IS A KEYFRAME AT THE FRAME 5
k.isKeyAt(5)
#GET KEY VALUE AT FRAME 3
nuke.selectedNode()['rotate'].getValueAt(3)
# PRINT KEY VALUE AT CURRENT FRAME
nk = nuke.selectedNode()
knob = nk.knob('rotate')
print knob.getValueAt(nuke.frame())
#SET KNOB TO ACCEPT ANIMATION
node = nuke.createNode( 'Blur' )
k = node['size']
k.setAnimated()
#SET KEY IN THE CURRENT FRAME
k.setValue( 5 )
#TWO MORE KEYS AT FRAME 10 AND 100 WITH VALUES OF 55 AND 66 RESPECTIVELY
k.setValueAt( 55, 10 )
k.setValueAt( 66, 100 )
#IF KNOB IS AN ARRAY, THIS SETS THE FIRST FIELD/CHANNEL TO 77 AND THE SECOND TO 88 AT FRAME 100
k.setValueAt( 77, 100, 0 )
k.setValueAt( 88, 100, 1 )
#------------------------------------------------------------------------------------------------
#PRINT ALL THE KEYS WITH THE VALUES FOR THE GIVEN ANIMATION CURVE
for key in animCurve.keys():
xValue = key.x
yValue = key.y
print 'ket at %s has value %s' % ( xValue, yValue )
# Result:
ket at 1.0 has value 5.0
ket at 10.0 has value 55.0
ket at 100.0 has value 77.0
#------------------------------------------------------------------------------------------------
#Clear all the animation in a node
n=nuke.selectedNode()
k=n.allKnobs()
for i in k:
i.clearAnimated()
#------------------------------------------------------------------------------------------------
#BAKE ANIMATION
https://learn.foundry.com/nuke/developers/63/pythondevguide/animation.html
#------------------------------------------------------------------------------------------------
#EXAMPLE 01: SELECT THE ANIM CURVE
g1 = nuke.toNode("Grade1")
gBlack = g1['blackpoint']
anim = gBlack.animation(0)
print anim
#------------------------------------------------------------------------------------------------
#EXAMPLE 02: CREATE A FRADE NODE WITH 2 KEYS ON THE BLACKPOINT AT FRAME 1 AND 10
g = nuke.nodes.Grade()
a = nuke.AnimationC urve(g['blackpo int'], 0, 'r')
a.setKey(1, .1)
a.setKey(10, .125)
g['blackpoint'].copyAnimation(0, a)
#------------------------------------------------------------------------------------------------
#EVALUATE: THIS SIMPLY TAKES A NUMERIC FRAME ARGUMENT (INT OR FLOAT) AND RETURNS THE CURVE’S VALUE AT THAT FRAME
anim.evaluate(30)
#FRAME NUMBER AND A KEY VALUE
anim.setKey(48, .044)
#THIS RETURNS TRUE IF THE ANIMATION IS DRIVEN BY KEYS, OR FALSE IF THE ANIMATION IS LINKED BY AN EXPRESSION.
anim.noExpression()
#ATTACH AN EXPRESSION TO AN ANIMATIONCURVE
gWhite = g1['whitepoint']
gWhite.setAnimated()
anim2 = gWhite.animation(0)
anim2.setExpression("blackpoint")
#------------------------------------------------------------------------------------------------
#THIS METHOD WILL STILL RETURN THE VALUE ‘CURVE IF THE PARENT KNOB ISN’T LINKED USING AN EXPRESSION
anim.expression()
#THIS RETURNS A LIST OF ANIMATIONKEY OBJECTS
keys = anim.keys()
print keys
#------------------------------------------------------------------------------------------------
#DELETE ANIMATION
#DELETE ALL KEYS FROM THE CURVE
anim.clear()
#REMOVE KEY
knob.removeKey()
#REMOVE KEY AT TIME 't'
knob.removeKeyAt(t)
#DELETE THE ANIMATION FROM ALL THE SELECTED NODES
nodes = nuke.selectedNodes()
for n in nodes:
knobs = n.allKnobs()
for k in knobs:
k.clearAnimated()
#------------------------------------------------------------------------------------------------
#*******************************************************************
#*************** EXAMPLE with Corner Pin Node ******************
#*******************************************************************
#setKeyframe at the current frame to all knobs 'TO'
n = nuke.thisNode()
#save current values
knob_to1 = n['to1'].getValue()
knob_to2 = n['to2'].getValue()
knob_to3 = n['to3'].getValue()
knob_to4 = n['to4'].getValue()
#create Animation to all the knobs
n['to1'].setAnimated()
n['to2'].setAnimated()
n['to3'].setAnimated()
n['to4'].setAnimated()
#create keyframe at the current frame with the current value
n['to1'].setValue(knob_to1)
n['to2'].setValue(knob_to2)
n['to3'].setValue(knob_to3)
n['to4'].setValue(knob_to4)
08. EXPRESSIONS
http://www.nukepedia.com/python/animationcurve-and-animationkey-objects
https://learn.foundry.com/nuke/developers/63/pythondevguide/animation.html
https://learn.foundry.com/nuke/developers/80/pythonreference/nuke.Knob-class.html
https://learn.foundry.com/nuke/developers/63/pythondevguide/basics.html#copying-an-animation-curve-between-nodes
- PYTHON:
#EXPRESSION in PYTHON
• nuke.expression() to use a Nuke expression in Python code.
• expression to use a Nuke expression in TCL.
• nuke.tcl() to run TCL code in Python.
• python to run Python code in TCL
• [ ] (square brackets) to embed TCL in a Nuke expression (or a string knob)
• [python {...}] to embed Python in a Nuke expression.
#SET KNOB WITH AN EXPRESSION
node = nuke.selectedNode()
node.knob('mix').setExpression('size + 5')
#ANOTHER EXAMPLE
node = nuke.toNode('Grade1')
node.knob('whitepoint').setExpression('gain + 1')
#USE PYTHON IN THE EXPRESSION (WITH TCL)
[python nuke.thisNode().metadata().keys()]
[python nuke.thisNode().metadata()\['input/filename'\]]
[python {nuke.thisNode().metadata['input/filename']}]
[python {nuke.thisNode().metadata['input/filename']}]
#USE PYTHON IN EXPRESSION. CHECK NUKE VERSION
[python {nuke.thisNode().knob(\'rotate\').value()}]
[if {[python nuke.NUKE_VERSION_MAJOR]<10} {return [11]} {return 10}]
[if {[python nuke.NUKE_VERSION_MAJOR]<10} {return "CornerPin2D.copy_from"} {return "CornerPin2D.copy_from_to"}]
#GET NUKE VERSION
if nuke.NUKE_VERSION_MAJOR < 11:
#nuke <= 10
else:
#nuke >= 11
#TCL IN PYTHON
nuke.tcl('return '+nuke.selectedNode()['filter'].value())
- TCL:
Use this link to check Expressions with TCL
http://www.andreageremia.it/tutorial_animation_nuke.html
www.cameroncarson.com/nuke-wave-expressions/
https://docs.python.org/2/library/math.html
https://en.wikibooks.org/wiki/Python_Programming/Basic_Math
https://help.thefoundry.co.uk/nuke/8.0/content/user_guide/expressions/adding_math_functions.html
- PYTHON:
09. MATH FUNCTIONS and WAVE GENERATOR
#MATH FUNCTIONS AND WAVE GENERATOR
#PYTHON
#--------------------------------------------------------
#IMPORT THE MATH LIBRARY
import math
#--------------------------------------------------------
#WAVE GENERATOR
#RANDOM WAVE
random((frame+offset)/waveLength) * (maxVal-minVal) + minVal
#NOISE WAVE
(noise((frame+offset)/waveLength)+1)/2 * (maxVal-minVal) + minVal
#SINE WAVE
(sin(2*pi*(frame+offset)/waveLength)+1)/2 * (maxVal-minVal) + minVal
#TRIANGLE WAVE
(asin(sin(2*pi*(frame+offset)/waveLength))/pi+0.5) * (maxVal-minVal) + minVal
#SQUARE WAVE
int(sin(2*pi*(frame+offset)/waveLength)+1) * (maxVal-minVal) + minVal
#SAWTOOTH WAVE
((frame+offset) % waveLength)/waveLength * (maxVal-minVal) + minVal
#SAWTOOTH (PARABOLIC) WAVE
sin((pi*(frame+offset)/(2*waveLength)) % (pi/2)) * (maxVal-minVal) + minVal
#SAWTOOTH (PARABOLIC REVERSED) WAVE
cos((pi*(frame+offset)/(2*waveLength)) % (pi/2)) * (maxVal-minVal) + minVal
#SAWTOOTH (EXPONENTIAL) WAVE
(exp(2*pi*((frame+offset) % waveLength)/waveLength)-1)/exp(2*pi) * (maxVal-minVal) + minVal
#BOUNCE WAVE
abs(sin(pi*(frame + offset)/waveLength))* (maxVal-minVal) + minVal
#BLIP
((frame+(offset+waveLength)) % (waveLength+blipLength)/(waveLength)) *(waveLength/blipLength) - (waveLength/blipLength) >= 0 ? maxVal : minVa
#SINEBLIP
((int((frame+offset) % waveLength)) >= 0 ? ((int((frame+offset) % waveLength)) <= (0+(blipLength-1)) ? ((sin(pi*((frame+offset) % waveLength)/blipLength)/2+1/2) * (2*maxVal-2*minVal) + (2*minVal-maxVal)) : minVal) : minVal)
- TCL:
#MATH FUNCTIONS
#TCL
#RETURNS THE ABSOLUTE VALUE OF THE FLOATING-POINT NUMBER X.
abs (x)
#ROUND X UP TO THE NEAREST INTEGER.
ceil (x)
#ROUND X DOWN TO THE NEAREST INTEGER.
floor (x)
#ROUND X TO THE NEAREST INTEGER NOT LARGER IN ABSOLUTE VALUE
int (x)
#ROUND X TO THE NEAREST INTEGER
rint (x)
#RETURN X CLAMPED TO [0.0 ... 1.0].
clamp (x)
#RETURNS THE COSINE OF X.
cos(x)
#RETURNS THE SINE OF X.
sin (x)
#RETURNS A POINT ON THE LINE F(X) WHERE F(0)==A AND F(1)==B. MATCHES THE LERP FUNCTION IN OTHER SHADING LANGUAGES.
lerp (a, b, x)
#RETURNS THE Y VALUE OF THE ANIMATION CURVE AT THE GIVEN FRAME
curve (frame)
rotate(frame)
#RETURNS THE CURRENT FRAME
frame
#CONVERT THE ANGLE X FROM RADIANS INTO DEGREES
degrees (x)
#CONVERT THE ANGLE X FROM DEGREES INTO RADIANS
radians (x)
#RETURN THE GREATEST OF ALL VALUES
max (x, y, ... )
#RETURN THE SMALLEST OF ALL VALUES
min (x, y, ... )
#RETURN THE VALUE FOR PI (3.141592654...)
pi
#RETURNS THE VALUE OF X RAISED TO THE POWER OF Y.
pow (x, y)
#RETURNS THE NON-NEGATIVE SQUARE ROOT OF X.
sqrt (x)
#EVALUATES THE Y VALUE FOR AN ANIMATION AT THE GIVEN FRAME
value (frame)
10. FUNCTIONS def()
- PYTHON:
#SINTAX
def function_name( parameters ):
"function_docstring"
function_suite
return [expression]
#EXAMPLE
def printme( str ):
"This prints a passed string into this function"
print str
return
def sum(a, b)
c = a+b
return c
---------------------
print "the sum is " + sum(10, 5)
11. CALLBACKS
https://learn.foundry.com/nuke/developers/63/pythondevguide/callbacks.html
https://learn.foundry.com/nuke/developers/63/ndkdevguide/knobs-and-handles/knobchanged.html
- PYTHON:
#CALLBACKS
#----------------------------------------------------------------
#KNOB CHANGED
#SINTAX
#copy this in the Script Editor in Nuke, select your node (or subsistute nuke.selectedNode() with nuke.toNode("NodeName")) and launch the script
#Example 01
nuke.selectedNode().knob('knobChanged').setValue("
nk = nuke.thisNode()
k = nuke.thisKnob()
if ('rotate' in k.name()):
#YOUR CODE")
#EVERY TIME THAT ROTATE WILL CHANGE, IT WILL EXECUTE YOUR CODE
#THIS WAS JUST AN EXAMPLE, IN YOUR SCRIPT EDITOR USE THIS VERSION WITH \N FOR A NEW LINE
nuke.selectedNode().knob('knobChanged').setValue("nk = nuke.thisNode()\nk =nuke.thisKnob()\nif ('rotate' in k.name()): #YOUR CODE")
#----------------------------------------------------------------
#EXAMPLE 02
#TO AVOID THE \N TO EVERY LINE, JUST USE """
nuke.selectedNode().knob('knobChanged').setValue("""
nk = nuke.thisNode()
k = nuke.thisKnob()
if ('gain' in k.name()):
print 'ciao'
""")
#----------------------------------------------------------------
nuke.selectedNode()['knobChanged'].setValue("if nuke.thisKnob().name() == 'inputChange': print 'input has Changed'")
#REMEMBER TO USE THE ' ' INSTEAD OF " " INSIDE THE PYTHON CODE
#----------------------------------------------------------------
#ON CREATE
nuke.selectedNode().knob('onCreate').setValue("nk = nuke.thisNode()\nk = nk['first_frame']\nk.setValue(nuke.frame())")
12. CUSTOM PANELS
https://learn.foundry.com/nuke/developers/63/pythondevguide/custom_panels.html
http://www.andreageremia.it/tutorial_panel_qtpy.html
- PYTHON:
CUSTOM PANELS
#----------------------------------------------------------------
pan = nuke.Panel('test')
choices = 'fistchoice secondchoice thridchoice'
pan.addEnumerationPulldown('choice:', choices)
pan.show()
13. TRICKS
http://www.comp-fu.com/2014/07/nuke-autolabel-magic
http://www.andreageremia.it/tutorial_label_autolabel.html
- PYTHON:
TRICKS
#-----------------------------------------------------------------------------
#IN CASE YOU WOULD LIKE TO SWITCH THE ANTIALIASING INSIDE A SCANLINE RENDERER TO “HIGH” WHEN rendering on the farm, but keep working in the GUI with “none”, you could use a line like this:
nuke.selectedNode()['antialiasing'].setExpression('$gui? 0:3')
#-----------------------------------------------------------------------------
TCL:
in Transform1.filter {set_expression {Transform2.filter}}
PYTHON:
k=nuke.toNode('Transform1')['filter']
k.setExpression('Transform2.filter',0)
#-----------------------------------------------------------------------------
#SWITCH NODE CHANGE ONLY IN THE FRAMES IN THE LIST
# If you use this inside a Switch Node, it can change value only in those frames
nuke.frame() in [1025,1072,1074]
#CURRENT FRAME
print nuke.frame()
#GO TO FRAME x
nuke.frame(x)
#------------------------------------------------------------------------------------------
#AUTOLABEL
n = nuke.selectedNodes()
for p in n:
p['autolabel'].setValue("nuke.thisNode().name()")
#EXAMPLE01
#Try this with a Grade Node
n = nuke.selectedNodes()
for p in n:
p['autolabel'].setValue("nuke.thisNode().name() + \"\\n\" + '(' + str(nuke.thisNode()['white'].value()) + ')' ")
#EXAMPLE02
#Try this with a Blur Node
n = nuke.selectedNodes()
for p in n:
p['autolabel'].setValue("nuke.thisNode().name() + \"\\n\" + '(' + nuke.thisNode()['filter'].value() + ')' ")
#EXAMPLE03
#When you create a Blur node, every time you will see this autolabel
def BlurLabel():
n = nuke.thisNode()
if n.Class() == "Blur":
autoLabel = n.name() + (' big!' if n['size'].value()>100 else ' small')
if n['label'].value():
autoLabel = autoLabel + '\n' + str(n['size'].value())
return autoLabel
nuke.addAutolabel(BlurLabel)
#------------------------------------------------------------
#RELATIVE PATH FILE
#This will set the project_directory path to the same one where the Nuke script is stored
[python {nuke.script_directory()}]