Как выполнять процедуру Maya MEL через равные промежутки времени

Я хотел бы, чтобы одна из моих процедур Maya MEL выполнялась каждые x секунд. Есть ли способ сделать это?


person Laurent Crivello    schedule 16.01.2014    source источник


Ответы (2)


Настройка mel будет

scriptJob -e "idle" "yourScriptHere()";

Однако трудно получить время в секундах от Мела - система («время / t») даст вам время с точностью до минуты, но не до секунды в окнах. В системе Unix ("date +\"%H:%M:%S\"") вы получите часы, минуты и секунды.

Основным недостатком scriptJob здесь является то, что события простоя не будут обрабатываться, когда пользователь или скрипт работают - если либо графический интерфейс, либо скрипт делают что-то долго, вы не получите никаких событий в течение этого периода.

Вы также можете сделать это в Python с потоками:

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()

Потоки намного мощнее и гибче - и большая проблема. Они также страдают тем же ограничением, что и событие бездействия scriptJob; если Майя занята, они не будут стрелять.

person theodox    schedule 16.01.2014
comment
Вы уверены, что функция Python не зависнет в Maya, пока она не вернется полностью? Кроме того, я бы не рекомендовал idleEvent совсем. В документе правильно сказано: Используйте idleEvents с осторожно. У этого есть плохие побочные эффекты, один из которых - это пустой редактор атрибутов, с чистого листа! Вы в конечном итоге выстрелите себе в ногу, используя его. Хотя вы предлагаете idle, я не уверен, что это что-то другое. - person Bleeding Fingers; 16.01.2014
comment
Пользовательский интерфейс Maya живет в одном потоке, поэтому он всегда будет заблокирован кодом, который выполняется в потоке пользовательского интерфейса (mel или Python). Однако с потоками Python вы можете запускать длительные фоновые процессы без блокировки, за исключением случаев доставки результата (вызовы executeDeferred и evalDeferredInMainThreadWithResult выталкивают этот бит выполнения в основной поток). К сожалению, большинство манипуляций со сценой также находятся в потоке пользовательского интерфейса. Бездействие является «безопасным» в том смысле, что оно работает, но вы хотите запускать только очень легкий код в режиме ожидания, иначе вы заставите программу работать очень медленно. - person theodox; 17.01.2014

В общем, нет. Однако в Python я смог создать что-то, что работает очень хорошо:

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

Я не знаю, каковы накладные расходы, но в любом случае он работает только в режиме ожидания, так что, вероятно, это не имеет большого значения.

Большую часть этого можно сделать в Mel (но, как обычно, не так элегантно...). Самое большое препятствие — найти время. В Mel вам нужно будет разобрать вызов system time.

Редактировать: Сохранив этот Python, вы можете вызывать свой код Mel из Python timed_function()

person mhlester    schedule 16.01.2014