Create and assign a renderable MaterialX material

# The following is a scripting example of how to create and assign a renderable material
import maya.cmds as cmds
import maya.mel as mel
import ufe

# This example uses multiple different UFE interfaces. Since there are more focused examples for
# most of them, this example won't explain the individual interfaces in detail, but focus on the
# overall task of creating and assigning a renderable material. Check the other examples for more
# details on the individual interfaces.

# Create a stack and a MaterialX document.
stackName = mel.eval("createNode materialxStack")
stackPathString = mel.eval("ls -l " + stackName)[0]
stackItem = ufe.Hierarchy.createItem(ufe.PathString.path(stackPathString))
ufe.ContextOps.contextOps(stackItem).doOp(['MxCreateDocument'])
documentItem = ufe.Hierarchy.hierarchy(stackItem).children()[-1]
runTimeId = documentItem.runTimeId()

# In MaterialX, a document is simply a container. Materials in MaterialX are `ND_surfacematerial`
# nodes within a document. Create a new surfacematerial.
materialNodeDef = ufe.NodeDef.definition(runTimeId, 'ND_surfacematerial')
materialItem = materialNodeDef.createNode(documentItem, ufe.PathComponent('material1'))

# For the material to be renderable, a surfaceshader is needed. Create an OpenPBR surface.
shaderNodeDef = ufe.NodeDef.definition(runTimeId, 'ND_open_pbr_surface_surfaceshader')
shaderItem = shaderNodeDef.createNode(documentItem, ufe.PathComponent('open_pbr_surface1'))

# Connect the surfaceshader to the material.
shaderOutputInfo = ufe.AttributeInfo(shaderItem.path(), 'outputs:out')
materialInputInfo = ufe.AttributeInfo(materialItem.path(), 'inputs:surfaceshader')
connectionHandler = ufe.RunTimeMgr.instance().connectionHandler(runTimeId)
connectionHandler.connect(shaderOutputInfo, materialInputInfo)

# The material is now renderable. To make it stand out more, change the base color to green.
shaderBaseColor = ufe.Attributes.attributes(shaderItem).attribute('inputs:base_color')
shaderBaseColor.set(ufe.Color3f(0, 1, 0))

# MaterialX materials are assigned to native Maya geometry. Create a Maya sphere.
sphereName = cmds.polySphere()[0]
spherePathString = mel.eval("ls -l " + sphereName)[0]
sphereItem = ufe.Hierarchy.createItem(ufe.PathString.path(spherePathString))

# To assign a material to a geometry, the geometry has to be selected. The Maya polySphere() command
# technically already selects the sphere but in order to assign to other geometry it may be necessary
# to select it manually. It's done as follows.
ufe.GlobalSelection.get().clear()
ufe.GlobalSelection.get().append(sphereItem)

# Use the context ops to assign the material to the current selection.
ufe.ContextOps.contextOps(materialItem).doOp(['Assign Material to Selection'])