How to ensure that user can input any datatype (str, float, int, boolean...)?

1.1k views Asked by At

So this is my first question on the forum and I hope I am doing it correct. General question: How can I ensure that python does not return any errors when writing a script that allows the user to input values of different datatypes depending on the context or parameter they want to change? More specific: I am new to python and want to write a script that allows users of The Foundry's Nuke to change values on multiple nodes of the same class at once. Depending on whether the desired parameter to change is a checkbox('bool'), and RGBA input ('4 floats')... the input has to be of a different type. Searching the forum I found that the type can be checked by type() function and compared in an if statement with the isinstance() function. I guess I could work with that, but the type of e.g. a Gradenode's multiply knob returns type 'AColor_Knob'. I expected something like float. And comparing it in an isinstance() does not give me a match regardless of the datatype I am comparing to.

Mainscript so far:

nukescripts.clear_selection_recursive()

userInput = nuke.getInput('Which type of nodes would you like to select? (!!!first char has to be capitalized!!!)',
                          'Shuffle')

matchingNodes = []

for each in nuke.allNodes():
    if each.Class() == userInput:
        matchingNodes.append(each)
    else:
        pass

for i in matchingNodes:
    i.setSelected(True)

nuke.message(str(len(
    matchingNodes)) + ' matching Nodes have been found and are now selected! (if 0 there either is no node of this type or misspelling caused an error!)')

userInput_2 = nuke.getInput('Which parameter of these nodes would you like to change? \n' +
                            '(!!!correct spelling can be found out by hovering over parameter in Properties Pane!!!)',
                            'postage_stamp')
userInput_3 = nuke.getInput('To what do you want to change the specified parameter? \n' +
                            '(allowed input depends on parameter type (e.g. string, int, boolean(True/False)))', 'True')

for item in matchingNodes:
    item.knob(userInput_2).setValue(userInput_3)

How I checked the datatypes so far:

selected = nuke.selectedNode()
knobsel = selected.knob('multiply')
print(type(knobsel))
#if type(knobsel) == bool:
if isinstance(knobsel, (str,bool,int,float,list)):
    print('match')
else:
    print('no match')
1

There are 1 answers

2
M.Last On BEST ANSWER

You can call a TCL command with nuke.tcl(). In TCL, everything is a string, so type is irrelevant (in some commands).

p = nuke.Panel('Property Changer')
p.addSingleLineInput('class', '')
p.addSingleLineInput('knob', '')
p.addSingleLineInput('value', '')
p.show()

node_class = p.value('class')
knob_name = p.value('knob')
knob_value = p.value('value')

for node in nuke.allNodes(node_class):
    tcl_exp = 'knob root.{0}.{1} "{2}"'.format(node.fullName(),knob_name,knob_value)
    print tcl_exp
    nuke.tcl(tcl_exp)

That should answer your question. There are many ways to approach what you're trying to do - if you want to keep it all in python, you can do type checking on the value of the knob. For example:

b = nuke.nodes.Blur()
print type(b.knob('size').value()).__name__

This creates a Blur node and prints the string value of the type. Although I don't recommend this route, you can use that to convert the value:

example = '1.5'
print type(example)
exec('new = {}(example)'.format('float'))
print type(new) 

An alternative route to go down might be building yourself a custom lookup table for knob types and expected values.

Edit:

TCL Nuke Commands: http://www.nukepedia.com/reference/Tcl/group__tcl__builtin.html#gaa15297a217f60952810c34b494bdf83d

If you press X in the nuke Node Graph or go to File > Comp Script Command, you can select TCL and run:

knob root.node_name.knob_name knob_value

Example:

knob root.Grade1.white "0 3.5 2.1 1"

This will set values for the named knob.