another newbie question

120 views
Skip to first unread message

Serena Xu

unread,
May 23, 2012, 10:33:57 AM5/23/12
to python_inside_maya
i'm trying to make a bunch of cubes move and rotate everytime I update
the current time by using the setTranslation and setRotation. It's not
doing that when I call moveCubes(). Please let me know what's wrong
with my script. Thanks!

#move objects with respect to time
import maya.OpenMaya as om
import maya.cmds as cmds
import sys

def setVector(x, y, z):
time = cmds.currentTime(q=True)
vector = om.MVector(0.0, 0.0, 0.0)
vector.x = x * time
vector.y = y * time
vector.z = z * time
return vector

def moveCubes():
sList = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sList)
iter1 = om.MItSelectionList( sList, om.MFn.kGeometric )

while not iter1.isDone():
dagPath = om.MDagPath()
cube = om.MObject()
sList.getDagPath(0, dagPath, cube)
ord = om.MEulerRotation.kXYZ
rot = om.MEulerRotation(3.4, 5.4, 22.3, ord)

vector = setVector(0.5, 0.2, 0.8)
#print vector.x
spc = om.MSpace.kWorld

try:
transFn = om.MFnTransform(dagPath)
except:
pass
else:
try:
transFn.setTranslation(vector, spc)
print vector.y
transFn.setRotation(rot, spc)
except:
sys.stderr.write("Error doing translate on transform
\n")
iter1.next()
continue

iter1.next()

Justin Israel

unread,
May 23, 2012, 11:38:07 AM5/23/12
to python_in...@googlegroups.com
Hi Serena,

The first and most important reason that its not working as expected is that while you are looping over the iterator, you aren't using it to get the current object. Instead, you are accessing the original selection list each time with the same 0 index. You should change that line to:
    iter1.getDagPath(dagPath)  

Note that I removed the cube object because you never use it. There were some other things I saw too but I might just be using it differently than you intended...

It was crashing for me while trying to rotate and transform on shape nodes as opposed to transform notes, because your selection filter "geometric" was causing it to return shapes. I removed the filter for now. Also, it crashed doing the rotate because seRotation() was expecting a Quaternion type instead of a EulerRotation. You can call asQuaternion() for that part.
You have a pretty generic nested try-except block in there which can make debugging very difficult. Its best not to wrap blanket statement exception handling around code because you might miss unexpected errors and completely mask them. 
And the last comment I have is more of a performance thing. There are a few lines you can move outside the while loop and only create them once. This could help if you had a very large selection list to loop over and you were concerned with speed.

Here is the modified moveCubes() function. I will include it here and a pastebin in case its not readable:

def moveCubes():
    sList = om.MSelectionList()
    om.MGlobal.getActiveSelectionList(sList)
    # removed the geometric filter for now
    iter1 = om.MItSelectionList( sList )
    
    # creating all of these once to reuse
    dagPath = om.MDagPath()
    transFn = om.MFnTransform()
    spc = om.MSpace.kWorld
    ord = om.MEulerRotation.kXYZ
   
    while not iter1.isDone():
        # 1. removed the cube ref, as its never used
        # 2. use the iter1 to get the dagPath instead of
        # calling it on the sList
        iter1.getDagPath(dagPath)
        
        rot = om.MEulerRotation(3.4, 5.4, 22.3, ord)
        vector = setVector(0.5, 0.2, 0.8)
        # reuse the fn by settings the new dagPath object 
        transFn.setObject(dagPath)
               
        try:
            transFn.setTranslation(vector, spc)
            # convert Euler -> Quaternion as required by API
            transFn.setRotation(rot.asQuaternion(), spc)
        except Exception, e:
            # at least logging the exception as well
            sys.stderr.write("Error doing translate on transform\n%s" % e)
        # always calling next(), and only in one place
        iter1.next()

I didn't move the rotation and vector function calls outside of the for loop because even though you are using the same value each time, I expect that you will be doing something to probably vary that in each loop.

Hope that help!

-- justin



Serena Xu

unread,
May 23, 2012, 12:32:59 PM5/23/12
to python_inside_maya
Thanks so much for your help!! This is starting to get clearer to me.
What's the easiest way for me to run moveCubes() as I scrub the
timeline? Should I just call the function from the expression editor?

Justin Israel

unread,
May 23, 2012, 1:17:46 PM5/23/12
to python_in...@googlegroups.com
Ya that API is more complicated to learn than just the python commands module, for sure.

To attach this to the event of the current time changing, you can either use the maya.cmds.scriptJob() or the equivalent lower level API version.

## maya commands
jobNum = cmds.scriptJob(event=('timeChanged', moveCubes))
cmds.scriptJob(kill=jobNum)

## or,  API
import maya.OpenMaya as om
# start it
jobid = om.MEventMessage.addEventCallback("timeChanged", moveCubes)
# stop it
om.MEventMessage.removeCallback(jobid) 

Serena Xu

unread,
May 23, 2012, 3:32:20 PM5/23/12
to python_inside_maya
...this is a dumb question...

how do i attach it to the event of time changing?

Justin Israel

unread,
May 23, 2012, 3:38:05 PM5/23/12
to python_in...@googlegroups.com
Well, one of those two snippets of code I just posted in the last reply would do it.
Choose one of those. When you run it, you are binding your moveCubes() callable function to the "timeChanged" event.
Every occurrence of the time changing should fire that callback.  

Here is an even simpler and concise example:

def foo():
    print "TIME CHANGED!"

jobNum = cmds.scriptJob(event=('timeChanged', foo))

You bind the foo() function to the event "timeChanged". When you click around the timeline, you should see it print.
Then you can kill that binding with:
cmds.scriptJob(kill=jobNum)

Serena Xu

unread,
May 23, 2012, 3:45:57 PM5/23/12
to python_inside_maya
Oooh I see. It wasnt working for me at first because I was scrubbing
through the timeline and not clicking through it.

Thanks so much! I really appreciate it! :)
Reply all
Reply to author
Forward
0 new messages