====== 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))