Maya Python API: программа не закрывается при запуске скрипта

У меня есть короткий скрипт Maya, который просто непрерывно вращает камеру по кругу. Проблема в том, что когда я пытаюсь запустить скрипт, после его запуска я не могу закрыть приложение, пока не убью скрипт. Я использую cmds.refresh(), но это только обновляет пользовательский интерфейс и по-прежнему задерживает другие операции (например, закрытие программы). Я понимаю, что могу просто убить скрипт вручную, но я хотел бы иметь возможность делать это программно через обратные вызовы или что-то в этом роде.

Вот как выглядит мой код прямо сейчас:

import sys
import time
import maya.cmds as cmds
import maya.api.OpenMayaUI as omui

view = omui.M3dView.active3dView()
currentCamera = view.getCamera()

while(True):
    cmds.orbit(currentCamera, ha = 1)
    view.setCamera(currentCamera)
    cmds.refresh()
    time.sleep(.01)

В принципе, есть ли что-то, что я могу поместить в while () вместо «True», что автоматически убьет скрипт, когда вы закроете программу? Или что-то, что я мог бы сделать по-другому вообще?


person ClydeTheGhost    schedule 03.08.2015    source источник
comment
Где определяется camera? Вы имели в виду currentCamera вместо этого?   -  person matthewatabet    schedule 03.08.2015
comment
Да, спасибо. Отредактировано соответствующим образом.   -  person ClydeTheGhost    schedule 03.08.2015


Ответы (2)


Вы действительно не хотите while True: здесь. Maya довольно старомоден в отношении многопоточности — прикосновение к видимой сцене или пользовательскому интерфейсу из отдельного потока запрещено — поэтому вы не можете легко создать желаемое поведение, не полностью переняв сеанс Maya. К сожалению, это дает вам поведение, которое вы испытываете.

Вы можете попробовать две основные стратегии:

Самое простое — использовать задание сценария Maya, которое срабатывает при событии «idle». Это будет пытаться работать только тогда, когда Maya не делает ничего другого, и — поскольку Maya запускает его для вас в основном потоке — не вызовет никаких проблем. Однако это будет срабатывать только тогда, когда Maya не делает ничего другого, поэтому, если пользователь делает что-то в пользовательском интерфейсе или на сцене, ваш скрипт не сработает. Что-то типа:

def orbit_cam():
   cmds.orbit('persp', ha = .01)

cmds.scriptJob(e=('idle', orbit_cam))

Большим недостатком этого является то, что у вас нет никакого контроля над частотой запуска скрипта: это зависит от Maya.

Второй вариант — создать отдельный поток для запуска скрипта на ваших условиях. Однако здесь вам нужно быть осторожным, потому что функции, запущенные из второго потока, вызовут сбои, если вы не завернете их в вызов maya.util.executeDeferred.

Дополнительная информация: Как использовать многопоточность python (maya) и Как выполнить процедуру Maya MEL в регулярные интервалы

person theodox    schedule 03.08.2015
comment
Спасибо, это сработало отлично! Я знал, что Maya обидчиво относится к многопоточности, но использование его с executeDeferred исправило ситуацию. - person ClydeTheGhost; 04.08.2015

Вы можете сделать это с помощью scriptJob, прикрепленного к событию idle.

import time
import sys
import maya.cmds as cmds
import maya.api.OpenMayaUI as omui

view = omui.M3dView.active3dView()
currentCamera = view.getCamera()

def rotate_camera():
    cmds.orbit(currentCamera, ha = 1)
    view.setCamera(currentCamera)
    cmds.refresh()
    time.sleep(.01)

cmds.scriptJob(event=['idle', rotate_camera], killWithScene=True)

Это будет постоянно вращать камеру, позволяя пользователю в любой момент выйти из приложения или взаимодействовать с пользовательским интерфейсом. Обратите внимание, что вам, вероятно, понадобится обратный вызов, который удаляет задание сценария, когда анимация должна закончиться.

person matthewatabet    schedule 03.08.2015