def appendShaders(menuDefinition, prefix="/Arnold"): with IECoreArnold.UniverseBlock(): it = arnold.AiUniverseGetNodeEntryIterator(arnold.AI_NODE_SHADER | arnold.AI_NODE_LIGHT) while not arnold.AiNodeEntryIteratorFinished(it): nodeEntry = arnold.AiNodeEntryIteratorGetNext(it) shaderName = arnold.AiNodeEntryGetName(nodeEntry) displayName = " ".join( [IECore.CamelCase.toSpaced(x) for x in shaderName.split("_")]) if arnold.AiNodeEntryGetType(nodeEntry) == arnold.AI_NODE_SHADER: menuPath = prefix + "/Shader/" + displayName nodeType = GafferArnold.ArnoldShader else: menuPath = prefix + "/Light/" + displayName nodeType = GafferArnold.ArnoldLight menuDefinition.append( menuPath, { "command": GafferUI.NodeMenu.nodeCreatorWrapper( IECore.curry(__shaderCreator, shaderName, nodeType)), }) arnold.AiNodeEntryIteratorDestroy(it) arnold.AiEnd()
def testLoadAllLightsWithoutWarnings( self ) : lightNames = [] with IECoreArnold.UniverseBlock( writable = False ) : it = arnold.AiUniverseGetNodeEntryIterator( arnold.AI_NODE_LIGHT ) while not arnold.AiNodeEntryIteratorFinished( it ) : nodeEntry = arnold.AiNodeEntryIteratorGetNext( it ) lightNames.append( arnold.AiNodeEntryGetName( nodeEntry ) ) self.longMessage = True for lightName in lightNames : with IECore.CapturingMessageHandler() as mh : l = GafferArnold.ArnoldLight() l.loadShader( lightName ) self.assertEqual( [ m.message for m in mh.messages ], [], "Error loading %s" % lightName )
if arnold.AiMetaDataGetStr( nodeEntry, paramName, name, value ) : return value.value return None ########################################################################## # Build a registry of information retrieved from Arnold metadata. We fill this # once at startup, as we can only get it from within an AiUniverse block, # and we don't want to have to keep making those temporarily later. ########################################################################## __metadata = collections.defaultdict( dict ) 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 ) 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 )
That's not a simple information to get from Arnold as there's no API to get info about a node entry type. So below we're going to list the arnold node entries, check their type and list of parameters. For example, in order to get the list of parameters for "ArnoldLight", we're going to compute the union of all parameters for in "ArnoldSkydomeLight", "ArnoldDistantLight", "ArnoldPointLight", "ArnoldQuadLight", etc... In theory we should also compare the parameter types and their default values, from AFAIK we shouldn't have this problem in the current set of arnold nodes ''' ai.AiBegin() entryList = [] # list of [nodeEntryName, nodeEntryTypeName, parametersList ] entryByType = { } # dictionary (key= nodeEntryTypeName, value=list of nodeEntryName for this type) typeParams = { } # dictionary (key=nodeEntryTypeName, value= list of parameters which exist in ALL the corresponding nodeEntryName) # Loop over node entries nodeEntryIter = ai.AiUniverseGetNodeEntryIterator(ai.AI_NODE_ALL) while not ai.AiNodeEntryIteratorFinished(nodeEntryIter): nentry = ai.AiNodeEntryIteratorGetNext(nodeEntryIter) # Name of this AtNodeEntry (distant_light, skydome_light, etc...) entryName = str(ai.AiNodeEntryGetName(nentry)) # 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 = []
def appendShaders(menuDefinition, prefix="/Arnold"): MenuItem = collections.namedtuple("MenuItem", ["menuPath", "nodeCreator"]) # Build a list of menu items we want to create. categorisedMenuItems = [] uncategorisedMenuItems = [] with IECoreArnold.UniverseBlock(writable=False): it = arnold.AiUniverseGetNodeEntryIterator(arnold.AI_NODE_SHADER | arnold.AI_NODE_LIGHT) while not arnold.AiNodeEntryIteratorFinished(it): nodeEntry = arnold.AiNodeEntryIteratorGetNext(it) shaderName = arnold.AiNodeEntryGetName(nodeEntry) displayName = " ".join( [IECore.CamelCase.toSpaced(x) for x in shaderName.split("_")]) category = __aiMetadataGetStr(nodeEntry, "", "gaffer.nodeMenu.category") if category == "": continue if arnold.AiNodeEntryGetType(nodeEntry) == arnold.AI_NODE_SHADER: menuPath = "Shader" if shaderName == "light_blocker": nodeCreator = functools.partial( __shaderCreator, shaderName, GafferArnold.ArnoldLightFilter) else: nodeCreator = functools.partial(__shaderCreator, shaderName, GafferArnold.ArnoldShader) else: menuPath = "Light" if shaderName != "mesh_light": nodeCreator = functools.partial(__shaderCreator, shaderName, GafferArnold.ArnoldLight) else: nodeCreator = GafferArnold.ArnoldMeshLight if category: menuPath += "/" + category.strip("/") menuPath += "/" + displayName if category: categorisedMenuItems.append(MenuItem(menuPath, nodeCreator)) else: uncategorisedMenuItems.append(MenuItem(menuPath, nodeCreator)) arnold.AiNodeEntryIteratorDestroy(it) # Tidy up uncategorised shaders into a submenu if necessary. rootsWithCategories = set( [m.menuPath.partition("/")[0] for m in categorisedMenuItems]) for i, menuItem in enumerate(uncategorisedMenuItems): s = menuItem.menuPath.split("/") if s[0] in rootsWithCategories: uncategorisedMenuItems[i] = MenuItem( "/".join([s[0], "Other", s[1]]), menuItem.nodeCreator) # Create the actual menu items. for menuItem in categorisedMenuItems + uncategorisedMenuItems: menuDefinition.append( prefix + "/" + menuItem.menuPath, { "command": GafferUI.NodeMenu.nodeCreatorWrapper(menuItem.nodeCreator), "searchText": "ai" + menuItem.menuPath.rpartition("/")[2].replace(" ", ""), })
"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) with IECoreArnold.UniverseBlock(writable=False): nodeIt = arnold.AiUniverseGetNodeEntryIterator( arnold.AI_NODE_SHADER | arnold.AI_NODE_LIGHT | arnold.AI_NODE_COLOR_MANAGER) while not arnold.AiNodeEntryIteratorFinished(nodeIt): __translateNodeMetadata(arnold.AiNodeEntryIteratorGetNext(nodeIt)) ########################################################################## # Gaffer Metadata queries. These are implemented using the preconstructed # registry above. ########################################################################## def __nodeDescription(node): if isinstance(node, GafferArnold.ArnoldShader): return __metadata[node["name"].getValue()].get(