ID 241373 - Shader parameters that use Float Ramp or Color Ramp widgets cannot be edited in downstream Material nodes in edit mode

Follow

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:

  1. Launch KATANA in an environment with PRMan 21.1 available.
  2. Create a PrmanShadingNode node and set its edit flag to edit its parameters.
    1. Set the nodeType parameter to PxrBlockerLightFilter.
    2. Expose the Falloff parameter:
      1. Expand the parameter.
      2. Click its Edit Parameter button (the one with the wrench icon on the right-hand side).
      3. Choose Edit Parameter Name in Material Interface.
      4. Enter a Name, e.g. falloff, and click OK.
  3. Create a NetworkMaterial node and set its edit flag to edit its parameters.
    1. Add a prmanLightfilter terminal.
      1. Click Add Terminal.
      2. In the prman section of the menu, choose lightfilter.
  4. Connect the output of the PrmanShadingNode node to the prmanLightfilter terminal of the NetworkMaterial node.
  5. Create a Material node and set its edit flag to edit its parameters.
  6. Connect the output of the NetworkMaterial node to the input of the Material node.
  7. Drag the NetworkMaterial node onto the Material node, and in the NetworkMaterial Drop dialog, click OK to confirm the selected edit: NetworkMaterial action.
  8. In the Parameters tab, expand the Falloff parameter in the parameters group.

Expected behaviour:

A Float Ramp widget is shown for the Falloff parameter.

Actual behaviour:

An error message is shown for the Falloff parameter:

  • The structure of the "edit_NetworkMaterial.shaders.parameters.Falloff.falloff" parameter does not follow the parameter convention for "floatRamp" widgets.

Workaround:

Scripted workaround:

  • Save the project.
  • Download the following Python script, and save it as ShelvesNodeSpecific/<shelf name>/Update_Ramp_Widget_Sibling_Parameters.py in a directory whose path is added to KATANA_RESOURCES.
  • Restart KATANA.
  • Set the edit flag on the PrmanShadingNode node.
  • In the Parameters tab, execute the Update Ramp Widget Sibling Parameters shelf item script from the Shelf Actions button.
  • Set the edit flag back to the Material node to check if the Falloff parameter is now shown with a Float Ramp widget.

"""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:

  • In the Shading Node's parameter interface, use the node-level wrench menu to 'Show Hidden Parameters'.
  • Expose each of the parameter dependencies, normally the parameter name and a suffix such as '_Knots', 'Floats', ''Colors' or 'Interpolation', using the same naming convention.

Reproduced versions/platforms:

  • 2.5v4/Linux

Customer version/platform:

2.5v4/Linux

    We're sorry to hear that

    Please tell us why