Python and TCL: Tips and Tricks for Foundry Nuke

www.andreageremia.it/tutorial_python_tcl.html

https://www.gatimedia.co.uk/list-of-knobs-2

https://learn.foundry.com/nuke/developers/63/ndkdevguide/knobs-and-handles/knobtypes.html

 

http://www.andreageremia.it/tutorial_python_tcl.html

 

http://thoughtvfx.blogspot.com/2012/12/nuke-tcl-tips.html


Check final image quality

https://www.compositingpro.com/tech-check-compositing-shot-in-nuke/

Local copy:
http://pixelsham.com/wp-content/uploads/2023/03/compositing_pro_tech_check_nuke_script.nk

 

Nuke tcl procedures
https://www.gatimedia.co.uk/nuke-tcl-procedures

 

Knobs
https://learn.foundry.com/nuke/developers/63/ndkdevguide/knobs-and-handles/knobtypes.html

 

# return to the top
nuke.Root().begin()
nuke.allNodes()
nuke.Root().end()



# check if Nuke is running in UI or batch mode
nuke.env['gui'] # True or False



# prformatted font to use in a text node:
liberation mono




# import node from a path
# Replace '/path/to/your/script.nk' with the actual path to your Nuke script
script_path = '/path/to/your/script.nk'
# Create the node in the script
mynode = nuke.nodePaste(script_path)
# or
mynode = nuke.scriptReadFile(script_path) #asynchronous so the code wont wait for its completion, mynode  is empty
# same as 
mynode = nuke.tcl('source "{}"'.format(script_path))
my node will be empty and it wont select the node either
# or synchronous
mynode = NukeUI.Scriptlets.loadScriptlet(script_path) 




# connect a knob on an internal node to a parent's knob
# add a python expression to the internal node's knob like:
nuke.thisNode().parent()['falseColors'].getValue()
# or the opposite
not nuke.thisNode().parent()['falseColors'].getValue()
# or as tcl expression
1- parent.thatNode.disable




