top of page

Nuke python:

Multiple knob editor

Nuke python:

import nuke
import nukescripts

class ShapePanel(nukescripts.PythonPanel):
def __init__(self, node):
"""
defining and adding knobs
"""
FL_STR_KNOBS = ('float_Knob', 'MultiFloat_Knob', 'Boolean_Knob', 'Multiline_Eval_String_Knob', 'Disable_Knob', 'String_Knob', 'File_Knob',
'Cached_File_Knob', 'Read_File_Knob', 'Write_File_Knob', 'Multiline_String_Knob', 'Password_Knob')

INT_KNOBS = ('Array_Knob', 'ColorChip_Knob', 'Int_Knob', 'MultiInt_Knob', 'UV_Knob', 'Color_Knob', 'Double_Knob', 'Obsolete_Knob')

CHANNEL_KNOBS = ('ChannelMask_Knob', 'Channel_Knob', 'Font_Knob')

DIRECT_KNOBS = ('WH_Knob', 'XY_Knob', 'XYZ_Knob', 'BBox_Knob', 'Format_Knob', 'Box3_Knob', 'Scale_Knob', 'PixelAspect_Knob',
'PositionVector_Knob', 'Transform2d_Knob', 'Axis_Knob', 'AColor_Knob', 'MultiView_Knob', 'EvalString_Knob' )

MENU_KNOBS = ('Enumeration_Knob', 'CascadingEnumeration_Knob', 'PyPulldown_Knob', 'Menu_Knob', 'Pulldown_Knob', 'Dynamic_Bitmask_Knob')

INVALID_KNOBS = ('Knob', 'PyScript_Knob', 'Script_Knob', 'Tab_Knob', 'LookupCurves_Knob', 'PythonKnob')

nukescripts.PythonPanel.__init__(self, 'Multiple Knob editor')

self.select_similar = nuke.PyScript_Knob('Select similar nodes', 'Select similar nodes')
self.addKnob(self.select_similar)

self.class_name = nuke.Text_Knob('', 'Select Node: ' + '')
self.addKnob(self.class_name)

self.node_knobs = nuke.Enumeration_Knob('Available Knobs', 'Available Knobs', [])
self.addKnob(self.node_knobs)

self.nodes_change = nuke.Enumeration_Knob('Node Name', 'Node Name', [])

self.div1 = nuke.Text_Knob('divider1', '')
self.addKnob(self.div1)

self.update_button = nuke.PyScript_Knob('Update', 'Update')

self.help = nuke.Text_Knob("<a href=\http://any_link/\">some text</font></a>")

self.knobs_added = []

#callingupdate/cancel button at the end of the panel
self.add_update_cancel()

def add_update_cancel():
"""
placing the add/remove buttons and adding those knobs
"""
self.addKnob(self.update_button)
self.update_button.setFlag(nuke.STARTLINE)
self.addKnob(self.help)

def remove_update_cancel(self):
'''
removing update/help
'''
self.removeKnob(self.update_button)
self.update_button.clearFlag(nuke.STARTLINE)
self.removeKnob(self.help)

def build_knob(self, knob_type, knob_names, knob_value_variable):
'''
for all knob types called, it looks in the appropriate lists and adds those
knob_type: self.knob_type
knob_names: self.knob_names
knob_value_variable: self.knob_values
'''

try:
if knob_type in self.FL_STR_KNOBS:
self.knob_value=eval('nuke.%s("%s", "%s", %s)' %(knob_type, knob_names, knob_names, knob_value_variable))
self.knobs_added.append(knob_names)
self.addKnob(self.knob_value)
self.knob_value.setValue(knob_value_variable)

elif knob_type in self.INT_KNOBS:
integer_value = int(knob_value_variable)
if knob_type == 'Array_knob':
self.knob_value=eval('nuke.%s("%s", "%s")' %(knob_type, knob_names, knob_names))
else:
self.knob_value=eval('nuke.%s("%s", "%s", %s)' %(knob_type, knob_names, knob_names, integer_value))

self.knobs_added.append(knob_names)
self.addKnob(self.knob_value)
self.knob_value.setValue(integer_value)

elif knob_type in self.CHANNEL_KNOBS:
knob_values = nuke.selectedNode().knob(knob_names).value()
self.knob_value=eval('nuke.%s("%s", "%s")' %(knob_type, knob_names, knob_names))
self.knobs_added.append(knob_names)
self.knobs_value.setName(knob_names)
self.addKnob(self.knob_value)
self.knob_value.setValue(knob_values)

elif knob_type in self.DIRECT_KNOBS:
self.knob_value=eval('nuke.%s("%s", "%s")' %(knob_type, knob_names, knob_names))
self.knobs_added.append(knob_names)
self.knobs_value.setName(knob_names)
self.addKnob(self.knob_value)
if knob_type == 'MultiView_Knob':
self.knob_value.setValue(str(knob_value_variable))
else:
self.knob_value.setValue(knob_value_variable)

elif knob_type in self.MENU_KNOBS:
knob_values = nuke.selectedNode().knob(knob_names).value()
self.knobs_added.append(knob_names)
self.knob_value=eval('nuke.%s("%s", "%s", %s)' %(knob_type, knob_names, knob_names, knob_values))
self.addKnob(self.knob_value)
self.knob_value.setValue(knob_values)

