Create and assign a renderable USD material

# The following is a scripting example of how to create and assign a renderable material
import ufe
import mayaUsd_createStageWithNewLayer

# 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 stage and a USD material.
stagePathString = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
stageItem = ufe.Hierarchy.createItem(ufe.PathString.path(stagePathString))
ufe.ContextOps.contextOps(stageItem).doOp(['Add New Prim', 'Material'])
materialItem = ufe.Hierarchy.hierarchy(stageItem).children()[-1]

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

# Connect the surfaceshader to the material.
# Note: Usually connections are `output -> input`, but when connecting a port of a node to a port of
# the node's parent compound, it's possible to have `input -> input` and `output -> output`
# connections.
shaderOutputInfo = ufe.AttributeInfo(shaderItem.path(), 'outputs:out')
materialOutputInfo = ufe.AttributeInfo(materialItem.path(), 'outputs:surface')
connectionHandler = ufe.RunTimeMgr.instance().connectionHandler(runTimeId)
connectionHandler.connect(shaderOutputInfo, materialOutputInfo)

# 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))

# Create geometry to assign the material to.
ufe.ContextOps.contextOps(stageItem).doOp(['Add New Prim', 'Sphere'])
sphereItem = ufe.Hierarchy.hierarchy(stageItem).children()[-1]

# To assign a material to a geometry, the geometry has to be selected. The previous 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'])