# check session performance
Sebastian Schütt – Monitoring Nuke’s sessions performance
nuke.startPerformanceTimers() nuke.resetPerformanceTimers() nuke.stopPerformanceTimers() # set a project start and end frames new_frame_start = 1 new_frame_end = 100 project_settings = nuke.Root() project_settings['first_frame'].setValue(new_frame_start) project_settings['last_frame'].setValue(new_frame_end) # disable/enable a node newReadNode['disable'].setValue(True) # force refresh a node myNode['update'].execute() # or myNode.forceValidate() # pop up UI alert warning nuke.alert('prompt')   # return a given node hdriGenNode = nuke.toNode('HDRI_Light_Export') clampTo1 = nuke.toNode('HDRI_Light_Export.Clamp To 1')   # access nodes within a group nuke.toNode('GroupNodeName.nestedNodeName')   # access a knob on a node hdriGenNode.knob('checkbox').getValue()   # return the node type topNode.Class() nuke.selectedNode().Class() nuke.selectedNode().name()   # return nodes within a group hdriGenNode = nuke.toNode('HDRI_Light_Export') hdriGenNode.begin() sel = nuke.selectedNodes() hdriGenNode.end()   # nodes position node.setXpos( 111 ) node.setYpos( 222 ) xPos = node.xpos() yPos = node.ypos() print 'new x position is', xPos print 'new y position is', yPos # execute a node's button through python node['button'].execute() # add knobs div = nuke.Text_Knob('someTextKnob','') myNode.addKnob(div) lgt_name = nuke.EvalString_Knob('lgt1_name','LGT1 name', 'some text') # id, label, txt myNode.addKnob(lgt_name) lgt_size = nuke.XY_Knob('lgt1_size', 'LGT1 size') myNode.addKnob(lgt_size) lgt_3Dpos = nuke.XYZ_Knob('lgt1_3Dpos', 'LGT1 3D pos') myNode.addKnob(lgt_3Dpos) lgt_distance = nuke.Double_Knob('lgt1_distance', ' distance') myNode.addKnob(lgt_distance ) lgt_isSun = nuke.Boolean_Knob('lgt1_isSun', ' sun/HMI') myNode.addKnob(lgt_isSun ) lgt_mask_clr = nuke.AColor_Knob('lgt1_maskClr', 'LGT1 mask clr') lgt_mask_clr.setValue([0.12, 0.62, 0.115, 0.65]) lgt_mask_clr.setVisible(False) myNode.addKnob(lgt_mask_clr) # add tab group knob lightTab = nuke.Tab_Knob('lgt1_tabBegin', 'LGT1, nuke.TABBEGINGROUP) myNode.addKnob(lightTab) lightTab = nuke.Tab_Knob('lgt1_tabEnd', 'LGT1', nuke.TABENDGROUP) myNode.addKnob(lightTab) # note if you have only one tab and you are programmatically adding to the bottom of it # remove the last endGroup node to make sure the new knobs go into the tab myNode.removeKnob(myNode['endGroup']) # python script knob remove_script = """ node = nuke.thisNode() for knob in node.knobs(): print(knob) if "lgt%s" in knob: node.removeKnob(node.knobs()[knob]) node.begin() lightGizmo = nuke.toNode('lgt%s') nuke.delete(lightGizmo) node.end() """ % (str(length), str(length)) lgt_remove = nuke.PyScript_Knob('lgt1_remove', 'LGT1 Remove', remove_script) myNode.addKnob(lgt_remove ) # link checkbox to function through knobChanged hdriGenNode.knob('knobChanged').setValue(''' nk = nuke.thisNode() k = nuke.thisKnob() if ("Jabuka_checkbox" in k.name()): print 'ciao' ''') # knobChanged production example my_code = """ n = nuke.thisNode() k = nuke.thisKnob() if k.name()=="sheetOrSequence" or k.name()=="showPanel": #print(nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue()) if nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue() == 0.0: n['frameEnd'].setValue(nuke.toNode(n.name() + '.MasterSwitch')['masterAppendClip_lastFrame'].getValue()) elif nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue() == 1.0 : n['frameEnd'].setValue(nuke.toNode(n.name() + '.MasterSwitch')['masterContactSheet_lastFrame'].getValue()) """ nuke.toNode("JonasCSheet1").knob("knobChanged").setValue(my_code) # retrieve the knobChanged callback node['knobChanged'].toScript() # nuke knobChanged callback https://corson.be/nuke_python_snippet/ # “knobChanged” is an “hidden” knob which holds code executed each time that we touch any node’s knob. # Thanks to that we can filter some user actions on the node and doing cool stuff like dynamically adding things inside a group. # This follows the node code = """ knob = nuke.thisKnob() if knob.name() == 'size': print "size : %s" % knob.value() """ nuke.selectedNode()["knobChanged"].setValue(code) def find_dependent_nodes(selected_node, targetClass): dependent_nodes = set() visited_nodes = set() def recursive_search(node): if node in visited_nodes: return visited_nodes.add(node) dependents = node.dependent() for dependent_node in dependents: print(dependent_node.Class()) if dependent_node.Class() == targetClass: dependent_nodes.add(dependent_node) recursive_search(dependent_node) recursive_search(selected_node) return dependent_nodes find_dependent_nodes(node, 'Write') # nuke changed through a nuke callback def myCallback(): # Code to execute when any checkbox knob changes print("Some checkbox value has changed!") n = nuke.thisNode() k = nuke.thisKnob() if k.name()=="myknob" or k.name()=="showPanel": print('do this') nuke.addKnobChanged(myCallback) nuke.removeKnobChanged(myCallback) # remove it first every time you wish to change the callback # nuke callback production example (note this will need to be saved in a place that nuke can retrieve: https://support.foundry.com/hc/en-us/articles/115000007364-Q100248-Adding-Callbacks-in-Nuke) def sheetOrSequenceCallback(): # Code to execute when any checkbox knob changes #print("Some checkbox value has changed!") n = nuke.thisNode() k = nuke.thisKnob() if k.name()=="sheetOrSequence" or k.name()=="showPanel": #print(nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue()) if nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue() == 0.0: n['frameEnd'].setValue(nuke.toNode(n.name() + '.MasterSwitch')['masterAppendClip_lastFrame'].getValue()) elif nuke.toNode(n.name() + '.MasterSwitch')['which'].getValue() == 1.0 : n['frameEnd'].setValue(nuke.toNode(n.name() + '.MasterSwitch')['masterContactSheet_lastFrame'].getValue()) # Add the callback function to the knob nuke.addKnobChanged(sheetOrSequenceCallback) nuke.removeKnobChanged(sheetOrSequenceCallback) # more about callbacks
# return all knobs for label, knob in sorted(jonasNode.knobs().items()): print(label, knob.value()) # remove a knob for label, knob in sorted(mynode.knobs().items()): if 'keyshot' in label.lower(): mynode.removeKnob(knob) # work inside a node group posNode.begin() posNode.end()   # move back to root level nuke.Root().begin() # Add a button link to docs import webbrowser browser = webbrowser.get('chrome') site = 'https://yoursite' browser.open(site)   # return all nodes nuke.allNodes() # python code inside a text node message [python -exec { import re import json output = 'hello' ... ... }] [python output]   # connect nodes blur.setInput(0, read) # label a node blur['label'].setValue("Size: [value size]\nChannels: [value channels]\nMix: [value mix]") # disconnect nodes node.setInput(0, None)   # arrange nodes for n in nuke.allNodes(): n.autoplace()   # snap them to closest grid for n in nuke.allNodes(): nuke.autoplaceSnap( n )   # help on commands help(nuke.Double_Knob)   # rename nodes node['name'].setValue('new') # query the format of an image at a given node level myNode.input(0).format().width()   # select given node all_nodes = nuke.allNodes() for i in all_nodes: i.knob("selected").setValue(False) myNode.setSelected(True)   # return the connected nodes metaNode.dependent()   # return the input node metaNode.input(0)   # copy and paste node nuke.toNode('original node').setSelected(True) nuke.nodeCopy(nukescripts.cut_paste_file()) nukescripts.clear_selection_recursive() newNode = nuke.nodePaste(nukescripts.cut_paste_file()) # copy and paste node alternative https://corson.be/nuke_python_snippet/ node = nuke.selectedNode() newNode = nuke.createNode(node.Class(), node.writeKnobs(nuke.WRITE_NON_DEFAULT_ONLY | nuke.TO_SCRIPT), inpanel=False) node.writeKnobs(nuke.WRITE_USER_KNOB_DEFS | nuke.WRITE_NON_DEFAULT_ONLY | nuke.TO_SCRIPT)   # set knob value metaNode.knob('operation').setValue('Avg Intensities')   # get knob value writeNode.knob('file').value() # get a pulldown choice knob label pulldown_knob = node[knob_name] pulldown_index = pulldown_knob.value() # Get the current index of the pulldown knob pulldown_label = pulldown_knob.enumName(pulldown_index) # link two knobs' attributes # add knob link k = nuke.Link_Knob('attr1_id','attr1') k.makeLink(node.name(), 'attr2_id.attr2')   # link two knobs between different nodes sel = nuke.selectedNode() lgt_colorspace = nuke.Link_Knob('colorspace', 'Colorspace') sel.addKnob(lgt_colorspace) Read1 = nuke.selectedNode() sel.knob('colorspace').makeLink(Read1.name(), 'colorspace') # link pulldown menus
Ben, how do I expression-link Pulldown Knobs?
This syntax can be read as {child node}.{knob} — link to {parent node}.{knob} nuke.toNode('lgtRenderStatistics.Text2').knob('yjustify').setExpression('lgtRenderStatistics.yjustify') nuke.toNode('lgtRenderStatistics.Text2').knob('xjustify').setExpression('lgtRenderStatistics.xjustify')   # create a grade node set to only red and change its gain mg = nuke.nodes.Grade(name='test2',channels='red') mg['white'].setValue(2) # remove a node nuke.delete(newNode)   # get one value out of an array paramater mynode.knob(pos_name).value()[0] mynode.knob(pos_name).value()[1]   # find all nodes of type write writeNodesList = [] for node in nuke.allNodes('Write'): writeNodesList.append(node)   # create an expression in python to connect parameters myNode.knob("ROI").setExpression("parent." + pos_name) # link knobs between nodes through an expression (https://learn.foundry.com/nuke/content/comp_environment/expressions/linking_expressions.html) Transform1.scale # connect two checkbox knobs so that one works the opposite of the other (False:True) node = nuke.toNode('myNode.Text2_all_sphericalcameratest_beauty') node.knob('disable').setExpression('parent.viewStats ? 0 : 1') # connect parameters between nodes at different level through an (non python) expression maskGradeNode.knob('white').setExpression('parent.parent.lgt1_maskClr') # connect parameters between nodes at different level through a python expression nuke.thisNode().parent()['sheetOrSequence'].getValue() # or using python in TCL [python {nuke.thisNode().parent()['sheetOrSequence'].getValue()}] # multiline python expression in TCL [python {nuke.thisNode().parent()['sheetOrSequence'].getValue()}] [python {print(nuke.thisNode())}] # multiline python expression from code with a return statement nuke.selectedNode().knob('which').setExpression('''[python -execlocal x = 2 for i in range(10): x += i ret = x]''', 0) # connect 2d knobs on the same node through a python expression nuke.thisNode()['TL'].getValue()[0] + ((nuke.thisNode()['TR'].getValue()[0] - nuke.thisNode()['TL'].getValue()[0])/2) # To add this as a python expression on each x and y of a 2d knob newLabel_expression_x = "[python nuke.thisNode()\['TL'\].getValue()\[0\] + ((nuke.thisNode()\['TR'\].getValue()\[0\] - nuke.thisNode()\['TL'\].getValue()\[0\])/2)]" newLabel_expression_y = "[python nuke.thisNode()\['TL'\].getValue()\[1\] + 10]" node['lightLabel'].setExpression(newLabel_expression_x, 0) node['lightLabel'].setExpression(newLabel_expression_y, 1) # note this may launch some errors when generating the node # a tcl expression seems to work best newLabel_expression_x = "lgt" + str(length) + "_tl.x() + 20" newLabel_expression_y = "lgt" + str(length) + "_tl.y() + 20" lgt_label.setExpression(newLabel_expression_x, 0) lgt_label.setExpression(newLabel_expression_y, 1) # load gizmo nuke.load('Offset')   # set knobs colors hdriGenNode.knob('add').setLabel("<span style="color: yellow;"&gt;Add Light") # or at creation, add knob with color lgt_LUX = nuke.Text_Knob('lgt%s_LUX' %str(length),"<font color='yellow'> LUX",'0') # id, label, txt # or when creating the knob manually: <font color='#FF0000'>Keyshot 1 or <font color='red'>Keyshot 1 # set color knob values hdriGenNode.knob('lgt_maskClr_1').setValue([0.0, 0.5, 0.0, 0.8]) hdriGenNode.knob('lgt_maskClr_1').setValue(0.4,3) # set only the alpha # return nuke file path nuke.root().knob('name').value()   # write metadata metadata_content = '{set %sName %s}\n{set %sMaxLuma %s}\n{set %sEV %s}\n{set %sLUX %s}\n{set %sPos2D %s}\n{set %sPos3D %s}\n{set %sDistance %s}\n{set %sScale %s}\n{set %sOutputPath %s}\n' % (lgtName, lgtCustomName, lgtName, str(maxL[0]), lgtName, str(lgt_EV), lgtName, str(lgt_LUX), lgtName, string.replace(str(pos2D),' ',''), lgtName, string.replace(str(pos3D),' ',''), lgtName, str(distance), lgtName, string.replace(str(scale),' ',''), lgtName, outputPath) metadataNode["metadata"].fromScript(metadata_content) # read metadata # metadata should be stored under the read node itself under one of the tabs readNode.metadata().get( 'exr/arnold/host/name' )   # return scene name nuke.root().knob('name').value()   # animate text by getting a knob's value of a specific node: [value Read1.first]   # animate text by getting a knob's value of current node: [value this.size]   # add to the menus mainMenu = nuke.menu( "Nodes" ) mainMenuItem = mainMenu.findItem( "NewMenuName" ) if not mainMenuItem : mainMenuItem = mainMenu.addMenu( "NewMenuName" ) subMenuItem = mainMenuItem.findItem( "subMenu" ) if not subMenuItem: subMenuItem = mainMenuItem.addMenu( "subMenu" ) return [ mainMenuItem ] menus = myMenus() for menu in menus: menu.addCommand('my tool', 'mytool.file.function()', None)   # add aov layer nuke.Layer(mynode, [mynode +'.red', mynode +'.green', mynode +'.blue', mynode +'.alpha'])   # onCreate options (like an onload option) # https://community.foundry.com/discuss/topic/106936/how-to-use-the-oncreate-callback # https://benmcewan.com/blog/2018/09/10/add-new-functionality-to-default-nodes-with-addoncreate/ # For example, you could do this: def setIt(): n = nuke.thisNode() k= n.knob( 'artist' ) user = envTools.getUser() k.setValue(user) nuke.addOnCreate(setIt, nodeClass = "") # retrieve the oncreate function sel = nuke.selectedNodes() code = sel[0]['onCreate'].getValue() print(code) # Or if you want to bake your code directly to a node: code = """ n = nuke.thisNode() k= n.knob( 'artist' ) user = envTools.getUser() k.setValue(user) """ nuke.selectedNode()["onCreate"].setValue(code) # Problem with onCreate is that it's run every time the node is created, which means even open a script will trigger the code.   # replace known nodes nodeToPaste = '''set cut_paste_input [stack 0] version 12.2 v10 push $cut_paste_input Group { name DeepToImage tile_color 0x60ff selected true xpos 862 ypos -3199 addUserKnob {20 DeepToImage} addUserKnob {6 volumetric_composition l "volumetric composition" +STARTLINE} volumetric_composition true } Input { inputs 0 name Input1 xpos -891 ypos -705 } DeepToImage { volumetric_composition {{parent.volumetric_composition}} name DeepToImage xpos -891 ypos -637 } ModifyMetaData { metadata { {remove exr/chunkCount ""} } name ModifyMetaData1 xpos -891 ypos -611 } Output { name Output1 xpos -891 ypos -530 } end_group ''' fileName = '/tmp/deleteme.cache' out_file = open(fileName, "w") out_file.write(str(nodeToPaste)) out_file.close() allNodes = nuke.allNodes() for i in allNodes: i.knob("selected").setValue(False) for node in allNodes: if 'DeepToImage' in node.name(): node.setSelected(True) newNode = nuke.nodePaste(fileName) nuke.delete(node) # force a knob on the same line hdriGenNode.addKnob(lgt_name) # stay on the same line lgt_lightGroup.clearFlag(nuke.STARTLINE) hdriGenNode.addKnob(lgt_lightGroup) # start a new line lgt_extractMode.setFlag(nuke.STARTLINE) hdriGenNode.addKnob(lgt_extractMode)   # text message per frame set cut_paste_input [stack 0] version 12.2 v10 push 0 push 0 push 0 push 0 Text2 { inputs 0 font_size_toolbar 100 font_width_toolbar 100 font_height_toolbar 100 message "MultiplyFloat.a 0.003\nMultiplyFloat2.a 0.35" old_message {{77 117 108 116 105 112 108 121 70 108 111 97 116 46 97 32 32 32 48 46 48 48 51 10 77 117 108 116 105 112 108 121 70 108 111 97 116 50 46 97 32 48 46 51 53} } box {175.2000122 896 1206.200012 1014} transforms {{0 2} } global_font_scale 0.5 center {1024 540} cursor_initialised true autofit_bbox false initial_cursor_position {{175.2000122 974.4000854} } group_animations {{0} imported: 0 selected: items: "root transform/"} animation_layers {{1 11 1024 540 0 0 1 1 0 0 0 0} } name Text20 selected true xpos 1197 ypos -132 } FrameRange { first_frame 1017 last_frame 1017 time "" name FrameRange19 selected true xpos 1197 ypos -77 } AppendClip { inputs 5 firstFrame 1017 meta_from_first false time "" name AppendClip3 selected true xpos 1433 } push 0 Reformat { format "2048 1080 0 0 2048 1080 1 2K_DCP" name Reformat4 selected true xpos 1843 ypos -251 } Merge2 { inputs 2 name Merge5 selected true xpos 1843 } push $cut_paste_input Reformat { format "2048 1080 0 0 2048 1080 1 2K_DCP" name Reformat5 selected true xpos 1715 ypos 80 } Merge2 { inputs 2 name Merge6 selected true xpos 1843 ypos 86 } # check negative pixels set cut_paste_input [stack 0] version 12.2 v10 push $cut_paste_input Expression { expr0 "r < 0 ? 1 : 0" expr1 "g < 0 ? 1 : 0" expr2 "b < 0 ? 1 : 0" name Expression4 selected true xpos 1032 ypos -106 } FilterErode { channels rgba size -1.3 name FilterErode4 selected true xpos 1032 ypos -58 } # check where the user is clicking on the viewer area import nuke from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, QEvent, Qt from PySide2.QtGui import QMouseEvent class ViewerClickCallback(QObject): def eventFilter(self, obj, event): if event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton: # Mouse click detected mouse_pos = event.pos() print("Mouse clicked at position:", mouse_pos.x(), mouse_pos.y()) return super(ViewerClickCallback, self).eventFilter(obj, event) #Create an instance of the callback callback = ViewerClickCallback() #Install the event filter on the application qapp = QApplication.instance() qapp.installEventFilter(callback) qapp.removeEventFilter(callback) ## you can put this under a node's button and close the callback after a given mouse click ## OR closing the callback through a different button import nuke from PySide2.QtCore import QObject, QEvent, Qt from PySide2.QtWidgets import QApplication class ViewerClickCallback(QObject): def __init__(self, arg1): super().__init__() self.arg1 = arg1 def eventFilter(self, obj, event): if event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton: # Mouse click detected mouse_pos = event.pos() print("Mouse clicked at position:", mouse_pos.x(), mouse_pos.y(),'\n') if self.arg1 == 'bl': jonasNode['bl'].setValue([mouse_pos.x(), mouse_pos.y()]) qapp.removeEventFilter(callback) return super(ViewerClickCallback, self).eventFilter(obj, event) # Create an instance of the callback callback = ViewerClickCallback('bl') # Store the callback as a global variable nuke.root().knob('custom_callback').setValue(callback) # Install the event filter on the application qapp = QApplication.instance() qapp.installEventFilter(callback) ## on the second button: import nuke # Retrieve the callback object from the global variable callback = nuke.root().knob('custom_callback').value() # Retrieve the QApplication instance qapp = QApplication.instance() # Remove the event filter qapp.removeEventFilter(callback) # collect deepsamples for a given node nodelist = ['DeepSampleB_hdri','DeepSampleA_hdri','DeepSampleB_spheres','DeepSampleA_spheres','DeepSampleB_volume','DeepSampleA_volume','DeepSampleB_furmg','DeepSampleA_furmg','DeepSampleB_furfg','DeepSampleA_furfg','DeepSampleB_furbg','DeepSampleA_furbg','DeepSampleB_checkers','DeepSampleA_checkers'] nodelist = ['DeepSampleB_hdri'] finalSamplesList = [] for nodeName in nodelist: print(nodeName) finalSamplesList.append(nodeName) finalSampes = 0 for posX in range(0,1921): for posY in range(0,1081): nukeNode = nuke.toNode(nodeName) nukeNode['pos'].setValue([posX,posY]) current_posSamples = nukeNode['samples'].getValue() finalSamples = finalSamples + current_posSamples print(finalSamples) finalSamplesList.append(finalSamples) # false color expressions set cut_paste_input [stack 0] version 13.2 v8 push $cut_paste_input Expression { expr0 "(r > 2) || (g > 2) || (b > 2) ? 3:0" expr1 "((r > 1) && (r < 2)) || ((g > 1) && (g < 2)) || ((b > 1) && (b < 2))\n ? 2:0" expr2 "((r > 0) && (r < 1)) || ((g > 0) && (g < 1)) || ((b > 0) && (b < 1))\n ? 1:0" name Expression4 selected true xpos 90 ypos 1795 }

