获取 Maya 命令的参数标志和默认值

问题描述

我正在尝试获取任何给定 Maya 命令的标志和认值。在python中,我通常会使用inspect模块,但由于pymel只是一个包装器,我不认为这是一个选项。我希望 api 能够实现这一点,但没有遇到任何问题。下面是一个 ghetto 方法,适用于这个用例,但它很笨拙,必须进行大量修改才能真正适用于所有命令(不是我想走的路):

def getMayaCmdFlagDefaults(cmd):
    '''Get the flags and corresponding default values of a given MEL command.

    :Parameters:
        cmd (str) = A MEL command name.

    :Return:
        (dict) {'flag':<value>}
    '''
    obj_types = ['polyPlane','nurbsPlane'] #etc..

    for obj in obj_types:
        try:
            temp = getattr(pm,obj)(ch=0)
            node = getattr(pm,cmd)(temp)
            if node:
                result = Init.getAttributesMEL(node[0])
                pm.delete(temp)
                return result

        except Exception as error:
            print ('# Error: {}: {} #'.format(cmd,error))
            pm.delete(temp)


print (getMayaCmdFlagDefaults('polyReduce'))
# returns: {u'keepQuadsWeight': 0.0,u'symmetryPlaneW': 0.0,u'symmetryPlaneZ': 0.0,u'symmetryPlaneX': 0.0,u'symmetryPlaneY': 0.0,u'sharpness': 0.0,u'keepBorderWeight': 0.5,u'vertexMapName': None,u'vertexWeights': None,u'border': 0.5,u'keepBorder': True,u'triangleCount': 0,u'keepHardEdgeWeight': 0.5,u'keepCreaseEdge': True,u'percentageAchieved': 0.0,u'keepColorBorder': True,u'version': 0,u'triangleCountIn': 200,u'percentage': 0.0,u'keepMapBorderWeight': 0.5,u'useVirtualSymmetry': 0,u'keepColorBorderWeight': 0.5,u'symmetryTolerance': 0.0,u'geomWeights': 1.0,u'detail': 0.5,u'invertVertexWeights': True,u'keepHardEdge': True,u'keepCreaseEdgeWeight': 0.5,u'uvWeights': 0.0,u'vertexCount': 0,u'termination': 0,u'line': 0.5,u'weightCoefficient': 10000.0,u'vertexCountIn': 121,u'keepFaceGroupBorderWeight': 0.5,u'keepMapBorder': True,u'vertexCountAchieved': 0,u'keepFaceGroupBorder': True,u'triangulate': True,u'cachingReduce': False,u'weights': [],u'compactness': 0.0,u'vertexWeightCoefficient': 1.0,u'triangleCountAchieved': 0,u'keepOriginalVertices': False,u'symmetryPlane': (0.0,0.0,0.0),u'colorWeights': 0.0,u'preservetopology': True}

使用 Inspect(目前是首选方法):

print (inspect.getargspec(pm.polyReduce))
# returns: ArgSpec(args=[],varargs='args',keywords='kwargs',defaults=None)

print (inspect.getargspec(cmds.polyReduce))
# returns: TypeError: <built-in method polyReduce of module object at 0x000002B30DDE3078> is not a Python function

# Additional things of interest that I have tried:
# backport of inspect.signature for python 2.6+:
import funcsigs
bound_args = funcsigs.signature(pm.polyReduce)

# unwrap a decorated method:
def extract_wrapped(decorated):
    closure = (c.cell_contents for c in decorated.__closure__)
    return next((c for c in closure if isinstance(c,FunctionType)),None)

解决方法

问题是命令不提供该信息。您需要了解 cmds 模块正是它的名称;一系列用于填充/操作场景的命令。实际默认值通过其属性嵌入到实际节点类中。

该命令实际上是一个调用特殊类 (MPxCommand) 的“函数”,它的工作是解析您在 mel/python 中传递的参数并使用这些参数做一些事情。

例如,

cmds.polyPlane 接受一系列传递给它的参数,然后创建/修改节点并基本上包装它,因此它是可撤销的。没有任何参数,通常它会在您的场景中创建该对象的实例。默认值来自 polyPlane 本身的类,而不是用于创建它的 cmd.polyPlane 函数。当您将参数传递给 cmds.polyPlane 以更改其属性时,该命令只需创建 polyPlane,然后修改其属性...显式!

我认为你需要的是 cmds.attrInfo。检查其文档。他们在那里概述了一个可以帮助您入门的示例。你在正确的轨道上...

好消息是这些数据需要解析一次(除非应用程序更改为新版本,否则对象的属性默认值不会更改)。一旦您有一个创建脚本,然后使用 cmds.attrInfo 检查节点,您就可以将该信息转储到一个文件中,然后在需要该信息时读取该文件。

例如,您可能希望使用要确定优先级的节点列表启动一个简单的文本或 json 文件,然后运行一个脚本来读取节点列表、创建每个节点、解析其属性信息并转储这些详细信息到单独的文本或 json 文件,您可以稍后阅读。如果您需要有关其他节点的信息,只需使用新节点名称更新前一个文件,运行更新后一个文件的脚本。从小处着手,然后根据需要进行修改。