Python For Maya P.3

Big Picture

In this article, I am going to demonstrate the following key aspects:

1. Writing python to create a new maya interface

2. How to design your own tools

3. How to share your scripts with other people

4. More about Python function

I will discuss these features by giving simple two cases, basically, I hope you can get an overall idea that how python script works in maya and how to create your own tools by utilizing the techniques I showed you in previous articles.



Case 1: Create an alignment tool using Python script

Maya alignment command may not be widely used compared to 3DSMAX, for you can easily snap your objects to vertexes, grids or lines. However, sometimes, I do need to utilize the alignment command to align the objects.

So the general idea is to use the maya ‘Parent Constrain’ command. First, we need to uncheck the “maintain offset” option, if we do so and execute the “parent constrain” command, the command will create space relationship between two selected objects. More precisely, the target object (last selected object ) will move to the source object, and at the same time, the target object coordinate should be set the same as parent object coordinate. Basically, we can conclude that after parent constrain, the target object has already aligned with the source object. The last thing we need to do is to delete the constrain node, and separate the two objects apart.

0030QiC3ty6LUCZ8Gx6fc

In order to write our python code, we first need to know what’s the parent constrain representation in code. In order to get this command line, we can simply click the parent constrain command in maya GUI and get the command syntax in console window:

0030QiC3ty6LWb35rSV610030QiC3ty6LWb37sL872

You can see, in this case, the mel command is “parentConstraint -weight 1”, and this command only have only one attribute ‘weight’. (You can instead search the official manual to get the explanation for this command)

As long as we know the command, we can convert the code in python:

0030QiC3ty6LWbf3Vh680

First thing first, we still need to import maya command into python code, I have discussed this in the previous article, and we give an alias to maya.cmds module, so in the following code, we can use mc instead of maya.cmds.

The second line of code will perform Parent Constrain command on selected objects. Here we have to select at least two objects first. Or the code will throw an error. We set mo(maintain offset attribute) to false, which execute exactly as we uncheck the maintain offset checkbox. Here an interesting thing is I assign the final result to a new variable named ‘Temp_PCons’. The reason that I did this is because if I can save the result to a variable, I can assess the result later and do some modifications to the result. (In this case , we will finally delete the parent constrain node, so I can simply call mc.delete command)

The last thing is that we delete the parent constrain node and just keep our transformed target objects.

Tips: In python language, you do not need to specify variable type when declare a variable. The python interpreter will try to interpret a variable type based on its value.

 

Now, we can perform some simple test, hope you still know how to do it. (Select all the code, and press the Ctrl + Enter key or Enter key on Num Pad, the code will execute)

Be sure to select some geometry objects first.

0030QiC3ty6LWc1URs672

0030QiC3ty6LWc1XEYpf9

Now, we can see the results: if we only select two objects, the target object (child object) will attach to source object and orient to the same direction as target object.  If we selected multiple objects, the child object will be the last selected object and it will move to the center of all former objects.

OK, the next thing is that we can add some comments in our script so it will be convenient when we share our script with others. In python language, we use ‘#’ sign to add comments in the code instead of ‘//’.

0030QiC3ty6LWcdgrmCb6

After we have added some comments, we can extend our alignment tool by creating a window and a button when we run the script, so we can make the window stay open and easily execute the parent constrain command multiple times.

The general idea to implement these features is that we first group our parent constrain related code in a function, then each time when we click the button, we call this function and execute the command one time. Let’s do it right now:

0030QiC3ty6LWcGHzeTef

In python, the function are defined by def key word (As shown above). Be sure to add colon at the end of function name. Any codes which are meant to be inside a function should have a tab space before, and if you have for loops or if statement in your code, any code in these blocks should have two tab white before. Now, we create a function named ObjAligner(), and we put our parent constrain code in this function.

The next thing is to create a window to hold our button. Creating a new window is simple in Python, basically, you just need to call the window function from maya command module. The parameters are pretty straightforward, title means window name, s determines window scale (if false, the window can not be resized), wh means window width and height.

0030QiC3ty6LWdwnpGm4e

After we have a window, now we can create the real content. First, we call the columnLayout function. This function will create a canvas in window area, all the other created contents will be displayed in this area. We set the adj to true so that the canvas will resize based on contents (e.g. button size), but it is also limited to window size. After that, we add a text which demonstrate the usage of this script. Then we call separator function to add a line between instruction and real button.

The last thing is button, basically, it is straightforward as well, l means button label name, in this case, the name is ‘Go’. w and h means width and height. c means the function to call when we hit the button. The final line is to draw the window.

0030QiC3ty6LWdK6uHS28

Before we do a real test, we can add some checks in the ObjALiner() function to handle the situation if we do not select at least two objects.  The code is simple, we first save all the selected objects in a list, then we check whether the length of the list is greater or equal than 2. If it is not, we print an error message to remind user to at least two objects.

Then we are done!

0030QiC3ty6LWebOFn399

Let’s test it!

0030QiC3ty6LXMGfx6f6f

When we run the code, you can see we have a window popup with the Go button. If we select two objects in the scene, and press the button, the child object is aligned to the parent object.

0030QiC3ty6LXMGiY30fa

If we only select one object and hit the button,  an error will pop up in the console window.

OK! The next thing is to add these code to our shelf and create a new tool icon, so we do not need to keep our code in editor area. How can we do that? Select all the code,  press down mouse middle button and drag all the code to the shelf area, then release the middle button, you can see a new icon is created. Now, if you want to execute the code, you can just click the icon.