# set knob flags
https://learn.foundry.com/nuke/developers/80/ndkdevguide/knobs-and-handles/knobflags.html

http://www.nukepedia.com/python/some-flags

knobName.setFlag(0x0000000000040000) #the 'HIDDEN' flag (this will remove pins from the viewer as well)
knobName.setFlag(0x0000000000008000) # disable widget
knobName.setFlag(0x0000000000000080) # disable panel

Based on

# General flags (must not intersect any class-specific flags):
DISABLED = 0x0000000000000080 # DISABLED Set by disable(), cleared by node.knob('knobName').setEnabled(True).
NO_ANIMATION = 0x0000000000000100 # NO_ANIMATION Prevent the value from being animated.
# This removes any anymation or view buttons, and
# it stops tcl expressions from being evaluated in
# string knobs, and may make it ignore attempts to
# set expressions or key frames (nyi).
DO_NOT_WRITE = 0x0000000000000200 # DO_NOT_WRITE Don't ever save this knob to a script
# (including copy & paste!)
INVISIBLE = 0x0000000000000400 # INVISIBLE The knob does not appear in the panels.
# No widgets are created. This is not the same
# as hide(), and show() will not undo it!
RESIZABLE = 0x0000000000000800 # RESIZABLE The knob can stretch in the panel so
# that it fills up all the remaining space in the line.
# Defaults to true for most of the complex knobs,
# but off for buttons, checkmarks, and pulldown lists.
STARTLINE = 0x0000000000001000 # STARTLINE This knob starts a new row in the panel.
# The default is true unless a zero-length (not NULL)
# string is passed as the label. Currently the default
# is false for checkmarks and buttons but this may
# change in future versions.+INVISIBLE
ENDLINE = 0x0000000000002000 # ENDLINE This knob will end a row, acts exactly
# like STARTLINE was set on the next knob.
# Set true for divider lines.
NO_RERENDER = 0x0000000000004000 # NO_RERENDER This knob does not contribute to the
# hash value for the op. This should be used on knobs
# that have no effect on the op's output.
NO_HANDLES = 0x0000000000008000 # NO_HANDLES Don't draw anything in the viewer,
# this is useful if the Op draws it's own indicators.
KNOB_CHANGED_ALWAYS = 0x0000000000010000 # KNOB_CHANGED_ALWAYS will call node()->knob_changed()
# every time the value of the knob changes. Normally
# it is only called if the user changes the value with
# the panel open. This allows you to track all changes to
# the value. Be careful as knob_changed() will be called
# without storing the new values into your structure.
NO_KNOB_CHANGED = 0x0000000000020000 # NO_KNOB_CHANGED: Don't bother calling Op::knob_changed()
# with this knob. This is turned on automatically
# if the knob_changed() returns false.
HIDDEN = 0x0000000000040000 # HIDDEN Set by hide(), cleared by show().
NO_UNDO = 0x0000000000080000 # NO_UNDO Don't undo/redo any changes to this knob.
# May be replaced with "output knob" in the future.
ALWAYS_SAVE = 0x0000000000100000 # ALWAYS_SAVE save the knob to a script even if not_default()
# returns false. *Deprecated*, instead override not_default()
# and make it return true!
NODE_KNOB = 0x0000000000200000 # NODE_KNOB is used by Nuke internally for controls on
# the DAG appearance such as xpos and ypos.
HANDLES_ANYWAY = 0x0000000000400000 # HANDLES_ANYWAY makes the handles appear in the viewer
# when the panel is open even if a different tab is selected.
INDETERMINATE = 0x0000000000800000 # Presents a blacked out undefined value interface on supporting knobs.
COLOURCHIP_HAS_UNSET = 0x0000000001000000 # whether a color chip can be in the 'unset' state,
# DEFAULTS TO FALSE
SMALL_UI = 0x0000000002000000 # Switches param panel widget to be more viewer Toolbar friendly in
# supported knobs (eg Button).
NO_NUMERIC_FIELDS = 0x0000000004000000 # Disables numeric input box widget on supported knobs.
KNOB_CHANGED_RECURSIVE = 0x0000000008000000 # recursive knobChanged calls are guarded against.
# To override the non-recursion on a particular knob,
# specify this flag
READ_ONLY = 0x0000000010000000 # knob cannot be modified by UI intervention but can
# still be copied from etc
NO_CURVE_EDITOR = 0x0000000020000000 # Disables curve editor.
NO_MULTIVIEW = 0x0000000040000000 # Disables view menu and splitting when in a multiview script.
EARLY_STORE = 0x0000000080000000 # Forces early synchronisation of data allowing usage in pre-op calls
# such as split_input().

