Maya Python Event Playback get currentTime

1,489 views
Skip to first unread message

raph_

unread,
Apr 6, 2015, 9:39:54 AM4/6/15
to python_in...@googlegroups.com

Hi,
I have a UI with 2 buttons that controls playback, "play" and "stop". It works good.
When the playback is running I would like to get and print the currentTime. But I dont't know how to call the print function at each frame. I guess it's related with event handler, but I am absolutely not familiar with it in python.
Can someone help or give direction to solve this ? thx

import pymel.core as pm



class PlayBackPrinter():
   
def __init__(self):
       
self.drawUI()
       
self.state = False
       
   
   
def drawUI(self):
       
if pm.window("UI_MainWindow", exists = True):
            pm
.deleteUI("UI_MainWindow")
         
        pm
.window("UI_MainWindow", title = "test playback...", w = 150, h = 150, mnb = False, mxb = False, sizeable = True)
        pm
.columnLayout("UI_MainLayout", w = 150, h =300)
        pm
.button("UI_pbStartButton", label = "Start", w = 150, command=self.pbStart)
        pm
.button("UI_pbStopButton", label = "Stop", w = 150, command=self.pbStop)  
        pm
.showWindow("UI_MainWindow")

   
def pbStart(self,*args):
        pm
.play(state=True)
       
self.state = True
#         print str("state : " +str(self.state))
                   
   
def pbStop(self,*args):
        pm
.play(state=False)
       
self.state = False
#         print str("state : " +str(self.state))

   
def pbPrintCurrentTime(self):
       
print pm.currentTime()
           
   
def pbListener(self):
        t
= pm.currentTime()


def main():
    pbPrinter
= PlayBackPrinter()
   
while pbPrinter.state==True:
        pbPrinter
.pbPrintCurrentTime()



main
()


AK Eric

unread,
Apr 6, 2015, 12:22:30 PM4/6/15
to python_in...@googlegroups.com
Off the cuff:  Make a method that prints the current frame (like you've done).  The "on" button of your ui calls to a new method that creates a scriptJob and passes the printer method to the timeChange arg.   The "off" button deletes the scriptJob.  You'd want to put checks in so no more than one scriptJob gets made if the user keeps bonking 'on'.   Should be about that simple. 

raph_

unread,
Apr 6, 2015, 10:40:51 PM4/6/15
to python_in...@googlegroups.com
hi Eric and thx for your help.
I tried but really, I don' get it "passes the printer method to the timeChange arg." as my skills in maya programming are very limited. I checked the
pymel.core.animation.keyframe class, found timeChange attribute....but then.. I tried to query it expecting I could detect when currentTime changes, but got no return value..
a = pm.keyframe(query = True, timeChange = True) 
        print a

In my case I am not sure that scriptJob is appropriate as it's mel and I want to use python class object and  avoid any kind of call like "python(blabla...)"

My previous print time sample code is maybe confusing so I updated my code trying to make it clearer. Basically I defined a CustomLocator object. Each time a frame is played after pressing Start button a custom locator is drawn. Right now the locator is drawn when pressing the start button. But it's not drawn each time a frame is played or updated and I still can' t figure how to do it...

class PlayBackDoSomething():
    def __init__(self):
        self.drawUI()
        self.state = False
        
    
    def drawUI(self):
        if pm.window("UI_MainWindow", exists = True):
            pm.deleteUI("UI_MainWindow")
         
        pm.window("UI_MainWindow", title = "test playback...", w = 150, h = 150, mnb = False, mxb = False, sizeable = True)
        pm.columnLayout("UI_MainLayout", w = 150, h =300)
        pm.button("UI_pbStartButton", label = "Start", w = 150, command=self.pbStart)
        pm.button("UI_pbStopButton", label = "Stop", w = 150, command=self.pbStop)  
        pm.showWindow("UI_MainWindow") 

    def pbStart(self,*args):
        pm.play(state=True)
        self.state = True
        self.doTheJob()        
                            
    def pbStop(self,*args):
        pm.play(state=False)
        self.state = False
        self.stopTheJob()
         
    def doTheJob(self):
        #this is basically part of code that i want to execute each time a frame is updated after pressing Play button
        print ("start of job")
        a = pm.keyframe(query = True, timeChange = True) 
        print a
        
        t =  pm.currentTime()
        cl = CustomLocator(t, 0,0)
        cl.draw()
        
               
    def stopTheJob(self):
        print ("end of job")

    
            

class CustomLocator():
    def __init__(self, x, y, z):
        self.x = x   
        self.y = y 
        self.z = z 
        
    def draw(self):
        pm.spaceLocator( p=(self.x, self.y, self.z) )
        pm.spaceLocator( p=(self.x, self.y, self.z-5) )
        pm.spaceLocator( p=(self.x, self.y, self.z+5) )
        
            
      
def main():
    pb = PlayBackDoSomething()


main()



Pseudo Code:
Press Start Button
>>Start Playback
>>>>While(currentTime changes):
              DoTheJob()

Press Stop Button
>>Stop Playback

AK Eric

unread,
Apr 6, 2015, 11:14:57 PM4/6/15
to python_in...@googlegroups.com
So I gave it a shot myself, and I realized the scriptJob only fires when the playback is over, not during playback.  That being said, scriptJobs have both a python cmd and pymel implementation, so there'd be no reason you'd need to call to the mel version.

It's possible you could get away with something similar using an API MDGMessage callback:
I have notes on how to use these here:
But they may have the same failures as the scriptJob : only executing when the playback is over.

Even easier than all this though : Just make an expression:

print ("The Frame!" + frame + " \n");


Totally works, and prints every frame during playback.  I create and manage expressions from Python all the time:  One button makes the expression node if it doesn't exist.  The other button deletes it if it does.  I'm still fuzzy on the how\why of all this, but I hope this helps ;)

