def add_parameter():
"""
This function is run upon pressing the Add Parameter button.
Due to nuke limitations, we are forced to remove all the knobs,
add the new parameters knobs, then recreate the removed knobs.
Yes it is tedious, and it creates UI bugs, but there is no real other way...
"""
removed_knobs, available = delete_below_knobs()
create_parameter_knobs(available)
bring_knobs_back(removed_knobs)
def delete_below_knobs():
"""
Get the number that will be used to give a name/label to the new knobs
the function makes a list of dictionaries, used here to remove the knobs,
and that will be used later to bring them back into the node.
It returns the available (int) and knobs_to_remove (list)
"""
this_node = nuke.thisNode()
# Get the available spot for the creation of a new parameter# Get the index from which the knobs will be deleted/recreated
available = 1
parameter_knobs_index = []
for index, knob in enumerate(this_node.allKnobs()):
if knob.name().startswith("parameter_"):
parameter_knobs_index.append(index)
available = int(knob.name().split("_")[-1])+1
elif knob.name() == "add_parameter":
add_parameter_index = index
if parameter_knobs_index:
start_remove_index = max(parameter_knobs_index)+1
else:
start_remove_index = add_parameter_index+1
# Remove the knobs
knobs_to_remove = []
for index, knob in enumerate(this_node.allKnobs()):
if index >= start_remove_index:
knob_data = {"knob_object" : knob,
"Class" : knob.Class(),
"name" : knob.name(),
"label" : knob.label(),
"value" : knob.value(),
"tooltip" : knob.tooltip(),
"visible" : knob.visible()}
knobs_to_remove.append(knob_data)
for item in knobs_to_remove:
this_node.removeKnob(item["knob_object"])
return(knobs_to_remove, available)
def create_parameter_knobs(available):
"""
Create the new parameters knobs (parameter_name_, parameter_keyword_, parameter_remove_)
The function takes one argument (int)
"""
this_node = nuke.thisNode()
remove_knob_script = """
import fixtafoule_parameters
reload(fixtafoule_parameters)
fixtafoule_parameters.remove_parameter()
"""
name_knob = nuke.EvalString_Knob("parameter_name_{}".format(available),
"Parameter {} Name".format(available))
keyword_knob = nuke.EvalString_Knob("parameter_keyword_{}".format(available),
"Keywords")
remove_knob = nuke.PyScript_Knob("parameter_remove_{}".format(available),
"Remove Parameter",
remove_knob_script)
keyword_knob.clearFlag(nuke.STARTLINE)
remove_knob.clearFlag(nuke.STARTLINE)
remove_knob.setFlag(nuke.ENDLINE)
this_node.addKnob(name_knob)
this_node.addKnob(keyword_knob)
this_node.addKnob(remove_knob)
def bring_knobs_back(removed_knobs):
"""
Bring the knobs back from the dead
The function needs the list returned by the delete_below_knobs() function.
"""
this_node = nuke.thisNode()
for item in removed_knobs:
Class = item["Class"]
name = item["name"]
label = item["label"]
value = item["value"]
tooltip = item["tooltip"]
visible = item["visible"]
# Do not try to evaluate values, the results can be really buggy...
nuke_knob_object = eval("nuke.{}('{}')".format(Class, name))
nuke_knob_object.setValue(value)
nuke_knob_object.setLabel(label)
nuke_knob_object.setTooltip(tooltip)
nuke_knob_object.setVisible(visible)
if name in ("load_parameters", "dispatch_parameters"):
nuke_knob_object.clearFlag(nuke.STARTLINE)
else :
nuke_knob_object.setFlag(nuke.STARTLINE)
if Class == "Array_Knob":
nuke_knob_object.setFlag(0x00000002)
this_node.addKnob(nuke_knob_object)