MODIFIES_GEOMETRY = 0x0000000100000000 # MODIFIES_GEOMETRY should be set for any knob
# that modifies geometry, either by affecting the
# internal geometry directly or by changing its transform
OUTPUT_ONLY = 0x0000000200000000 # Similar to READ_ONLY & NO_RERENDER together - data changes don't
# count as a script change.
NO_KNOB_CHANGED_FINISHED = 0x0000000400000000 # Prevents knob_changed_finished being called on value change.
# Set if prev call returned false.
SET_SIZE_POLICY = 0x0000000800000000 # Do not use.
EXPAND_TO_WIDTH = 0x0000001000000000 # Force knob to expand to fill available space
# only for Enum knobs currently
NEVER_DRAW_HANDLES = 0x0000002000000000 # Disables viewer widget handles from drawing.
# Unlike the NO_HANDLES flag,
# the state of this flag will never change internally within Nuke
KNOB_CHANGED_RIGHTCONTEXT= 0x0000004000000000 # Always call knob_changed on a properly cooked Op,
# even if KNOB_CHANGED_ALWAYS is on
DONT_SAVE_TO_NODEPRESET = 0x0000008000000000 # This value of this knob should never be saved to a NodePreset.
# Can be used, for example, for data knobs.
RESERVED_COLORCHIP_KNOB = 0x0000010000000000 # DO NOT USE. This value is used by the colorchip knob.
READ_ONLY_IN_SCRIPTS = 0x0000020000000000 # Prevents knobs from being modified from Python/Tcl
ALWAYS_ALIGN_LABEL_TOP = 0x0000040000000000 # Label is always aligned to the top of the Knob
TINY_SLIDER = 0x0000080000000000 # Modifies SLIDER to be a tiny slider underneath lineedit.
# Should be a numeric knob flag but we've overrun the < 0x80 condition.
HIDE_ANIMATION_AND_VIEWS = 0x0000100000000000 # Prevents Animation Curve_Knob and Views being shown.
# Animation is still possible, unless NO_ANIMATION is set of course.
NO_COLOR_DROPDOWN = 0x0000200000000000 # Prevents Color Panel Dropdown from being available.
# Popup color panel will stil be available.
NODEGRAPH_ONLY = 0x0000400000000000 # Indicate that this knob should only be displayed when using
# the NodeGraph, since the Timeline uses gpuEngine,
# which might not support all the same knobs.
MODIFIES_TIME = 0x0001000000000000 # Should be set on all knobs which modify timing
TOOLBAR_BUTTON_DRAWSTYLE = 0x0002000000000000 # This knob must be drawn in the style of Viewer toolbar knobs
NO_SCRIPT_EXECUTE = 0x0000800000000000 # Prevents 'execute' being called on the knob

