Adding Presets to Global Context Variables
Global context variables can be useful for ensuring a context variable is always accessible and set for the entire script. Unless it is overridden by a ContextVariables or ContextVariablesTweaks node in the node graph, all nodes will have access to the same global context variable. There are some global context variables added by Gaffer by default when creating a new script. You can see these, and add your own, from the Variables
tab in the Settings
dialog accessed from the File.Settings
menu item.
The default user interface for a global context variable can be useful for many situations, but like all plugs in Gaffer, it is possible to customize how the plugs for global context variables are presented to the user. One such customization is adding presets for the user to choose from. This ensures only valid values can be assigned to the context variable. This guide will describe how to add presets to the widget controlling a global context variable.
Adding Presets to the Settings
Dialog
One way of controlling global context variables is through the Settings
dialog as described above. Presets can be added here by assigning metadata to the value plug for a global context variable. Before we assign metadata, we need to identify which plug represents the context variable you want to add presets to. Global context variables are stored in the variables
child of the script root. In the Python editor, these are accessed by root["variables"]
.
The entries in root["variables"]
are of the type NameValuePlug
. These plugs themselves have three child plugs : name
, enabled
and value
. The name
plug sets the name of the context variable and the value
sets the value of the variable. The enabled
plug is used to enable or disable the variable. Note that the value of name
may be different from the name of the actual NameValuePlug
. When adding plugs in using the +
button in the Settings
dialog, the NameValuePlug
added will start with member
and be followed by the next available number to keep the child names of root["variables"]
unique.
To determine which child of root["variables"]
you want to add metadata to, loop through all the children of root["variables"]
checking the value of the name
plug until you find the variable. The corresponding value
child plug will be the plug we add metadata to.
The first metadata entry will tell Gaffer to use a presets dropdown as the plug widget. That is done by setting plugValueWidget:type
to "GafferUI.PresetsPlugValueWidget"
.
Now we can add the presets themselves. That can be done in one of two ways. You can add a metadata entry starting with preset:
followed by the display string of your preset, the value of which is the preset value. For example, Gaffer.Metadata.registerValue( root["variables"]["member1"]["value"], "preset:Shot 1004", "shot1004")
will create a preset on the member1
plug's value
plug called Shot 1004
. When the user chooses that preset, the actual value of the context variable will be shot1004
.
The second method sets all of the preset names and all of the values in one step each. This can be done by setting the presetNames
metadata entry to a Cortex string vector (IECore.StringVectorData
)holding all of the preset names. Setting presetValues
to a Cortex vector of some type, such as IECoreStringVectorData
or IECoreFloatVectorData
.
Note that the Settings
UI is built once and then reused for subsequent showings. This means after adding presets, you need to force Gaffer to refresh the Settings
dialog. You can force Gaffer to rebuild the Settings
dialog by running the following code in the Python editor :
sw = GafferUI.ScriptWindow.acquire(root) for window in sw.childWindows(): if hasattr( window, "_settingsEditor" ) : sw.removeChild(window)
The following script is an example of all of the above steps condensed into a reusable function for adding presets for a global context variable.
# Sets the preset names and values for a global context variable. # `scriptNode` is the script node which you want to set global context variables for. # `variableName` is the name of the variable to set presets for. # `presetNames` is a list of strings to set the preset names to. # `presetValues` is an `IECore.*VectorData` holding a list of preset values # for each corresponding item in `presetNames` def globalContextPresets( scriptNode, variableName, presetNames, presetValues ) : if len( presetNames ) != len( presetValues ) : raise ValueError( "`presetNames` and `presetValues` must be the same length" ) # Find the value plug for `variableName` global context variable. variablePlug = None for p in scriptNode["variables"] : if p["name"].getValue() == variableName : variablePlug = p["value"] break if variablePlug is None : raise RuntimeError( "\"{}\" not found in global context variables".format( variableName ) ) # Set the widget to a presets dropdown. Gaffer.Metadata.registerValue( variablePlug, "plugValueWidget:type", "GafferUI.PresetsPlugValueWidget" ) # Register the names and values. Gaffer.Metadata.registerValue( variablePlug, "presetNames", IECore.StringVectorData( presetNames ) ) Gaffer.Metadata.registerValue( variablePlug, "presetValues", presetValues ) # Set the value to the first preset. variablePlug.setValue( presetValues[0] ) # Tell Gaffer to rebuild the `Settings` dialog. sw = GafferUI.ScriptWindow.acquire( scriptNode ) for window in sw.childWindows(): if hasattr( window, "_settingsEditor" ) : sw.removeChild(window)
For example, to set a few presets for a global context variable named shot
run the script above in the Python editor, followed by the line below.
globalContextPresets( root, "shot", ["shot A", "shot B", "shot C"], IECore.StringVectorData( [ "shotA", "shotB", "shotC" ] ) )