Discover an objects parents in Maya using Python

Let’s say we have 2 shapes (a cube and a circle), and we want to parent one shape under the other.

Lets start with some code:

// import the maya commands
from maya import cmds

// Place a cube list in a variable
cube = cmds.polyCube()

// Get the cube object from the 'cube' list
cubeShape = cube[0]

// Place a circle list in a variable
circle = cmds.circle()

// Get the circle object from the 'circle' list
circleShape = circle[0]

If we run this code, we should see a cube and a circle in the perspective viewport and the 2 objects in the outliner:

To parent one object under the other we’ll use the parent command:

cmds.parent()

If you run this alone you’ll get a ‘not enough object or values’ error, which makes sense as we need to define which objects we want to parent (this command expects2 values).

So lets give this command something to chew on:

cmds.parent(cubeShape, circleShape)

Thefirstvalue is the child, and the secondis the parent (Give this child ‘cubeShape’ to its parent ‘circleShape’).

Now run this command and we can see that the hierarchy has been updated in the outliner and the cube is now a child of the circle:

This is great because if you move the nurbsCircle, the cube will move with it.  However you can still grab the pCube in the perspective view and move it independently from the nurbsCircle, lets see how we can fix this:

Now we are going to ‘lock’ the pCube’s attributes:

Click on the pCube in the perspective panel (or top, side whatever)

Open the channel box

Alt click on ‘Translate X’ and select ‘Lock Selected’:

You’ll see that the command output has been updated with a command

While this command is accurate, its output in the MEL language, lets convert it to Python:

cmds.setAttr("pCube2.tx", lock=True)

Lets break down this command:

Cmds      = Use a maya command (imported in line 1)

setAttr() = Set attribute method (expects values)

pCube2  = The object to set the attribute of (We discovered this from the MEL output)

.tx            = The attribute we are changing (in this case translate x)

lock=True = Set the lock attribute to true

We can change the attribute to translate y by updating the code to the following:

cmds.setAttr("pCube2.ty", lock=True)

But hang on a second! If we are applying attributes using code, and we are already putting objects into variables, why don’t we apply the new attributes using the variable names rather than the objects directly:

Lets go back to our original code:

from maya import cmds

cube = cmds.polyCube()
cubeShape = cube[0]

circle = cmds.circle()
circleShape = circle[0]

cmds.parent(cubeShape, circleShape)

We have already declared the variables cubeShape and circleShape which hold the objects, lets update the setAttr command to use the cubeShape variable:

cmds.setAttr(cubeShape+".ty", lock=True)

If we select and run the part we updated, you’ll see in the output that the string has been constructed using our variable name plus the translate y extension (.ty):

Now let’s say we want to lock ALL of the translates, and not just the x or y value:

cmds.setAttr(cubeShape+".translate", lock=True)

Lets go 1 step further and lock all of the basic position attributes (translate, rotate and scale)

cmds.setAttr(cubeShape+".translate", lock=True)
cmds.setAttr(cubeShape+".rotate", lock=True)
cmds.setAttr(cubeShape+".scale", lock=True)

Now if we try to manipulate the cube in the viewport, we will not be able to.  However we can still move and manipulate the circle which will effect the cube as it is a child of the circle object.

The add a little bonus in, when we run our code from the start we want to end up with the circle selected, so that we can immediately start to manipulate our object.

cmds.select(circleShape)

Now lets take a look at our code in its entirety:

from maya import cmds

cube = cmds.polyCube()
cubeShape = cube[0]

circle = cmds.circle()
circleShape = circle[0]

cmds.parent(cubeShape, circleShape)

cmds.setAttr(cubeShape+".translate", lock=True)
cmds.setAttr(cubeShape+".rotate", lock=True)
cmds.setAttr(cubeShape+".scale", lock=True)

cmds.select(circleShape)