Raphael Crespin

unread,
Apr 7, 2015, 12:27:32 AM4/7/15
to python_in...@googlegroups.com
how\why :)
you right I should explain  a bit more..
First I wrote a python script that allows to export piece of geometry and related data into a text file.
But how to use my script on animated geometry? execute my script during playback?

- First shot was to just execute my script by defining  a start and end frame and iterate using currentTime+=1. Not bad but you in case of large animation you have to wait the end of the loop. I can't find a way to break the loop until it's over
- Then I tried to use animation/ expression editor...as it "doesn't work" with python I had to call my python script using "python()" .mel expression which is crazy slow

So the purpose of this is to be able to run python script using play and stop according to time frame. Kind of mimic the animation expression editor with the possibility to use python object
Here I am today..
I am going to look at what you just sent me..
Appreciate you help :)
cheers



--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/kfpi8VrLpLw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/f816eba4-7f6c-487b-ae20-2bc863453341%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

AK Eric

unread,
Apr 7, 2015, 12:03:24 PM4/7/15
to python_in...@googlegroups.com
If you're trying to export stuff per frame over a long sequence, then you want the calling code to control the frame step, not Maya's playback mechanism.  I've authored tools that export a .obj per frame over a framerange for the selected mesh.  In that case, you pass your min\max frame-range to pythons range function, and loop over those:  Each loop you set Maya's frame to the given iteration, then do the export work you're after.  If you're concerned about canceling the job in the middle of some super-long sequence, wrapper the whole thing in a progressWindow.  I have an example of how to author a progressWindow context manager here:
I use this all the time, and sounds like even the example code could get you what you're after, since it iterates over a frame range.

Raphael Crespin

unread,
Apr 7, 2015, 8:50:35 PM4/7/15
to python_in...@googlegroups.com
great! really closed to what I am looking for. I am going to combine it with a play stop buttons, although I am not sure to be able to override esc key, but I get the wrapper logic now ... thx !

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/kfpi8VrLpLw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_m...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages