Как прервать загрузку файла в Maya, запущенную через cmds.file в python - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть код, который запускает пакетную операцию над файлами в Maya. Реальная реализация не важна, просто знайте, что она получает список путей к файлам, майя открывает файлы, затем по очереди выполняется операция над каждым файлом.

В тех случаях, когда ссылка по какой-либо причине недопустима (например, неверный путь), я хочу прервать загрузку всей этой сцены и перейти к следующей в списке пакетов.

Глядя на другие вопросы на этом и других сайтах, я только видел пользователей, спрашивающих, как запрашивать ссылки. У меня уже есть разумная функция для этого, это то, что нужно делать после того, как эта функция возвращает неверный ссылочный путь, что ставит меня в тупик.

Устранение недопустимых эталонных путей исторически выполнялось вручную через всплывающее окно, однако в больших партиях постоянно присматривать за экземпляром maya не представляется возможным. Также не подавляет само всплывающее окно, так как я считаю, что он все равно откроет файл и запустит пакетную операцию на сцене, пока она находится в недопустимом состоянии.

Я прошел через модуль майя cmds python , чтобы попытаться не загружать ссылки, однако при использовании флага loadReferenceDepth вместе с cmds.file я все еще получаю всплывающее окно:

cmds.file(r'c:\path\to\file.ma', o=1, f=1, lrd='none')  #invalid ref popup during file cmd

Второй подход состоял в том, чтобы заглянуть в Maya Open API и зарегистрировать обратный вызов на событие до открытия. Приведенный ниже код функционально аналогичен настройке партии:

import maya.OpenMaya as OpenM

batchFileList = [r"c:\path\to\file.ma", r"c:\path\to\file2.ma"]

def _test_raise_exception(arg0, arg1, arg2):
    #pretending that a file ref failed below. Ref path validation code would go here.
    print '\n'*5+'Test Logging'+'\n'*5
    return False

cId = OpenM.MSceneMessage.addCheckFileCallback(OpenM.MSceneMessage.kBeforeOpenCheck, _test_raise_exception)

for file_ in batchFileList:
    try:
        rv = cmds.file(file_, o=1)
        #do stuff to the maya scene here
    except:
        #something didn't validate on load, except and skip, logging the occurrence.
        print 'load cancelled'

OpenM.MSceneMessage.removeCallback(cId)

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

Аналогично, замена return False на raise RuntimeError не позволяет мне поймать исключение. Вместо этого cmds.file завершает работу и печатает только небольшое сообщение в журнале, в котором говорится: «Ошибка обратного вызова python». Документы Python Open API говорят, что привязки предпочитают исключения, а не коды возврата MStatus, поэтому я ожидал, что это сработает.

Мы удалили класс MStatus. Python исключения должны быть использованы вместо MStatus.

Я что-то здесь упускаю? Должен быть способ сделать это. Создание очень грубого парсера .ma - это еще один вариант, но это будет означать прекращение поддержки файлов .mb, чего я не хочу делать.

Спасибо за ваше время!

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Я спрашивал об этом на форумах майя, и получил очень полезную подсказку от плаката с ручкой JoeAlter-Inc :

Документация, на которую вы ссылаетесь, относится к Maya Python API 2, но используемые вами классы взяты из Maya Python API 1.

В API 1 большинство методов принимают те же параметры, что и в C ++. Это означает, что CheckFileCallback будет передан три параметра, первый из которых является ссылкой на переменную bool C ++. Чтобы прервать загрузку файла, вы должны установить для этой переменной значение false, что требует использования ctypes или MScriptUtil.

В API 2 CheckFileCallback возвращает True или False, чтобы указать, должна ли загрузка файла продолжаться. Таким образом, в вашем примере измените 'import maya.OpenMaya' на 'import maya.api.OpenMaya' и удалите один параметр из списка параметров _test_raise_exception, и вам будет хорошо идти.

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

import maya.api.OpenMaya as OpenM
batchFileList = [r"c:\path\to\file.ma", r"c:\path\to\file2.ma"]

def _test_raise_exception(fileObject, clientData):
    #pretending that a file ref failed below. Ref path validation code would go here.
    clientData['exception'] = RuntimeError('bad ref {}'.format(fileObject.expandedFullName()))
    return False

for file_ in batchFileList:
    try:
        outData = {} 
        cId = OpenM.MSceneMessage.addCheckFileCallback(OpenM.MSceneMessage.kBeforeCreateReferenceCheck, _test_raise_exception, clientData=outData)
        rv = cmds.file(file_, o=1)
        OpenM.MSceneMessage.removeCallback(cId)
        if 'exception' in outData: #check if an exception was set, if so, raise it
            raise outData['exception']
    except:
        #handle the exception here
        print 'load cancelled'

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

0 голосов
/ 04 мая 2018

Вы пробовали cmds.file с lrd = 'none' и prompt=0 в автономном режиме? Это приведет к тому, что вы попадете в файл без диалогового окна, чтобы вы могли предварительно проверить ссылки перед их загрузкой и пропустить файл, если они скрыты.

...