# Numeric knobs:
MAGNITUDE = 0x0000000000000001 # MAGNITUDE If there are several numbers, this enables a
# button to only show a single number, and all are set equal
# to this number. Default is true for WH_knob() and Color_knob().
SLIDER = 0x0000000000000002 # SLIDER Turns on the slider. Currently this only works if the size
# is 1 or MAGNITUDE is enabled and it is set to single numbers.
# Defaults to on for most non-integer numerical controls.
LOG_SLIDER = 0x0000000000000004 # LOG_SLIDER Tick marks on the slider (if enabled with SLIDER)
# are spaced logarithmically. This is turned on for WH_knob()
# and Color_knob(), and if the range has both ends greater
# than zero. If you turn this on and the range passes
# through zero, the scale is actually the cube root of
# the number, not the logarithim.
STORE_INTEGER = 0x0000000000000008 # STORE_INTEGER Only integer values should be displayed or stored.
FORCE_RANGE = 0x0000000000000010 # FORCE_RANGE Clamps the value to the range when storing.
ANGLE = 0x0000000000000020 # ANGLE Turn on a little widget depicting this number as an angle.
NO_PROXYSCALE = 0x0000000000000040 # NO_PROXYSCALE disables proxy scaling for XY or WH knobs.
# Useful if you just want two numbers called "x" and "y"
# that are not really a position.
# You probably also want to do NO_HANDLES.

