To Merge here: [[appwiki:nuke|App Nuke]] ====== Technique Section ====== ===== useful plugin ===== * https://github.com/adrianpueyo/KnobScripter * a standalone python editor for nuke, but can be extended ===== Pipeline ===== * pyside for nuke https://www.youtube.com/watch?v=ltODr920bpA * https://github.com/fredrikaverpil/pyvfx-boilerplate * http://community.thefoundry.co.uk/discussion/topic.aspx?f=190&t=102688 * https://docs.thefoundry.co.uk/nuke/63/pythondevguide/custom_panels.html * fxphd NUK230 PySide for NUKE * http://tylerart.com/sketchbook/ * Method 1: nuke environment setting, use that to let nuke load its init.py and menu.py there NUKE_PATH D:/myPath_for_nuke * Method 2: edit ~/.nuke/init.py, and menu.py, to load your custom init.py and menu.py at other location import nuke nuke.pluginAddPath('D:/myPath_for_nuke') ==== Environment Detection ==== * system detection import sys osMode = 'other' if sys.platform in ['win32','win64']: osMode = 'win' elif sys.platform == 'darwin': osMode = 'mac' elif sys.platform == 'linux2': osMode = 'linux' print("OS: {0}".format(osMode)) * nuke detect GUI mode import nuke nuke.env['gui'] # print 1 or 0 ==== Global Custom Pipeline integration ==== * nuke will auto run all the init.py in the path directories before launch import sys if nuke.NUKE_VERSION_STRING.startswith('9'): nuke.pluginAddPath('./9.0') # relative path sys.path.append('D:/myOtherPythonModulePath') # abs path * launch nuke with custom python initial script Nuke.exe replaceWritePaths.py other_args * menu.py file is another place for you to put menu related script, it is like init.py but more for menu creation # nuke main menu object nuke.menu('Nuke').addCommand('subMenuFolder/menuItemName','print("your python cmd example")', icon='/iconPath/toolName.png') # nuke gizmo menu object cur_menu = nuke.menu("Nodes").addMenu("myGiz", icon="myGizmo.png") cur_menu.addCommand('subMenuFolder/menuItemName','print("your python cmd example")', icon='/iconPath/toolName.png') # custom image formats nuke.addFormat("1280 768 0 0 1280 768 1 HD 1280 Square") ==== Callback Function ==== * the event driven functions that nuke will execute when the event happend. You can put those event function in init.py file, which nuke reads after launch. (in both gui and cmd mode) * nuke before render event example nuke.addBeforeRender(funcNameToDoBeforeRender) # it pass the write node as nuke.thisNode ==== commandline render ==== * render the all write node in script "C:\pathToNuke\NukeVersion.exe" -nukex -i -F 1001-1020 -x "R:/pathToScript/myNukeScript.nk" * render the Defined Write Node "C:\pathToNuke\NukeVersion.exe" -nukex -i -X ThatFinalWrite "R:/pathToScript/myNukeScript.nk" 1001-1020 ===== UI Integration ===== * menu creation with one-line and auto creation if not exist # it automatically create xTool menu in menubar, # and create "CompHelper" menu item that call function string, with shortcut and icon import sys,os;myPath=r'D:\Dev\CompHelper' myPath in sys.path or sys.path.append(myPath);import CompHelper; cmd = nuke.menu('Nuke').addCommand("xTool/CompHelper", 'CompHelper.main()',icon=os.path.join(myPath,'icons','CompHelper.png')) cmd.setIcon(os.path.join(myPath,'icons','CompHelper.png')) * save script nuke.scriptSave( outScript ) curScript = nuke.toNode("root").name() nuke.scriptSaveAs("/scratch/snapshot.nk") nuke.scriptSaveAs(curScript) ==== Node attribute knob Operation ==== * set knob to readonly/locked knob.setEnabled(False) # lock with a flag nuke.selectedNode()[knob].setFlag(nuke.DISABLED) nuke.selectedNode()[knob].clearFlag(nuke.DISABLED) ==== menu operation ==== **common menu operation codes** # top menu and side bar menu obj nuke.menu("Nuke") nuke.toolbar("Nodes") # add menu and add cmd obj menubar = nuke.menu("Nuke") # main menu bar my_menu = menubar.addMenu("MyMenu") # menu object my_menu.addCommand("Test","print('Test')") # menu item; subFolder/Test for subfolder cmds menubar.addMenu("MyMenu") # Important, without a var to hold it, it becomes menuItem object instead of menu obj # get items of a ui object # list direct child UI object menubar.items() # return menu child with that name menubar.menu('MyMenu') # return menu or menuItem child w that name menubar.findItem('MyMenu') # loop method of listing name_item_child_list = [ [cur_item.name(), cur_item] for cur_item in menubar.items() ] print(name_item_child_list ) * ref: * http://community.foundry.com/discuss/topic/100730 * https://help.thefoundry.co.uk/nuke/8.0/content/user_guide/configuring_nuke/custom_menus_toolbars.html * https://learn.foundry.com/nuke/developers/70/pythonreference/ ===== Setting Operation ===== * root first frame and last frame start = int(nuke.Root().knob('first_frame').value()) end = int(nuke.Root().knob('last_frame').value()) * get and goto frame curFrame = nuke.frame() # get nuke.frame(1002) # goto ===== File Operation ===== * Common maya like file operation, like Import/Edit file, and export selected/ save file as. # import file to viewport nuke.nodePaste(in_filepath.replace('\\', '/')) # edit File nuke.scriptOpen(in_filepath.replace('\\', '/')) # save Selected as File nuke.nodeCopy(out_filepath) # save file as nuke.scriptSaveAs(out_filepath) * get current script file path full_path = '' try: full_path = nuke.scriptName() except: nuke.message('No path found.') ===== Node Operation ===== * set a nuke node default nuke.knobDefault( 'Write.afterRender', 'import myFun;myFun.some_action()') * nuke script's root root root = nuke.thisNode() * nuke callBack function to access current call node thisNode = nuke.thisNode() * read my_node = nuke.createNode('Read') my_node['file'].fromUserText('/path/to/your/file.mov') * get selected nodes with type filtering selected = [x for x in nuke.selectedNodes() if x.Class() == 'Read'] * find all read nodes nuke_readNodes = [x for x in nuke.allNodes(recurseGroups=True) if x.Class() == 'Read'] self.memoData['nuke_path_list'] = [os.path.normpath(os.path.dirname(x['file'].value())) for x in nuke_readNodes] * find all write nodes def getNodeByClass(nodeClass, startNode): if startNode.Class() == nodeClass: yield startNode elif isinstance(startNode, nuke.Group): for child in startNode.nodes(): for foundNode in RecursiveFindNodes(nodeClass, child): yield foundNode allWriteNodes = [w for w in getNodeByClass('Write', nuke.root())] * render write node # set after render python script cur_node.knob('afterRender').setValue("WriteToMov()") # call a python function after done rendering # call render nuke.execute( nodeName, firstFrame, lastFrame ) * ref: https://www.thefoundry.co.uk/products/nuke/developers/63/pythondevguide/command_line.html ====== Knob Operation ====== * bake keyframe animation * ref: https://docs.thefoundry.co.uk/nuke/63/pythondevguide/animation.html * add knob callback node.knob('knobChanged') nuke.addKnobChanged(function) nuke.removeKnobChanged(function) ====== Nuke Tcl Expression ====== * Nuke Tcl Expression is not python, but nuke's own syntax for UI starts and node copy,paste,save as nk files. * it functions like Maya mel expression but it doesn't show the final result in attribute panel but the formula, while it does show the result in node editor view. * it use [] to contain a element, and operation is inside it with parameters and spaces. * the Tcl expression support data operation, logic operation, regex, and python script. * tip example: http://thoughtvfx.blogspot.com/2012/12/nuke-tcl-tips.html * auto write node: http://www.nukepedia.com/written-tutorials/how-to-build-an-automatic-write-node * ref: * https://docs.thefoundry.co.uk/nuke/105/pythondevguide/ * http://www.nukepedia.com/tcl/tcl-reference * http://www.nukepedia.com/tcl/value-vs-knob-command * nuke help/Documentation/Tcl/group__tcl__expressions.html#gafe083716d50b3fb4057e519961b9235c **Replace Single Line String to Multi Line Display** * put noteStr text input value into current message text block value, the single line format as "test / better one / best line" as [regsub -all " / " [value noteStr] "\n"] * it is useful to put [argv 8] like in the noteStr value, as cmd arg has to be in single line format **Use Express to Link StrValue to IntValue** * create a user text input knob, then use expression to link int knob to this text knob, and use [argv 7] like cmd arg to drive text value then updating the int value. (since int knob seems can't set as [argv 7] like) **example** # file attribute expression: [value rdir]/finals/[value shot]/NK_[value shot].%03d.dpx # get evaluate result print (nuke.thisNode()["file"].evaluate()) # mix python in tcl file "\[value nas_root]/\[value project]/\[value seq]/zup_renders/Comp/\[value RenderType]/\[value shot]_[value FileName]_v[python {str(int(nuke.thisNode()['ver'].value())).zfill(3)} ]/\[value shot]_[value FileName]_v[python {str(int(nuke.thisNode()['ver'].value())).zfill(3)} ].####.\[value file_type]" # use cmd knobChanged "\ncur=nuke.thisNode()\npathA = \[ cur\[each].value() for each in \['nas_root', 'project', 'seq'] ]\npathB = \['zup_renders/Comp', cur\['RenderType'].value() ]\nsegC = cur\['shot'].value()\nif cur\['FileName'].value() !='':\n segC+='_'+cur\['FileName'].value()\nsegC+='_v'+ str(int(cur\['ver'].value())).zfill(3)\npathD = \[ segC+'.####.'+cur\['file_type'].value() ]\ncur\['file'].setValue( '/'.join( pathA + pathB + \[segC] + pathD ) )\n" * TCL and Python Expression that trigger by frame reading error, as a way to detect error frame like corrupted exr, ref: https://forums.cgsociety.org/t/read-node-on-corrupt-frames-workaround/1650526/2 - create a user integer knob on Read node - set its value expression (Python) nuke.thisNode().error() - or set its value expression (TCL) [value error] - or create a user integer knob on Read node downstream connected node and - set its value express (Python) nuke.thisNode().input(0).error() - or set its value express (TCL), which take its topnode [value [topnode].error ] {{:graphic:python:nuke:nuke_read_node_error_frame_check.png|}} * addition info: * Windows > Error Console for error information ====== Nuke API ====== * nuke used library: nuke help/Documentation/html/content/comp_environment/third_party_software/third_party_libraries.html