;

Pymel Blog Rss Feed

Wednesday, May 23, 2012


Prior to starting any of these lessons be sure to import the PyMEL library. See here for why and how.



In a previous tutorial, we talked about built in Maya commands. Here we'll talk about user created Maya commands.

 

Often times in programming, we need to break large problems down into smaller ones. We also like to encapsulate behavior. Functions give us this ability. Let's write a few small examples.

 

def Hello():
	print "Hello world!"
Hello()

This basic function prints out the infamous "Hello World" line. I know, it’s not very flashy. But there are some things to note here. First, the code is indented. If you need a refresher on the perils of indentation in Python, check this out. Also note on line 3, how we execute the function. Lines 1 and 2 define the behavior. And line 3 actually tells Maya to run our code. Now let's add a parameter:

def Hello(name):
	print "Hello " + name
Hello("Chuks")

Here we add a parameter, also known as an argument. We can no longer simply call Hello() Maya will complain that it expected 1 argument and it got none. But with this new definition, we can do:

 

Hello("John")  #prints Hello John
Hello("Sally")  #prints Hello Sally
Hello("Bob")  #prints Hello Bob
Hello("Newman")  #prints Hello Newman (like Seinfeld would say it)

We can have more than one parameter:

def Hello(firstName, lastName):
	print "Hello " + firstName + " " + lastName
Hello("Babe", "Ruth")  #prints Hello Babe Ruth
Hello("Abe", "Lincoln")  #prints Hello Abe Lincoln
Hello("Bugs", "Bunny")  #prints Hello Bugs Bunny
Hello("Yogi", "Bear")  #prints Hello Yogi Bear (like Seinfeld would say it)

Additional parameters can be added as needed. And you can add as many as you want. Just make sure that they're separated by commas. Oh and if you don't get string concatenation, check out the variables tutorial.

 

So if parameters are inputs, what about outputs?  Surely we're not only limited to only inputs?! The answer, as you may have guess is no, we're not just limited to inputs.  Not only can we have inputs by way of parameters, we can create and send return values:

def Square(num):
	numSquared = num * num
	return numSquared
myResult = Square(5) #result is 25
print myResult #prints myResult

This way, you can store the results of functions into variables. And from there, you can use these variables to do whatever it is you need to do.

 

I like to think of functions as factories that work best when they perform a singular task. You pass information through the front door as arguments and then the factory does its work. When it's done, the function passes the result out the back door as a return value.

 

So let's put everything together and write a script that creates a random combination of poly spheres, tori, and cylinders. And then the script will move each object's vertices to random locations.

def MoveObjVertices(curObj):
	numVertex = len(curObj.vtx)
	for i in range(0, numVertex):
		xVal = random.uniform(-0.03, 0.03)
		yVal = random.uniform(-0.03, 0.03)
		zVal = random.uniform(-0.03, 0.03)
		randVector = dt.Vector(xVal, yVal, zVal)
		polyMoveVtxObj = polyMoveVertex(curObj.vtx[i])[0]
		polyMoveVtxObj.setTranslate(randVector)

def MakeObj(objType):
	if(objType == 1):
		curObj = polySphere()[0]
	elif(objType == 2):
		curObj = polyTorus()[0]
	else:
		curObj = polyCylinder()[0]
	MoveObjVertices(curObj)	
	return curObj

def PolyRandomization(numObj):
	for i in range(0, numObj):
		objType = random.randint(0,2) #make sure you imported random
		xVal = random.uniform(-30, 30)
		yVal = random.uniform(-30, 30)
		zVal = random.uniform(-30, 30)
		curObj = MakeObj(objType)
		curObj.translate.set(xVal, yVal, zVal)
		delete(curObj, ch=True)

See the tutorial on random numbers if you need to. Also see the tutorial for PyMEL objects to understand how polyMoveVtxObj works on line 8. So let's step through this. The entry point to this script is on line 21. We need to supply the number of object we wish to create. So we would write something like this:

PolyRandomization(5)

Lines 23-26 create random numbers we need to choose which object to create as well as where to move the object. Line 27 we call MakeObj(). Control jumps to line 11. This is where we choose which object to create based on the random integer generated on line 23. On line 18, we call MoveObjVertices(). Control jumps to line 1. And this is where we actually move the object's vertices. We loop through each vertex, making use of the PolyMoveVertex object, and we move them to a random location. Finally control returns back to line 28 and 29 where we move the newly created object and delete its construction history.

 

Without separating the functionality into separate functions, the code would look like this:

def PolyRandomization(numObj):
	for i in range(0, numObj):
		objType = random.randint(0,2) #make sure you imported random
		xValObj = random.uniform(-30, 30)
		yValObj = random.uniform(-30, 30)
		zValObj = random.uniform(-30, 30)
		if(objType == 1):
			curObj = polySphere()[0]
		elif(objType == 2):
			curObj = polyTorus()[0]
		else:
			curObj = polyCylinder()[0]
		numVertex = len(curObj.vtx)
		for i in range(0, numVertex):
			xValVtx = random.uniform(-0.03, 0.03)
			yValVtx = random.uniform(-0.03, 0.03)
			zValVtx = random.uniform(-0.03, 0.03)
			randVector = dt.Vector(xValVtx, yValVtx, zValVtx)
			polyMoveVtxObj = polyMoveVertex(curObj.vtx[i])[0]
			polyMoveVtxObj.setTranslate(randVector)	
		curObj.translate.set(xValObj, yValObj, zValObj)
		delete(curObj, ch=True)

Indentation nightmare! Very hard to read. It's not very clear what's doing what. I'll leave it to you if you want to follow the flow. It hurts my eyes just looking at it.

 

So in conclusion, use functions whenever you have functionality that can be grouped. As an added benefit, you may be able to reuse code; you won't have to write the same lines over and over. Plus it will make your code more readable. Any questions? Let me know!

My comment system is powered by Disqus. And they require you to put in a name and an email. But I'd love to hear what you think. So if you want to comment anonymously, just put any name and test@test.com for your email.

blog comments powered by Disqus