elif knob_type in self.INVALID_KNOBS:
nuke.message("invavid knobs")
else:
print knob_type
except RuntimeError:
print knob_type
nuke.message("invavid knobs")

def remove_knobs(self, knobs_remove):
'''
called every time when previous knobs have to be replaced with new.
knobs_remove: all_knobs_to_remove
'''
node = nuke.thisNode()

for k, knob in node.knobs().items():
if k == knobs_remove:
node.removeKnob(k)

def knobChanged(self, knob):
'''
runs every time any action happens in python panel
'''
self.class_list = []
selected_node = nuke.selectedNode()
self.class_list.append(selected_node.Class())
self.class_name.setValue(self.class_list[0])

#selects all matching nodes of class and zooms to fit in scene
if knob == self.select_similar:
nuke.selectSimilar(nuke.MATCHCLASS)
nuke.zoomToFitSelection()

#defining knobs which are not used by artist
omit_list = ['onUserCreate', 'knobChanged', 'onDestroy', 'onCreate', 'updateUI', 'xpos', 'ypos', 'merge_bbox', 'layer', 'panel', 'icon', 'help', 'name', 'autolabel', 'add_panelDropped', 'Mask', 'maskFrom', 'AChannels', 'A', 'B', 'BChannels', 'shutter_offset', 'presets', 'Render']

self.nodes_change.setValues(self.class_list)
nodes_to_change = self.nodes_change.value()
all_knobs_list = []

#getting all Knobs of the node class selected
for i in nuke.allNodes(nodes_to_change):
all_knobs_list = sorted(i.knobs())
for name in all_knobs_list:
omit_more = type(nuke.selectedNode().knob(name)).__name__
if omit_more in ['PyScript_Knob', 'Python_Knob', 'Obsolete_Knob', 'Script_Knob', 'Tab_Knob', 'Knob', 'LookupCurves_Knob']:
omit_list.append(name)

#removing all knobs which are there in omit list from all_knobs_list
all_knobs_set = [x for x in all_knobs_list if x not in omit_list]

if self.class_list[0] in ['Grade', 'Constant', 'Roto', 'Blur', 'Merge2', 'MetaMerge']:
if self.class_list[0] == 'Grade':
all_knobs_list = ['channels', 'multiply', 'add', 'mask', 'unpremult', 'mix', 'black_clamp', 'white_clamp']
elif self.class_list[0] == 'Constant':
all_knobs_list = ['channels', 'color', 'format']
elif self.class_list[0] == 'Roto':
all_knobs_list = ['output', 'view', 'feather', 'feather_falloff', 'unpremult', 'cliptype']
elif self.class_list[0] == 'Blur':
all_knobs_list = ['channels', 'size', 'mask', 'mix']
elif self.class_list[0] == 'Merge2':
all_knobs_list = ['operation', 'screen_alpha', 'mask', 'mix']
elif self.class_list[0] == 'MetaMerge':
all_knobs_list = ['blend', 'mask', 'mix']
sorted_knobs = sorted(all_knobs_list)
all_knobs = ['frequently used knobs'] + sorted_knobs
else:
#removing repeated items if any
all_knob_list = list(set(all_knobs_set))
sorted_knobs = sorted(all_knob_list)
all_knobs = ['available knobs'] + sorted_knobs

#adding items alphabetically
self.node_knobs.setValues(all_knobs)
self.knob_names = self.node_knobs.value()

if not self.knob_names in ['available knobs', 'frequently used knobs']:
self.knob_type = type(nuke.selectedNode().knob(self.knob_names)).__name__
self.knob_values = nuke.selectedNode().knob(self.knob_names).getValue()

if knob.name() in ['available knobs', 'ShowPanel']:
#removing the update/cancel buttons from panel to add knobs
self.remove_update_cancel()

#removing knobs
if self.knobs_added:
for all_knobs_to_remove in self.knobs_added:
self.remove_knobs(all_knobs_to_remove)
self.knobs_added.remove(all_knobs_to_remove)
#bug 37959, 14622
nuke.message('adding %s knob' % self.knob_names)

#adding selected knob
self.build_knob(self.knob_type, self.knob_names, self.knob_values)

#adding update/cancel buttons back
self.add_update_cancel()

#updating new values from user
if knob == self.update_button:
new_knob_value = self.knob_value.value()
for s in nuke.selectedNodes():
s.knob(self.knob_names.setValue(new_knob_value))

def show(self):
"""
checking if any node is selected or nodes of same class is selected. panel opens if input is correct
"""
self.class_list = []
for s in nuke.selectedNodes():
n = s['name'].value()
self.class_list.append(s.Class())

self.class_list = list(set(self.class_list))
if len(self.class_list) == 1:
result = nukescripts.PythonPanel.show(self)
elif len(self.class_list) == 0:
nuke.message('please select node')
else:
nuke.message('Please select node of same class')

def main():
"""
calling main func
"""
node = nuke.toNode('Multiple Knob editor')
dlg = ShapePanel(node)
if dlg.show():
dlg.show

main()

bottom of page