def arnoldToUsdParamString(paramEntry, scope): ret = '' paramName = ai.AiParamGetName(paramEntry) if paramName == 'name': return '' # nothing to return for attribute 'name' # Add the arnold scope to the attribute namespace, so that the token can be compiled if paramName == 'namespace' and len(scope) == 0: scope = 'arnold:' optionsStr = "customData = {string apiName = \"arnold_%s\"}" % paramName if len(paramName) == 1: paramName = paramName.lower() ''' // TODO: // AI_TYPE_POINTER // AI_TYPE_NODE // AI_TYPE_USHORT // AI_TYPE_HALF // AI_TYPE_UNDEFINED // AI_TYPE_NONE ''' paramType = ai.AiParamGetType(paramEntry) paramDefault = ai.AiParamGetDefault(paramEntry) paramVal = '' optionsStr = '' if paramType != ai.AI_TYPE_ARRAY: typeStr, valueStr, optionsValStr = getParameterStr(paramType, paramDefault, paramEntry) if typeStr is None or typeStr == '': return '' ret += typeStr paramVal = valueStr optionsStr += optionsValStr ret += ' {}{} = {} ({})'.format(scope, paramName, paramVal, optionsStr) else: # Array parameter arrayVal = paramDefault.contents.ARRAY if arrayVal is None or arrayVal[0] is None: return '' arrayVal = arrayVal[0] arrayType = ai.AiArrayGetType(arrayVal) typeStr, valueStr, optionsValStr = getParameterStr(arrayType) if typeStr is None or typeStr == '': return '' ret += '{}[] {}{}'.format(typeStr, scope, paramName) # FIXME do we need to set the API name ? # ret += ' (customData = {string apiName = "arnold{}"}\n'.format(GetCamelCase(paramName)) return ret
while not arnold.AiNodeEntryIteratorFinished( nodeIt ) : nodeEntry = arnold.AiNodeEntryIteratorGetNext( nodeIt ) nodeName = arnold.AiNodeEntryGetName( nodeEntry ) description = __aiMetadataGetStr( nodeEntry, None, "desc" ) if description is not None : __metadata[nodeName]["description"] = description paramIt = arnold.AiNodeEntryGetParamIterator( nodeEntry ) while not arnold.AiParamIteratorFinished( paramIt ) : ## \todo We could allow custom ui types to be specified using # arnold metadata entries. param = arnold.AiParamIteratorGetNext( paramIt ) paramName = arnold.AiParamGetName( param ) paramPath = nodeName + "." + paramName description = __aiMetadataGetStr( nodeEntry, paramName, "desc" ) if description is not None : __metadata[paramPath]["description"] = description paramType = arnold.AiParamGetType( param ) if paramType == arnold.AI_TYPE_ENUM : enum = arnold.AiParamGetEnum( param ) presets = IECore.StringVectorData() while True : preset = arnold.AiEnumGetString( enum, len( presets ) ) if not preset : break
def arnoldToUsdParamString(paramEntry, scope): ret = '' paramName = ai.AiParamGetName(paramEntry) if paramName == 'name': return '' # nothing to return for attribute 'name' # Add the arnold scope to the attribute namespace, so that the token can be compiled if (paramName == 'namespace' or paramName == 'operator') and len(scope) == 0: scope = 'arnold:' if len(paramName) == 1: paramName = paramName.lower() ''' // TODO: // AI_TYPE_POINTER // AI_TYPE_USHORT // AI_TYPE_HALF // AI_TYPE_UNDEFINED // AI_TYPE_NONE ''' paramType = ai.AiParamGetType(paramEntry) paramDefault = ai.AiParamGetDefault(paramEntry) paramVal = '' optionsStr = 'customData = {string apiName = "' optionsStr += makeCamelCase(paramName) optionsStr += '"}' if paramType != ai.AI_TYPE_ARRAY: typeStr, valueStr, optionsValStr = getParameterStr( paramType, paramDefault, paramEntry) if typeStr is None or typeStr == '': return '' ret += typeStr paramVal = valueStr if len(optionsValStr) > 0: if len(optionsStr) > 0: optionsStr = '\n {}{}\n '.format( optionsStr, optionsValStr) else: optionsStr = optionsValStr ret += ' {}{} = {} ({})'.format(scope, paramName, paramVal, optionsStr) else: # Array parameter arrayVal = paramDefault.contents.ARRAY if arrayVal is None or arrayVal[0] is None: return '' arrayVal = arrayVal[0] arrayType = ai.AiArrayGetType(arrayVal) typeStr, valueStr, optionsValStr = getParameterStr(arrayType) if typeStr is None or typeStr == '': return '' if len(optionsValStr) > 0: if len(optionsStr) > 0: optionsStr = '\n {}{}\n '.format( optionsStr, optionsValStr) else: optionsStr = optionsValStr ret += '{}[] {}{} ({})'.format(typeStr, scope, paramName, optionsStr) return ret
# Type of this AtNodeEntry (light, shape, shader, operator, etc...) entryTypeName = str(ai.AiNodeEntryGetTypeName(nentry)) # we don't want to create schemas for shaders, as we're relying on UsdShade schemas if entryTypeName == 'shader': continue # Get the list of parameters for this node entry paramsList = [] # Loop over AtParamEntry for this AtNodeEntry paramsIter = ai.AiNodeEntryGetParamIterator(nentry) while not ai.AiParamIteratorFinished(paramsIter): paramEntry = ai.AiParamIteratorGetNext(paramsIter) # Add this parameter name to our list paramsList.append(ai.AiParamGetName(paramEntry)) ai.AiParamIteratorDestroy(paramsIter) # iterators need to be deleted # Add an element in my list of node entries, with its name, type name, and list of parameters entryList.append([entryName, entryTypeName, paramsList]) if entryByType.get(entryTypeName) is None: # first time we find a node with this type, let's make the dict value a list entryByType[entryTypeName] = [] # Add this node entry to its "type" dictionary entryByType[entryTypeName].append(entryName) if typeParams.get(entryTypeName) is None: # first time we find a node with this type, let's simply copy all parameters for this node entry typeParams[entryTypeName] = paramsList
def __translateNodeMetadata(nodeEntry): nodeName = arnold.AiNodeEntryGetName(nodeEntry) # Shader description. We support Arnold-style "desc" and # OSL style "help". description = __aiMetadataGetStr(nodeEntry, None, "desc", defaultValue=__aiMetadataGetStr( nodeEntry, None, "help")) if description is not None: __metadata[nodeName]["description"] = description # Documentation URL. We support OSL-style "URL" url = __aiMetadataGetStr(nodeEntry, None, "URL") if url is not None: __metadata[nodeName]["documentation:url"] = url havePages = False paramIt = arnold.AiNodeEntryGetParamIterator(nodeEntry) while not arnold.AiParamIteratorFinished(paramIt): ## \todo We could allow custom ui types to be specified using # arnold metadata entries. param = arnold.AiParamIteratorGetNext(paramIt) paramName = arnold.AiParamGetName(param) paramPath = nodeName + ".parameters." + paramName # Parameter description description = __aiMetadataGetStr(nodeEntry, paramName, "desc") if description is not None: __metadata[paramPath]["description"] = description # Parameter presets from enum values paramType = arnold.AiParamGetType(param) if paramType == arnold.AI_TYPE_ENUM: enum = arnold.AiParamGetEnum(param) presets = IECore.StringVectorData() while True: preset = arnold.AiEnumGetString(enum, len(presets)) if not preset: break presets.append(preset) __metadata[paramPath][ "plugValueWidget:type"] = "GafferUI.PresetsPlugValueWidget" __metadata[paramPath]["presetNames"] = presets __metadata[paramPath]["presetValues"] = presets # Nodule type from linkable metadata and parameter type linkable = __aiMetadataGetBool( nodeEntry, paramName, "linkable", defaultValue=paramType not in (arnold.AI_TYPE_BYTE, arnold.AI_TYPE_INT, arnold.AI_TYPE_UINT, arnold.AI_TYPE_BOOLEAN, arnold.AI_TYPE_ENUM, arnold.AI_TYPE_STRING)) __metadata[paramPath][ "nodule:type"] = "GafferUI::StandardNodule" if linkable else "" # PlugValueWidget type from OSL "widget" widget = None widget = __aiMetadataGetStr(nodeEntry, paramName, "widget", widget) if widget is not None: __metadata[paramPath]["plugValueWidget:type"] = { "number": "GafferUI.NumericPlugValueWidget", "string": "GafferUI.StringPlugValueWidget", "boolean": "GafferUI.BoolPlugValueWidget", "checkBox": "GafferUI.BoolPlugValueWidget", "popup": "GafferUI.PresetsPlugValueWidget", "mapper": "GafferUI.PresetsPlugValueWidget", "filename": "GafferUI.PathPlugValueWidget", "null": "", }[widget] # Layout section from OSL "page". page = __aiMetadataGetStr(nodeEntry, paramName, "page") if page is not None: havePages = True __metadata[paramPath]["layout:section"] = page # Label from OSL "label" label = __aiMetadataGetStr(nodeEntry, paramName, "label") if label is not None: __metadata[paramPath]["label"] = label elif "_" in paramName: # Label from Arnold naming convention # Arnold uses snake_case rather than camelCase for naming, so translate this into # nice looking names __metadata[paramPath]["label"] = " ".join( [i.capitalize() for i in paramName.split("_")]) # NodeGraph visibility from Gaffer-specific metadata visible = __aiMetadataGetBool( nodeEntry, None, "gaffer.nodeGraphLayout.defaultVisibility") visible = __aiMetadataGetBool(nodeEntry, paramName, "gaffer.nodeGraphLayout.visible", visible) if visible is not None: __metadata[paramPath]["noduleLayout:visible"] = visible
def __translateNodeMetadata(nodeEntry): nodeName = arnold.AiNodeEntryGetName(nodeEntry) # Shader description. We support Arnold-style "desc" and # OSL style "help". description = __aiMetadataGetStr(nodeEntry, None, "desc", defaultValue=__aiMetadataGetStr( nodeEntry, None, "help")) if description is not None: __metadata[nodeName]["description"] = description # Documentation URL. We support OSL-style "URL" url = __aiMetadataGetStr(nodeEntry, None, "URL") if url is not None: __metadata[nodeName]["documentation:url"] = url # Icon. There doesn't appear to be a standard for this, so # we support "gaffer.icon" and "gaffer.iconScale". icon = __aiMetadataGetStr(nodeEntry, None, "gaffer.icon") if icon is not None: __metadata[nodeName]["icon"] = icon iconScale = __aiMetadataGetFlt(nodeEntry, None, "gaffer.iconScale") if iconScale is not None: __metadata[nodeName]["iconScale"] = iconScale paramIt = arnold.AiNodeEntryGetParamIterator(nodeEntry) while not arnold.AiParamIteratorFinished(paramIt): ## \todo We could allow custom ui types to be specified using # arnold metadata entries. param = arnold.AiParamIteratorGetNext(paramIt) paramName = arnold.AiParamGetName(param) paramPath = nodeName + ".parameters." + paramName paramType = arnold.AiParamGetType(param) # Parameter description description = __aiMetadataGetStr(nodeEntry, paramName, "desc") if description is not None: __metadata[paramPath]["description"] = description # Presets if paramType == arnold.AI_TYPE_ENUM: # Parameter presets from enum values presetValues = __enumPresetValues(param) presetNames = presetValues else: # Manually specified presets for other types presetValues = __plugPresetValues(nodeEntry, paramName, paramType) presetNames = __plugPresetNames(nodeEntry, paramName) if presetValues: __metadata[paramPath][ "plugValueWidget:type"] = "GafferUI.PresetsPlugValueWidget" __metadata[paramPath]["presetValues"] = presetValues __metadata[paramPath]["presetNames"] = presetNames # Nodule type from linkable metadata and parameter type linkable = __aiMetadataGetBool( nodeEntry, paramName, "linkable", defaultValue=paramType not in (arnold.AI_TYPE_BYTE, arnold.AI_TYPE_INT, arnold.AI_TYPE_UINT, arnold.AI_TYPE_BOOLEAN, arnold.AI_TYPE_ENUM, arnold.AI_TYPE_STRING)) __metadata[paramPath]["nodule:type"] = None if linkable else "" # PlugValueWidget type from OSL "widget" widget = None widget = __aiMetadataGetStr(nodeEntry, paramName, "widget", widget) if widget is not None: __metadata[paramPath]["plugValueWidget:type"] = { "number": "GafferUI.NumericPlugValueWidget", "string": "GafferUI.StringPlugValueWidget", "boolean": "GafferUI.BoolPlugValueWidget", "checkBox": "GafferUI.BoolPlugValueWidget", "popup": "GafferUI.PresetsPlugValueWidget", "mapper": "GafferUI.PresetsPlugValueWidget", "filename": "GafferUI.PathPlugValueWidget", "null": "", }[widget] # Layout section from OSL "page". page = __aiMetadataGetStr(nodeEntry, paramName, "page") if page is not None: __metadata[paramPath]["layout:section"] = page # Uncollapse sections if desired collapsed = __aiMetadataGetBool( nodeEntry, None, "gaffer.layout.section.%s.collapsed" % page) if collapsed == False: parent = paramPath.rsplit('.', 1)[0] __metadata[parent]["layout:section:%s:collapsed" % page] = collapsed # Label from OSL "label" label = __aiMetadataGetStr(nodeEntry, paramName, "label") if label is None: # Label from Arnold naming convention # Arnold uses snake_case rather than camelCase for naming, so translate this into # nice looking names label = " ".join([i.capitalize() for i in paramName.split("_")]) __metadata[paramPath]["label"] = label __metadata[paramPath]["noduleLayout:label"] = label childComponents = { arnold.AI_TYPE_VECTOR2: "xy", arnold.AI_TYPE_VECTOR: "xyz", arnold.AI_TYPE_RGB: "rgb", arnold.AI_TYPE_RGBA: "rgba", }.get(paramType) if childComponents is not None: for c in childComponents: __metadata["{}.{}".format( paramPath, c)]["noduleLayout:label"] = "{}.{}".format(label, c) # NodeEditor layout from other Gaffer-specific metadata divider = __aiMetadataGetBool(nodeEntry, paramName, "gaffer.layout.divider") if divider: __metadata[paramPath]["layout:divider"] = True index = __aiMetadataGetInt(nodeEntry, paramName, "gaffer.layout.index") if index is not None: __metadata[paramPath]["layout:index"] = index # GraphEditor visibility from Gaffer-specific metadata visible = __aiMetadataGetBool( nodeEntry, None, "gaffer.graphEditorLayout.defaultVisibility") visible = __aiMetadataGetBool(nodeEntry, paramName, "gaffer.graphEditorLayout.visible", visible) if visible is not None: __metadata[paramPath]["noduleLayout:visible"] = visible userDefault = None if paramType in [ arnold.AI_TYPE_BYTE, arnold.AI_TYPE_INT, arnold.AI_TYPE_UINT ]: userDefault = __aiMetadataGetInt(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_BOOLEAN: userDefault = __aiMetadataGetBool(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_FLOAT: userDefault = __aiMetadataGetFlt(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_RGB: userDefault = __aiMetadataGetRGB(nodeEntry, paramName, "gaffer.userDefault") #elif paramType == arnold.AI_TYPE_RGBA: # userDefault = __aiMetadataGetRGBA( nodeEntry, paramName, "gaffer.userDefault" ) elif paramType == arnold.AI_TYPE_VECTOR: userDefault = __aiMetadataGetVec(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_VECTOR2: userDefault = __aiMetadataGetVec2(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_STRING: userDefault = __aiMetadataGetStr(nodeEntry, paramName, "gaffer.userDefault") elif paramType == arnold.AI_TYPE_ENUM: userDefault = __aiMetadataGetStr(nodeEntry, paramName, "gaffer.userDefault") if userDefault: nodeName, _, plugName = paramPath.split(".") Gaffer.Metadata.registerValue( "ai:surface:%s:%s" % (nodeName, plugName), "userDefault", userDefault)
def __translateNodeMetadata( nodeEntry ) : nodeName = arnold.AiNodeEntryGetName( nodeEntry ) # Shader description. We support Arnold-style "desc" and # OSL style "help". description = __aiMetadataGetStr( nodeEntry, None, "desc", defaultValue = __aiMetadataGetStr( nodeEntry, None, "help" ) ) if description is not None : __metadata[nodeName]["description"] = description # Documentation URL. We support OSL-style "URL" and # Houdini-style "help_url". url = __aiMetadataGetStr( nodeEntry, None, "URL", defaultValue = __aiMetadataGetStr( nodeEntry, None, "houdini.help_url" ) ) if url is not None : __metadata[nodeName]["documentation:url"] = url havePages = False paramIt = arnold.AiNodeEntryGetParamIterator( nodeEntry ) while not arnold.AiParamIteratorFinished( paramIt ) : ## \todo We could allow custom ui types to be specified using # arnold metadata entries. param = arnold.AiParamIteratorGetNext( paramIt ) paramName = arnold.AiParamGetName( param ) paramPath = nodeName + ".parameters." + paramName # Parameter description description = __aiMetadataGetStr( nodeEntry, paramName, "desc" ) if description is not None : __metadata[paramPath]["description"] = description # Parameter presets from enum values paramType = arnold.AiParamGetType( param ) if paramType == arnold.AI_TYPE_ENUM : enum = arnold.AiParamGetEnum( param ) presets = IECore.StringVectorData() while True : preset = arnold.AiEnumGetString( enum, len( presets ) ) if not preset : break presets.append( preset ) __metadata[paramPath]["plugValueWidget:type"] = "GafferUI.PresetsPlugValueWidget" __metadata[paramPath]["presetNames"] = presets __metadata[paramPath]["presetValues"] = presets # Nodule type from linkable metadata and parameter type linkable = __aiMetadataGetBool( nodeEntry, paramName, "linkable", defaultValue = paramType not in ( arnold.AI_TYPE_BYTE, arnold.AI_TYPE_INT, arnold.AI_TYPE_UINT, arnold.AI_TYPE_BOOLEAN, arnold.AI_TYPE_ENUM, arnold.AI_TYPE_STRING ) ) __metadata[paramPath]["nodule:type"] = "GafferUI::StandardNodule" if linkable else "" # PlugValueWidget type from OSL "widget" or "houdini.type". widget = None if __aiMetadataGetStr( nodeEntry, paramName, "houdini.type" ) == "file:image" : widget = "filename" widget = __aiMetadataGetStr( nodeEntry, paramName, "widget", widget ) if widget is not None : __metadata[paramPath]["plugValueWidget:type"] = { "number" : "GafferUI.NumericPlugValueWidget", "string" : "GafferUI.StringPlugValueWidget", "boolean" : "GafferUI.BoolPlugValueWidget", "checkBox" : "GafferUI.BoolPlugValueWidget", "popup" : "GafferUI.PresetsPlugValueWidget", "mapper" : "GafferUI.PresetsPlugValueWidget", "filename" : "GafferUI.PathPlugValueWidget", "null" : "", }[widget] # Layout section from OSL "page". page = __aiMetadataGetStr( nodeEntry, paramName, "page" ) if page is not None : havePages = True __metadata[paramPath]["layout:section"] = page # Label from OSL "label" or "houdini.label". label = __aiMetadataGetStr( nodeEntry, paramName, "houdini.label" ) label = __aiMetadataGetStr( nodeEntry, paramName, "label", label ) if label is not None : __metadata[paramPath]["label"] = label # NodeGraph visibility from Gaffer-specific metadata visible = __aiMetadataGetBool( nodeEntry, None, "gaffer.nodeGraphLayout.defaultVisibility" ) visible = __aiMetadataGetBool( nodeEntry, paramName, "gaffer.nodeGraphLayout.visible", visible ) if visible is not None : __metadata[paramPath]["noduleLayout:visible"] = visible # If we haven't seen any nice sane OSL "page" metadata, then have # a go at translating the houdini layout metadata. Surely one of the # most tortured ways of defining a UI ever. if not havePages : __translateHoudiniLayout( nodeEntry )
def __translateHoudiniLayout( nodeEntry ) : # Houdini defines UI groupings through the use of extra # parameters with special types, which HtoA allows the # user to define via metadata on the Arnold shader. Grab # all those extra parameters. Parameter = collections.namedtuple( "Parameter", [ "name", "type", "contents" ] ) parameters = collections.OrderedDict() metaIt = arnold.AiNodeEntryGetMetaDataIterator( nodeEntry ) while not arnold.AiMetaDataIteratorFinished( metaIt ) : metadata = arnold.AiMetaDataIteratorGetNext( metaIt ) m = re.match( "houdini\.parm\.([^.]*)\.([^.]+)", metadata.contents.name ) if m : parameters[m.group(2)] = Parameter( m.group(2), m.group(1), __aiMetadataGetStr( nodeEntry, None, m.group(0) ) ) arnold.AiMetaDataIteratorDestroy( metaIt ) # Add on all the regular Arnold parameters. paramIt = arnold.AiNodeEntryGetParamIterator( nodeEntry ) while not arnold.AiParamIteratorFinished( paramIt ) : parameterName = arnold.AiParamGetName( arnold.AiParamIteratorGetNext( paramIt ) ) if parameterName != "name" : parameters[parameterName] = Parameter( parameterName, "arnold", "" ) arnold.AiParamIteratorDestroy( paramIt ) # Now, reorder the parameters according to the # houdini.order metadata. There seem to be two # different styles for doing this. For instance, # the HtoA metadata for "image" and "barndoor" # orders everything once with a single "order" # entry, even though different parameters are # destined for different tabs. The AlShader and # other HtoA metadata on the other hand seems # to use "order", "order2" ... "orderN" where # the numeric suffices map to tabs. So we try # to support both. orderedParameters = [] i = 1 while True : order = __aiMetadataGetStr( nodeEntry, None, "houdini.order%s" % ( str( i ) if i > 1 else "" ) ) if order is None : break for parameterName in order.split() : parameter = parameters.pop( parameterName, None ) if parameter is not None : orderedParameters.append( parameter ) else : # Tolerate non-existent parameters being listed # in the order metadata, for the sake of AlShaders. pass i += 1 # Any parameters not ordered explicitly go on the end. orderedParameters.extend( parameters.values() ) # Now we can set up the layout:index metadata from # the parameter order. nodeName = arnold.AiNodeEntryGetName( nodeEntry ) for i, parameter in enumerate( orderedParameters ) : __metadata[nodeName+".parameters."+parameter.name]["layout:index"] = i # Finally, we can recurse over all the parameters, # using the special parameters to figure out the section # metadata that applies to the regular parameters. __walkHoudiniParameters( nodeEntry, orderedParameters, sectionName = "" )
with IECoreArnold.UniverseBlock(): nodeIt = arnold.AiUniverseGetNodeEntryIterator(arnold.AI_NODE_SHADER | arnold.AI_NODE_LIGHT) while not arnold.AiNodeEntryIteratorFinished(nodeIt): nodeEntry = arnold.AiNodeEntryIteratorGetNext(nodeIt) nodeName = arnold.AiNodeEntryGetName(nodeEntry) paramIt = arnold.AiNodeEntryGetParamIterator(nodeEntry) while not arnold.AiParamIteratorFinished(paramIt): ## \todo We could allow custom ui types to be specified using # arnold metadata entries. param = arnold.AiParamIteratorGetNext(paramIt) paramPath = nodeName + "." + arnold.AiParamGetName(param) paramType = arnold.AiParamGetType(param) if paramType == arnold.AI_TYPE_ENUM: enum = arnold.AiParamGetEnum(param) namesAndValues = [] while True: enumLabel = arnold.AiEnumGetString(enum, len(namesAndValues)) if not enumLabel: break namesAndValues.append((enumLabel, enumLabel)) __plugValueWidgetCreators[paramPath] = ( GafferUI.EnumPlugValueWidget, namesAndValues)