State:Closed|icon_bug|icon_katana|database:public|Resolution:Fixed|TargetRelease:2.5v5|BugID:241373|
Problem summary:
When exposing a shader parameter that uses a Float Ramp or Color Ramp widget, not all of its sibling parameters are exposed as well, making it impossible to edit such a parameter using downstream Material nodes in edit mode.
Steps to reproduce:
Expected behaviour:
A Float Ramp widget is shown for the Falloff parameter.
Actual behaviour:
An error message is shown for the Falloff parameter:
Workaround:
Scripted workaround:
"""NAME: Update Ramp Widget Sibling ParametersICON: icon.pngSCOPE: PrmanShadingNodeModifies widget hints of parameters that are siblings of ramp parameters, sothat ramps can be modified by Material nodes in edit mode downstream."""import sys # for sys.exit()# Sanity-check that the node for which this shelf item script is run is a# PrmanShadingNode nodeif not node.getType() == 'PrmanShadingNode': print('This shelf item script can only be run for PrmanShadingNode nodes.') sys.exit(0)def GetParameterHints(parameter): """ @type parameter: C{NodegraphAPI.Parameter} @rtype: C{dict} or C{None} @param parameter: The parameter whose widget hints to return. @return: The given parameter's widget hints as a Python dictionary, or C{None} if widget hints are not available or could not be decoded. """ # Check if hints are available for the current parameter, by way of a child # parameter named "hints" of type string hintsParameter = parameter.getChild('hints') if hintsParameter is None or hintsParameter.getType() != 'string': return None # Evaluate the hints parameter's value as a Python object hintsString = hintsParameter.getValue(0) if hintsString: try: hints = eval(hintsString) except: print('The string value of child parameter "hints" of parameter ' '"%s" does not evaluate to a Python object: "%s"' % (parameter.getName(), hintsString)) return None else: return {} # Check if the evaluated hints parameter's value is a Python dictionary if not isinstance(hints, dict): print('The string value of child parameter "hints" of parameter "%s" ' 'does not evaluate to a Python dictionary.' % parameter.getName()) return None return hints# Obtain the group parameter that contains the PrmanShadingNode node's shader# parametersparametersParameter = node.getParameter('parameters')if parametersParameter is None: print('Required parameter "parameters" not found on PrmanShadingNode node ' '"%s".' % node.getName()) sys.exit(0)# Iterate over the shader parameters of the PrmanShadingNode nodefor parameter in parametersParameter.getChildren(): # Obtain the current parameter's widget hints as a Python dictionary hints = GetParameterHints(parameter) if hints is None: continue # Check if the current parameter is exposed in the material interface (as # controlled through a destination name widget hint) dstName = hints.get('dstName') # Obtain the widget hints of the current parameter via a parameter policy parameterPolicy = UI4.FormMaster.CreateParameterPolicy(None, parameter) if parameterPolicy is None: continue hints = parameterPolicy.getWidgetHints() if not hints or not 'widget' in hints: continue # Check if the current parameter is hinted to use a float ramp or color # ramp widget if not hints['widget'] in ('floatRamp', 'colorRamp'): continue parameterName = parameter.getName() if dstName: print('Parameter "%s" is a ramp parameter. Its sibling parameters ' 'should be exposed via widget hints as well. The destination ' 'name is "%s".' % (parameterName, dstName)) else: print('Parameter "%s" is a ramp parameter. Its sibling parameters ' 'should not be exposed via widget hints.' % parameterName) # Iterate over names of sibling parameters and update their widget hints in # order to expose them alongside the main parameter siblingParameterNames = ['%s_Knots' % parameterName, ('%s_Floats' % parameterName if hints['widget'] == 'floatRamp' else '%s_Colors' % parameterName), '%s_Interpolation' % parameterName] for siblingParameterName in siblingParameterNames: # Get the sibling parameter by its name siblingParameter = parametersParameter.getChild(siblingParameterName) if siblingParameter is None: print('Sibling parameter "%s" was not found.' % siblingParameterName) continue if dstName is not None: # Set the name to use for exposing the sibling parameter according # to the name under which the main parameter is exposed (which may # be different from its actual name) siblingParameterDstName = siblingParameterName.replace( parameterName, dstName) else: siblingParameterDstName = None # Obtain the sibling parameter's widget hints as a Python dictionary hints = GetParameterHints(siblingParameter) if hints is None: if siblingParameterDstName is not None: # Create a "hints" child parameter to expose the current # sibling parameter in the material interface print('Creating "hints" child parameter for sibling parameter ' '"%s"...' % siblingParameterName) siblingParameter.createChildString( 'hints', repr({'dstName': siblingParameterDstName})) else: print('Nothing to do for sibling parameter "%s". No widget ' 'hints are set.' % siblingParameterName) elif siblingParameterDstName is not None: if hints.get('dstName') != siblingParameterDstName: # Update the "hints" child parameter to expose the current # sibling parameter in the material interface hintsParameter = siblingParameter.getChild('hints') if hintsParameter is not None: print('Updating "hints" child parameter for sibling ' 'parameter "%s"...' % siblingParameterName) hints['dstName'] = siblingParameterDstName hintsParameter.setValue(repr(hints), 0) else: print('ERROR: Unable to find "hints" child parameter for ' 'sibling parameter "%s".' % siblingParameterName) else: print('Nothing to do for sibling parameter "%s". Destination ' 'name in widget hints is already up-to-date.' % siblingParameterName) else: if hints.get('dstName') is not None: # Update the "hints" child parameter to expose the current # sibling parameter in the material interface hintsParameter = siblingParameter.getChild('hints') if hintsParameter is not None: del hints['dstName'] if hints: print('Updating "hints" child parameter for sibling ' 'parameter "%s"...' % siblingParameterName) hintsParameter.setValue(repr(hints), 0) else: print('Removing "hints" child parameter from sibling ' 'parameter "%s"...' % siblingParameterName) siblingParameter.deleteChild(hintsParameter) else: print('ERROR: Unable to find "hints" child parameter for ' 'sibling parameter "%s".' % siblingParameterName) else: print('Nothing to do for sibling parameter "%s". Widget hints ' 'do not define a destination name.' % siblingParameterName) Manual workaround:
Reproduced versions/platforms:
Customer version/platform:
2.5v4/Linux
We're sorry to hear that
Please tell us why