01 - list comprehensions
When people want to use python in maya, most of the time they want to modify lots of things at once. Lots of lights, lots of objects, or both.
In python, you generally treat lots of objects as a list, so its good to have a basic understanding of how lists work.
Lists and list comprehensions
python makes working with lists easy. eg, you have a list:
mylist = [1,2,3,4,5,6]
mylist = [1,2,3,4,5,6]
say you want to multiply every number by two. You could do that with a loop:
for x in mylist:
print x * 2
for x in mylist:
print x * 2
but there's a neater way, a list comprehension. It's a list (hence the square brackets around it), but lets you modify the list elements easily.
In english:
[ do_stuff on each_element in my_list ]
In a list comprehension, multiplying each element by 2 reads like this:
[ x*2 for x in mylist ]
[ x*2 for x in mylist ]
what if you only want to modify certain elements, eg, only multiply numbers by two if the list element is bigger than 4?
Using a for loop it looks like this:
for x in mylist:
if x > 4:
print x * 2
for x in mylist:
if x > 4:
print x * 2
With a list comprehension, put the 'if' at the end:
[ x * 2 for x in mylist if x > 4 ]
[ x * 2 for x in mylist if x > 4 ]
Pymel overview
Before doing anything, import pymel (at some point I'm sure we'll import it by default, but until then: )
from pymel.core import *
from pymel.core import *
First you want to assign a maya node as a python variable. There's several ways to do this, the laziest way for a single thing is to put 'SCENE.' in front of the node name:
foo = SCENE.polySphere1
foo = SCENE.polySphere1
I know that a polysphere has a radius attribute. To get it, call .get():
foo.radius.get()
# Result: 1.0 #
foo.radius.get()
# Result: 1.0 #
To set the radius, use .set( yourvalue ) :
foo.radius.set(3)
foo.radius.set(3)
FInally to get a list of objects use ls. Eg, to get the current selection:
ls(selection=True)
ls(selection=True)
or to get anything with 'lego' in its name:
ls('*lego*')
ls('*lego*')
or to get all phxAreaLights in a scene:
ls(type='phxAreaLight')
ls(type='phxAreaLight')
Pymel and list comprehensions
Armed with these few simple things, you can do a lot.
Eg, get all the area lights:
ls(type='phxAreaLight')
ls(type='phxAreaLight')
That returns a list, which we can use directly in a list comprehension. Eg, not that it makes any sense, we could multiply each light by 2:
[ x * 2 for x in ls(type='phxAreaLight') ]
[ x * 2 for x in ls(type='phxAreaLight') ]
ok, thats dumb and will error out. Instead, we could just print the name of every phxAreaLight:
[ x for x in ls(type='phxAreaLight') ]
[ x for x in ls(type='phxAreaLight') ]
still dumb. Ok, how about we print the exposure attribute for every light?
[ x.exposure.get() for x in ls(type='phxAreaLight') ]
[ x.exposure.get() for x in ls(type='phxAreaLight') ]
ok, how about we set the exposure for each light to 5?
[ x.exposure.set(5) for x in ls(type='phxAreaLight') ]
[ x.exposure.set(5) for x in ls(type='phxAreaLight') ]
ok, how about we do this only if the light contains 'exterior' in its name?
[ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
[ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
as above, but in a rss friendly way next. i'm never sure if we import pymel by default, so i import it:
from pymel.core import *
[ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
from pymel.core import *
[ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
to run 2 python lines in 1, just use a semicolon:
from pymel.core import * ; [ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
from pymel.core import * ; [ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]
and finally wrap that in the rss call you need (watch the double/single quotes... we have single quotes inside the python line, so we have to wrap the outside of if with double quotes:
python = "from pymel.core import * ; [ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]"
python = "from pymel.core import * ; [ x.exposure.set(5) for x in ls(type='phxAreaLight') if 'exterior' in x.name()]"