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 )
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 ) paramName = arnold.AiParamGetName( param ) paramPath = nodeName + "." + paramName
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 = [] # Loop over AtParamEntry for this AtNodeEntry paramsIter = ai.AiNodeEntryGetParamIterator(nentry)
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(" ", ""), })
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 with IECoreArnold.UniverseBlock(writable=False): nodeIt = arnold.AiUniverseGetNodeEntryIterator(arnold.AI_NODE_SHADER | arnold.AI_NODE_LIGHT) 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( "description", """Loads shaders for use in Arnold renders. Use the ShaderAssignment node to assign shaders to objects in the scene.""", ) else: