I would like one of my Maya MEL procedures to be executed every x seconds. Is there any way to do that ?
2 Answers
The mel setup would be
scriptJob -e "idle" "yourScriptHere()";
However it's hard to get the time in seconds from Mel - system("time /t") will get you time to the minute but not to the second on windows. In Unix system("date +\"%H:%M:%S\"") would get you hours, minutes and seconds.
The main drawback to scriptJob here is that idle events won't be processed when the user or a script is operating - if either the GUI or a script does something long you won't get any events fired during that period.
You can do this in Python with threads as well:
import threading
import time
import maya.utils as utils
def example(interval, ):
global run_timer = True
def your_function_goes_here():
print "hello"
while run_timer:
time.sleep(interval)
utils.executeDeferred(your_function_goes_here)
# always use executeDeferred or evalDeferredInMainThreadWithResult if you're running a thread in Maya!
t = threading.Thread(None, target = example, args = (1,) )
t.start()
Threads are much more powerful and flexible - and a big pain the the butt. They also suffer from the same limitation of as the scriptJob idle event; if Maya's busy they won't fire.

- 12,028
- 3
- 23
- 36
-
You sure that Python function won't hang-up Maya until it returns completely? Plus, I wouldn't recommend `idleEvent` *at all*. The [doc](http://download.autodesk.com/global/docs/maya2013/en_us/Commands/scriptJob.html) rightly says *Use idleEvents with caution.* It has bad side effects one of them being them being a blank attribute editor, clean slate! You end-up shotting yourself in the foot by using it. Although you're suggesting `idle` I am not sure if it's any different. – Bleeding Fingers Jan 16 '14 at 19:15
-
The Maya UI lives on one thread, so its always going to be blocked by code that runs in the UI thread (mel or Python). However with python threads you can run long background processes _without_ blocking except when delivering result (the executeDeferred and evalDeferredInMainThreadWithResult calls pop that bit of execution into the main thread). Unfortunately most scene manipulations are also in the UI thread. Idle is 'safe' in the sense that it works - but you only want to run very lightweight code in idle or you'll make the program feel very slow. – theodox Jan 17 '14 at 18:03
In general, no. However in Python I was able to create something that works pretty well:
import time
def createTimer(seconds, function, *args, **kwargs):
def isItTime():
now = time.time()
if now - isItTime.then > seconds:
isItTime.then = now # swap the order of these two lines ...
function(*args, **kwargs) # ... to wait before restarting timer
isItTime.then = time.time() # set this to zero if you want it to fire once immediately
cmds.scriptJob(event=("idle", isItTime))
def timed_function():
print "Hello Laurent Crivello"
createTimer(3, timed_function) # any additional arguments are passed to the function every x seconds
I don't know what the overhead is, but it only runs on idle anyway, so it's probably not a big deal.
Most of this can be done in Mel (but as usual not as elegantly...). The biggest roadblock is getting the time. In Mel you'd have to parse a system time
call.
Edit: Keeping this Python, you can then call your Mel code from within the python timed_function()

- 22,781
- 10
- 52
- 75