# String Knobs
GRANULAR_UNDO = 0x0000000000000001 # Disables concatenation of minor undo events (string knobs)
NO_RECURSIVE_PATHS = 0x0000000000000002 # Badly named. Actually disables relative paths (string knobs).
NO_TCL_ERROR = 0x0000000000000004 # For strings containing TCL expressions,
# don't replace with TCL error messages if an error occurs

# Enumeration
SAVE_MENU = 0x0000000002000000 # SAVE_MENU writes the contents of the menu to the saved script.
# Useful if your plugin modifies the list of items.
EXPAND_TO_CONTENTS = 0x0000000000000001 # Make Enumeration knobs adjust their width to the size of the
# largest munu item.
EXACT_MATCH_ONLY = 0x0000000000000002 # Make Enumeration knobs use exact match when setting a value.
# If an attempt is made to set an invalid value,
# the knob will be put into an Error state.
STRIP_CASCADE_PREFIX = 0x0000000000000004 # Make Cascading Enumeration knobs not serialise out
# cascading prefixes

# SceneView knob
SINGLE_SELECTION_ONLY = 0x0000000000000001 # Knob only allows one item to be selected at a time
SHOW_BUTTONS = 0x0000000000000002 # Show Add Layer/Delete Layer buttons

# BeginGroup
CLOSED = 0x0000000000000001 # Stores the open/closed state of group knobs (group knobs).
TOOLBAR_GROUP = 0x0000000000000002 # Make the group into a viewer toolbar. General used via
# BeginToolbar (group knobs).
TOOLBAR_LEFT = 0x0000000000000000 # Defines which side of viewer toolbar appears on.
# Pick one at toolbar construction time (toolbar).
TOOLBAR_TOP = 0x0000000000000010 # Defines which side of viewer toolbar appears on.
# Pick one at toolbar construction time (toolbar).
TOOLBAR_BOTTOM = 0x0000000000000020 # Defines which side of viewer toolbar appears on.
# Pick one at toolbar construction time (toolbar).
TOOLBAR_RIGHT = 0x0000000000000030 # Defines which side of viewer toolbar appears on.
# Pick one at toolbar construction time (toolbar).
TOOLBAR_POSITION = 0x0000000000000030 # A mask for the position part of the flags

# ChannelSet/Channel:
NO_CHECKMARKS = 0x0000000000000001 # Disable individual channel checkbox widgets
# (channel/channelset knobs).
NO_ALPHA_PULLDOWN = 0x0000000000000002 # Disable 4th channel pulldown widget (channel/channelset knobs).

# Format knob
PROXY_DEFAULT = 0x0000000000000001 # Sets default knob value from script proxy format rather
# than full res (format knob).

COLORCHIP_PRESERVE_ALPHA = 0x0000010000000000 # The ColorChip_knob discards alpha values by default.
# Set this flag to make it keep them, instead.

 
Share: