Как прервать загрузку файла в Maya, запущенную через cmds.file в python

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

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

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

Разрешение недопустимых путей ссылок исторически выполнялось вручную через всплывающее окно, однако в больших пакетах постоянное присмотр за экземпляром 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 не выполнен». В документах по открытому API Python говорится, что привязки предпочитают исключения кодам возврата MStatus хотя, поэтому я ожидал, что это сработает.

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

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

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


person Nambread    schedule 30.04.2018    source источник
comment
FWIW, отказ от МБ не совсем сумасшедший вариант — многие студии делают это именно по этой причине :(   -  person theodox    schedule 02.05.2018
comment
@theodox Я думаю так же, когда мне нужно проверять файлы без накладных расходов на открытие через Maya.   -  person Nambread    schedule 08.05.2018


Ответы (2)


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

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

В API 1 большинство методов принимают те же параметры, что и в C++. Это означает, что CheckFileCallback будет передано три параметра, первый из которых является ссылкой на логическую переменную 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'

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

person Nambread    schedule 02.07.2018
comment
В качестве дополнительного пояснения: аргумент fileObject, показанный в обратном вызове _test_raise_exception, является экземпляром MFileObject. Вы можете использовать его методы, чтобы разрешить путь к файлу на диске и проверить, существует ли он или нет. Не полагайтесь на метод MFileObject.exists(), так как он всегда возвращает True. - person Nambread; 03.07.2018

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

person theodox    schedule 04.05.2018