如何中止通过 python 中的 cmds.file 在 Maya 中加载文件

How to abort the loading of a file in Maya started via cmds.file in python

我有代码 运行s 在 Maya 中对文件进行批处理操作。实际的实现并不重要,只要知道它得到一个文件路径列表,maya 打开文件,然后依次对每个文件执行操作。

如果引用出于某种原因(例如无效路径)无效,我想中止整个场景的加载并跳到批处理列表中的下一个场景。

查看本网站和其他地方的其他问题时,我只能看到用户询问如何查询参考文献。我已经有了这样做的合理功能,就是在该功能之后要做什么 returns 一个让我难过的无效参考路径。

解决无效引用路径历来是通过弹出窗口手动完成的,但是在大批量不断维护 Maya 实例是不可行的。也不会抑制弹出窗口 window 本身,因为我相信它仍然会打开文件,并且 运行 在现场处于无效状态时的批处理操作。

我已经通过 the maya cmds python module 尝试不加载引用,但是当使用 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 并在 before open 事件上注册回调。下面的代码在功能上与批处理的设置方式相同:

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 indicates that if the callback function returns False the operation is aborted,文件仍会加载。

同样,将 return False 替换为 raise RuntimeError 不会让我捕捉到异常。相反,cmds.file 完成并仅在日志中打印出一条小消息 "python callback failed"。 The python open api docs say that the bindings prefer exceptions over MStatus return codes though, so I would've expected that to work.

We have removed the MStatus class. Python exceptions must be used instead of MStatus.

我是不是漏掉了什么?必须有办法做到这一点。构建一个非常粗糙的 .ma 解析器是另一种选择,但这意味着放弃对 .mb 文件的支持,我不想这样做。

感谢您的宝贵时间!

您是否尝试过 cmds.filelrd = 'none'prompt=0 的独立使用?这应该可以让你在没有对话框的情况下进入文件,这样你就可以在加载它们之前预先检查引用,如果它们很无聊就跳过文件。

我在 Maya 论坛上问过这个 got a very helpful hint from a poster by the handle of JoeAlter-Inc:

The documentation you're referring to is for the Maya Python API 2, but the classes you're using are from the Maya Python API 1.

In API 1 most methods take exactly the same parameters as in C++. This means that a CheckFileCallback will be passed three parameters, the first of which is a reference to a C++ bool variable. To abort the file load you must set that variable to false, which requires using either ctypes or MScriptUtil.

In API 2 the CheckFileCallback returns True or False to indicate whether the file load should proceed. So in your example change 'import maya.OpenMaya' to 'import maya.api.OpenMaya' and remove one parameter from _test_raise_exception's parameter list and you should be good to go.

我继续测试它,发现如果我抛出一个异常,它会在内部被捕获并且进程继续。答案是加一些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'

这样我可以在批处理过程中加载我的文件,并以 pythonic 方式处理加载失败的任何异常。