====== Nuke Basic ======
* store your pre-set node setting [[http://shizukalog.blogspot.com/2010/11/nuke-setting-up-default-parameter-of.html|video guide]]
| action | shortcut, cmd=ctrl |
| open node property | double-click, cmd+click, return |
| open node property float | cmd+double-click, cmd+alt+click |
| close all property | alt+click on x on panel |
====== Nuke Intro ======
===== Tracking in Nuke =====
* tracker node:
* 2D for translation, rotation, scale
* require: 1 point for translation, 2 points for rotation and scale
* planar tracker node:
* 2.5D for translation, rotation, scale, skew, perspective
* require: a planar surface
* camera tracker node:
* 3D for volumes, spaces, planes, perspective in 3D
* require: focal length, film back size, camera parallax movement, lens distortion removal
===== Removal and Paint in Nuke =====
- prepare footage
* grain/noise removal (denoise node)
* stabilize
- choose clear reference frame
- get BBox coverage
- frameHold portions and paint node groups
- shape parts to relieve
- matchmove and add grain
===== Camera Track and Projection in Nuke =====
* solve camera in nuke or other app
* 3D camera in nuke
* Geometry
* Clean Patch
* Frozen Camera
====== Nuke Python Script Intro ======
**Where to enter the script**
* x key: (File > Script Command - TCL/Python)
* script editor: (Right click the panel bar > split vertical and choose "Script Editor" in drop down)
* Error console
**Where to view command history** (like Maya "Echo all Command")
* Edit menu > Preference : Script Editor tab : Echo python command
**Where to know the node or knob attribute name**
* right click on the attribute and click "Add Expression", then all the internal name releaved.
**How to know the node Class and Function**
* use this code your_node.Class() # to get Class name
help(your_node.Class()) # to get class definition
**Ultimate solution: Python Panels**
* a script based python-based floating tab panel that integrated with Nuke, not a dialog
===== Nuke Python common syntax =====
* common python syntax
i=0;
list=[]
list.append(item)
print list
total = len(list) - 1
print total
for i in range(0, total):
print list[i]
===== Interact with Nuke GUI interface =====
ref: http://www.youtube.com/watch?v=JoniI7oRDaU
** for the code not working, just clean the space and use tab to re-create the tabs**
Tips: if you want to know the knob name, then hold Alt+drag it to script editor to show its reference name.
* get and feedback to user nuke.message("hello") # alert box
nuke.tprint("it prints in terminal where nuke launched from")
* get selected node nuke.selectedNodes() # return a list
nuke.toNode('NodeName') # get node with the name
* get format and node format
node = nuke.selectedNode()
nodeFormat = node.format()
print nodeFormat.name()
#or width
nuke.selectedNode().width()
nuke.selectedNode().height()
# or all formats
scriptFormats = nuke.formats()
for f in scriptFormats:
print f.name()
print f.width()
print f.height()
print f.pixelAspect()
print 10*'-'
* get select node knobs (cool way for GUI programming of existing node) znodes=nuke.selectedNodes()
znode=znodes[0]
for i in range(znode.getNumKnobs()):
print '"%d %s' % (i, znode.knob (i).name())
# method 2
help(nuke.selectedNode()) #list all node method
nuke.selectedNode().Class() #print node class name
# qwidget under mouse
from PySide import QtGui,QtCore
def getPos():
pos = QtGui.QCursor.pos()
widget = QtGui.qApp.widgetAt(pos)
print(widget)
QtCore.QTimer.singleShot(5000, getPos) # print widget under mouse after 5s
# all panel
nuke.Double_knob
parent_window = QtGui.QApplication.activeWindow()
all_stacked_widgets = parent_window.findChildren(QtGui.QStackedWidget)
* get active knob from right click on knob
knobMenu = nuke.menu("Animation")
knobMenu.addCommand('Set Key knob', "nuke.message(\"Knob Name: nuke.toNode('%s').knob('%s'); %s\" % (nuke.thisNode().name(), nuke.thisKnob().name(), nuke.thisKnob().value()) );keyNode=nuke.thisNode().name()+'.'+nuke.thisKnob().name();" )
topMenu = nuke.menu('Nuke')
topMenu.addCommand('Test/Key knob', "nuke.message('keying now: %s' % keyNode);keyCurrent(keyNode)", 'Ctrl+F11' )
def keyCurrent(node_attr):
# node_attr format: node.attr
info = node_attr.split('.')
keyNodeAttr = nuke.toNode(info[0]).knob(info[1])
cur_frame = nuke.frame()
cur_value = keyNodeAttr.value()
if not keyNodeAttr.isAnimated():
keyNodeAttr.setAnimated()
keyNodeAttr.setValueAt(cur_value, cur_frame)
\\ {{:appwiki:nuke:nuke_script_get_knob.jpg|}} {{:appwiki:nuke:nuke_script_get_knob_2.jpg|}}
* get or set gui value print znode.knob ('knobName').value()
print znode['knobName'].value()
znode.knob (i).setValue('theValue')
* write to file and read from file
import sys
import os
filename='/home/user/TrackConvertSrc.txt'
fp = open(filename, 'w')
fp.write( "0 0 0\n" )
trackSrcX = znode.knob('to1').animation(0)
for key in trackSrcX.keys():
if flipY:
fp.write( "%g %g %g\n" % (key.x, key.y, imageHeight - trackSrcY.evaluate( key.x )) )
else:
fp.write( "%g %g %g\n" % (key.x, key.y, trackSrcY.evaluate( key.x )) )
fp.close()
# read
trackDst = znode.knob('to1')
trackDst.clearAnimated(0)
trackDst.clearAnimated(1)
trackDst.setAnimated(0)
trackDst.setAnimated(1)
trackX = trackDst.animation(0)
trackY = trackDst.animation(1)
fp = open(filename, 'r')
for line in fp:
if line.startswith('0'):
continue
try:
tt, xx, yy = [float(x) for x in line.split()]
except:
continue
trackX.setKey( tt, xx )
if flipY:
trackY.setKey( tt, imageHeight - yy )
else:
trackY.setKey( tt, yy )
fp.close()
* deal with 2D position animation curve (pre-baked curve required)
# like znode as cornerPin node
# read curve
trackSrc = znode.knob('to1')
if not trackSrc.isAnimated(0) or not trackSrc.isAnimated(1) :
nuke.message('source track no keyframes!')
trackSrcX = trackSrc.animation(0)
trackSrcY = trackSrc.animation(1)
# write curve
* node creation related
# method 1
newNode=nuke.nodes.CornerPin2D(name='newCorner')
# method 2
nuke.createNode('CornerPin2D')
# get selected node type or class name
znodes=nuke.selectedNodes()
znode=znodes[0]
znode.Class() # Tracker3
* node attributes related
imageHeight = znode.height()
imageWidth = znode.width()
format = znode.format().name()
pixelAspect = znode.format().pixelAspect()
# create attribute experssion
# example: tracker to crop mode
fullTracker="Track1" # tracker node
crop="Crop1" #crop node
newName=fullTracker+"_crop_mode"
newNode=nuke.nodes.Tracker3(name=newName)
newNode['enable1'].setValue(True)
newNode['enable2'].setValue(True)
newNode['enable3'].setValue(True)
newNode['enable4'].setValue(True)
newNode['track1'].setExpression(fullTracker+'.track1-'+crop+'.box.x', 0)
newNode['track1'].setExpression(fullTracker+'.track1-'+crop+'.box.y', 1)
newNode['track2'].setExpression(fullTracker+'.track2-'+crop+'.box.x', 0)
newNode['track2'].setExpression(fullTracker+'.track2-'+crop+'.box.y', 1)
newNode['track3'].setExpression(fullTracker+'.track3-'+crop+'.box.x', 0)
newNode['track3'].setExpression(fullTracker+'.track3-'+crop+'.box.y', 1)
newNode['track4'].setExpression(fullTracker+'.track4-'+crop+'.box.x', 0)
newNode['track4'].setExpression(fullTracker+'.track4-'+crop+'.box.y', 1)
* animation related
curNodeAttr = nuke.toNode("Grade1")['blackpoint']
animCuves = curNodeAttr.animations()
curAnimCurve = curNodeAttr.animation(0)
# get value at frame
valueAtFrame1 = curAnimCurve.evaluate(2) # value at frame 2
# set value at frame
curAnimCurve.setKey(10, 0.5) # set to 0.5 at frame 10
# check value expression
curNodeAttr.hasExpression() # 1,0
curAnimCurve.noExpression() # 1,0
# set expression connection
animCurveB.setExpression('blackpoint')
# get expression
exp = curAnimCurve.expression()
# get key
keys = curAnimCurve.keys()
curAnimCurve.addKey(keys)
curAnimCurve.clear()
# same as
nuke.animation("Grade1.blackpoint", "clear")
* plugins nuke.pluginPath() # list all plugin path, use first found in path
nuke.pluginAddPath(os.path.abspath("/my/path")) # all os compatile
===== menu.py =====
Nuke menu customization
- put menu.py in ".nuke" folder (which is under home directory)
- sample code of import a py file GUI tool in menu.py file
import sys; sys.path.insert(0, "/myPythonScriptDir/dev/")
import MyPythonFileNameOnly as myFirstGUI
m = menubar.addMenu("MyCustMenu")
m.addCommand("Menu Item Name", "myFirstGUI.go()")
* menu.py can also be used to change/add menu shortcut ([[http://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_ui.html#assigning-a-hotkey|read reference]])
* menu.py can also be used to set node default setting ([[http://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_ui.html#knobdefaults-ref-label|read reference]])
- sample code of Python GUI tool for menu integration
import nuke
import nukescripts
class myFirstGUI(nukescripts.panels.PythonPanel):
def __init__(self, name):
nukescripts.panels.PythonPanel.__init__(self, name)
# gui preset
newline = nuke.Text_Knob("")
newline.setVisible(False)
self.btn01=nuke.PyScript_Knob("firstBtn", "My button")
self.addKnob(self.btn01)
self.addKnob(newline)
self.addKnob(nuke.PyScript_Knob("AskBtn", "Hello Button", "nuke.message(\"Done by Me v1.0! \\n\\nv1.0 usage:\\n- Do it.\")"))
def knobChanged( self, knob ):
if knob == self.btn01:
print("cool")
def go():
mypanel = myFirstGUI("GUI cool v1.0")
mypanel.show()
===== Python-Panel GUI design=====
* ref here:
* build guide: http://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_panels.html#python-panels
* knob type: http://docs.thefoundry.co.uk/nuke/63/ndkdevguide/knobs-and-handles/knobtypes.html
* custom panel guide: http://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_panels.html
* common GUI element
p = nuke.Panel('My Pop-up Panel')
p.addButton("cool")
result = p.show()
* built-in GUI panel_testfrom nukescripts import panel_test
panel_test.panel_example()
* tab window template
class modelPanel(nukescripts.panels.PythonPanel):
def __init__(self, name):
nukescripts.panels.PythonPanel.__init__(self, name)
#=================
self.addKnob(nuke.Text_Knob("Group1"))
newline = nuke.Text_Knob("")
newline.setVisible(False)
self.addKnob(nuke.PyScript_Knob("btn01", "Label01", "nuke.message(\"hey\")" ))
self.addKnob(newline)
self.addKnob(nuke.PyScript_Knob("btn02", "Label02", "nuke.message(\"hey\")" ))
self.addKnob(newline)
#=================
self.addKnob(nuke.Text_Knob("Group2"))
self.addKnob(nuke.PyScript_Knob("btn03", "Label03", "nuke.message(\"hey\")" ))
self.addKnob(newline)
#=================
self.addKnob(nuke.Text_Knob("Group3"))
self.addKnob(nuke.PyScript_Knob("btn04", "Label04", "nuke.message(\"hey\")" ))
self.addKnob(newline)
#========== show up script run seperately
panel = None
global panel
if not panel:
panel = modelPanel("Model Select Panel")
panel.show()
* GUI knob button with multi-line pop-up message
self.addKnob(nuke.PyScript_Knob("HelpBtn", "Tip*Trick", "nuke.message(\"\\n1.ask me line 1.\\n2.check my update line2.\")"))
===== My Nuke Python Script tools =====
Example of procedure GUI design
* tracker in full resolution image into crop reformat image
#============================
# Full-Res Tracker to Crop Tracker by yx v1.0
# Input : name of tracker and crop node
# Output: new tracker node with linked corresponding tracker data in crop mode
# 2014.02.15
#============================
import nuke
def go():
p = nuke.Panel('Full-Res Tracker to Crop Tracker by yx v1.0')
p.addSingleLineInput('Full-Res Tracker Node', '')
p.addSingleLineInput('Crop Node', '')
p.addButton('Cancel')
p.addButton('Generate Crop Tracker Node')
ret = p.show()
fullTracker = p.value('Full-Res Tracker Node')
crop = p.value('Crop Node')
if ret:
print fullTracker, crop
newName=fullTracker+"_crop_mode"
newNode=nuke.nodes.Tracker3(name=newName)
print newName+" created"
newNode['enable1'].setValue(True)
newNode['enable2'].setValue(True)
newNode['enable3'].setValue(True)
newNode['enable4'].setValue(True)
newNode['track1'].setExpression(fullTracker+'.track1-'+crop+'.box.x', 0)
newNode['track1'].setExpression(fullTracker+'.track1-'+crop+'.box.y', 1)
newNode['track2'].setExpression(fullTracker+'.track2-'+crop+'.box.x', 0)
newNode['track2'].setExpression(fullTracker+'.track2-'+crop+'.box.y', 1)
newNode['track3'].setExpression(fullTracker+'.track3-'+crop+'.box.x', 0)
newNode['track3'].setExpression(fullTracker+'.track3-'+crop+'.box.y', 1)
newNode['track4'].setExpression(fullTracker+'.track4-'+crop+'.box.x', 0)
newNode['track4'].setExpression(fullTracker+'.track4-'+crop+'.box.y', 1)
Example of Class like GUI design
* copy BoundBox to CornerPin setting
#============================
# BBox_Pin v1.0
# pin placed directly to bbox of the node
#
#============================
p1x=0
p1y=0
p2x=0
p2y=0
p3x=0
p3y=0
p4x=0
p4y=0
class bboxPinPanel(nukescripts.panels.PythonPanel):
def __init__(self, name):
nukescripts.panels.PythonPanel.__init__(self, name)
# gui preset
newline = nuke.Text_Knob("")
newline.setVisible(False)
self.btn01=nuke.PyScript_Knob("CopyBtn", "Copy BBox")
#btn01.setCommand("copyBBox()")
self.addKnob(self.btn01)
self.btn02=nuke.PyScript_Knob("PasteBtn", "Paste to Pin")
self.addKnob(self.btn02)
def knobChanged( self, knob ):
if knob == self.btn01:
global p1x
global p1y
global p2x
global p2y
global p3x
global p3y
global p4x
global p4y
znode = nuke.selectedNode()
print znode.name()
bh=znode.bbox().h();
bw=znode.bbox().w();
bx=znode.bbox().x();
by=znode.bbox().y();
p1x=bx
p1y=by
p2x=bx+bw
p2y=by
p3x=bx+bw
p3y=by+bh
p4x=bx
p4y=by+bh
print [p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y,]
if knob == self.btn02:
global p1x
global p1y
global p2x
global p2y
global p3x
global p3y
global p4x
global p4y
znode = nuke.selectedNode()
znode["to1"].setValue(p1x,0)
znode["to1"].setValue(p1y,1)
znode["to2"].setValue(p2x,0)
znode["to2"].setValue(p2y,1)
znode["to3"].setValue(p3x,0)
znode["to3"].setValue(p3y,1)
znode["to4"].setValue(p4x,0)
znode["to4"].setValue(p4y,1)
znode["from1"].setValue(p1x,0)
znode["from1"].setValue(p1y,1)
znode["from2"].setValue(p2x,0)
znode["from2"].setValue(p2y,1)
znode["from3"].setValue(p3x,0)
znode["from3"].setValue(p3y,1)
znode["from4"].setValue(p4x,0)
znode["from4"].setValue(p4y,1)
bppanel = bboxPinPanel("BBox to PinPoint by Ying v1.0")
bppanel.show()
* roto shape point access and control script
node = nuke.selectedNode()
knob = node['curves']
for element in knob.rootLayer:
for index, point in enumerate(element):
print index, point.center.getPosition(nuke.frame())
# setPosition(CVec2(cpx, cpy))