0030QiC3ty6LXN3MSBkb2

We can right click the new added icon, and choose edit to add more information to these icon.

0030QiC3ty6LXN7LIMH93

Here, we basically modified three area, first we rename the command to make it more meaningful. Then I modified the tooltip, tool tip is a message which will show up when your mouse hover over the icon. The last thing I modified  is Icon Label, this is a short name for this icon, typically, never make this exceed 4 characters.

0030QiC3ty6LXOsDa3R9f

Another useful features is that these command can be executed by single click or double click the icon, which is useful for turn on and off different state such as turn on/off bone display.

0030QiC3ty6LXNO4YDXbd

The last improvement of our code is that at now, when we click our icon, we will get a new window open, which is not good. Let’s get rid of the previous existed window first before creating a new window. The code is simple:

0030QiC3ty6LXNZDmjTe1

OK, that’s all for the first example, all the code is here:



#The code is designed to Align  Object(s)
#First select the Source obj, then select the target obj
#Redefined the prefix of the Maya Command
import maya.cmds as mc
#Define the variable of window
string = WindowObjAliner
#Check if the window exists , if true, then delete it
if mc.window(WindowObjAliner, ex=True):
    mc.deleteUI(WindowObjAliner , window = True)
#Define the window
WindowObjAliner = mc.window(title = “Align Object(s)” , s = False , wh = (300,100))
mc.columnLayout(adj = True)
mc.text(l = “Instructions:First select the Source obj(s), Then select the target obj”)
mc.separator()
mc.button(l = “Go!” , w = 300, h = 40, c = “ObjAliner()”)
mc.showWindow(WindowObjAliner)
#Define the function to control the code
def ObjAliner():
    ListObj = mc.ls(sl = True)
    ListSize = len(ListObj)
    if ListSize>=2:
        #Create the Parent Constrain between object(s), align obj together
        Temp_PCons = mc.parentConstraint(mo = False)
        #Delete the Parent Constraint
        mc.delete(Temp_PCons)
    else:
        print “Error: At least two Objects selected”


 



Case 2: Create new objects based on the points of spline curve

If you have fully understand what we have written just now, this case should be easy.

The general idea for case 2 is that first we first create an arbitrary spline curve, after that, we iterate all its points, and get the coordinate of each point, then we create new object based on the coordinate values. In this case, I created joints in the point position. You can create arbitrary objects.

First, let’s create a CV curve. The setting does not matter (default is OK), just create a curve! Here is mine:

0030QiC3ty6LXOvy4oWfa

0030QiC3ty6LXOyfaVXd9

The next thing, we select the curve and iterate all the point in the curve, and save the iteration results in a list, then we calculate the length size (number of points), then start our for loop (Here the fl = True means when we using ls command, we save the individual element of our selected object, ):

0030QiC3ty6LXODvDcy1e

The next thing we need to know what is the exact command in maya related to control point. So we first select the curve and go to point component, then we click the CVs from the attribute editor, and then we modify the value a little bit… Then we get the command name from the console!

0030QiC3ty6LXOSuXse32

0030QiC3ty6LXOSxJOY64

0030QiC3ty6LXOSAuT10b

We can see here the attribute name is “xValue”, so we can write the code like this:

0030QiC3ty6LXPcIyX315

We first call the mc. getAttri function to get a specific attribute from objects. Here we loop all the object attribute values (corresponding control point coordinates) and save it to an attribute list. We do this for all three components. (Recall that in Python, we can do string concatenation by using ‘+’ operator)

0030QiC3ty6LXPwScs931

After that we call the command select to clear current active list (set cl(clear) = True to clear current selection. Here it maybe like burning a daylight, just in case). Then, we began creating joints by using mc.joint( ) command, and we set the new joint position based on the values of getVertX(Y/Z) variables. Then we are done with code!

Let’s test it…

0030QiC3ty6LXPGt1Hz29

First select the curve and then execute the code. It looks pretty good. Then we can add some comments and put it in our shelf like the last script.

0030QiC3ty6LXPKeEDh73

All the code is here:



#This code is for creating obj along the curve point…
#First select the curve point, then go!
#Redefined the prefix of the Maya Command
import maya.cmds as mc
#Put the Vertexes of the curve into the list
#@sl – List objects that are currently selected.
#@fl – Flattens the returned list of objects so that each component is identified individually.
selCVs = mc.ls(sl = True, fl = True)
#Get the length of the list
selCVs_Size = len(selCVs)
#Re-evaluate each point and get the position of them , then create the object for each point using their position…
for i in range(0,selCVs_Size,1):
getVertX = mc.getAttr(selCVs[i] + “.xValue”)
getVertY = mc.getAttr(selCVs[i] + “.yValue”)
getVertZ = mc.getAttr(selCVs[i] + “.zValue”)
#remove the vertex from the list
mc.select(cl = True)
mkJnt = mc.joint()
mc.setAttr(mkJnt + “.tx” , getVertX)
mc.setAttr(mkJnt + “.ty” , getVertY)
mc.setAttr(mkJnt + “.tz” , getVertZ)


 



As a reminder, when your code is in Script Editor, you can save it as a file and send to other people if you wish. Just normal “Ctrl + S” will do the work for you.

0030QiC3ty6LXQ0mZUOc6

That’s all for this article. Hope this will be helpful.

By Jun

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s