You're reading from Maya Programming with Python Cookbook
In the previous chapter, we looked at how to manipulate geometry with script. However, for most projects, creating the models is only the first step. Unless you want everything to look like boring gray plastic, you'll need to layout UVs, then create and apply shading networks.
In this chapter, we will be looking at how to do just that.
In this example, we will be looking at how to get information about UVs on a polygonal object. We will look at examining how many UV sets the object contains, getting the UVs for a given part of the object, and grabbing the position of a given UV point.
We will also look at how to convert one kind of selection to another and use that to determine if a given edge can be split or not.
Make sure that you have a scene that contains at least one polygonal object that has UVs—either an object that you have unwrapped or any of the built-in primitive shapes, which have UVs by default.
Create a new file, name it uvInfo.py
(or similar), and add the following code:
import maya.cmds as cmds def uvInfo(): sel = cmds.ls(selection=True) obj = sel[0] uvs = cmds.polyEvaluate(obj, uvComponent=True) uvPos = cmds.polyEditUV(obj + '.map[0]', query=True) isFirstEdgeSplit = isSplitEdge(obj, 0) print('Num UVs: ' + str(uvs)) print(...
In this example, we will look at how to actually lay out UVs using Python. We will be applying planar, cylindrical, and spherical projections, each to a different subset of the faces of the selected object.
Make sure that you have a scene containing a polygonal object. We will be applying three different mappings to different parts of the object (selected by dividing the total number of faces by three), so it is best to have an object with at least a few dozen faces. If you do not have a model handy, make a polygonal sphere of at least 10 or so divisions along both height and axis.
Create a new script and add the following code:
import maya.cmds as cmds def layoutUVs(): selected = cmds.ls(selection=True) obj = selected[0] totalFaces = cmds.polyEvaluate(obj, face=True) oneThird = totalFaces/3 startFace = 0 endFace = oneThird - 1 cmds.polyProjection(obj + '.f[' + str(startFace) + ':' + str(endFace) + ']',...
In this example, we'll be looking at how to create shading networks with code. We'll be creating a simple toon shader, with a solid color in the interior and a different color at the edges of the object. There are a few different ways to do this, including by creating a rampShader, but we'll be doing it in the somewhat old-fashioned way using a samplerInfo node, as it provides a great example of a relatively simple yet somewhat novel shading network.
First off, let's have a look at what our shader will do and how it will do it. The key characteristic of a toon shader is that the object has an outline around its edges that changes as the object moves. So, the first thing we'll need is some way of knowing what the angle is between a given part of the model and the camera. Luckily, Maya provides a utility node that does just that in the form of samplerInfo. SamplerInfo nodes provide us with a facingRatio
attribute that ranges from 0 (when a surface is perpendicular...
Once you have a shading network created, you'll generally want to apply it to one or more objects. In this example, we'll be looking at how to do it. Along the way, we'll create a script that can be used to apply a shader to all of the objects in the scene that are without one.
Make sure that you have a scene with a few different objects in it. Select a few objects and apply a shader to them in the normal way, using the hypershade's interface. Delete the shader, leaving at least one object without any shader of any kind.
Create a new script and add the following code:
import maya.cmds as cmds def shadersFromObject(obj): cmds.select(obj, replace=True) cmds.hyperShade(obj, shaderNetworksSelectMaterialNodes=True) shaders = cmds.ls(selection=True) return shaders def isGeometry(obj): shapes = cmds.listRelatives(obj, shapes=True) shapeType = cmds.nodeType(shapes[0]) geometryTypes = ['mesh', 'nurbsSurface', 'subdiv...
One of the really great things about the various nodes that Maya provides is that there are very few limits on how you use them. To Maya, all nodes are just collections of functionality with certain inputs and outputs, and as long as the type of data lines up, it doesn't really care how you connect them.
This means that it's completely possible (and often very useful) to use hypershade nodes for tasks that aren't related to creating shading networks. In this example, we'll be doing just that using a plus/minus/average utility node to set the position of a given object to the average position of a number of others. This could be used, for example, to ensure that the pelvis of a character always stays centered in between the IK handles controlling its feet.
Using utility nodes can be used for tasks where you might otherwise write an expression, but with the added benefit that they update constantly, not just while the playback head is moving.