如何在 PyMEL 中访问属性?

How are attributes accessed in PyMEL?

有多种方法可以访问 PyNode 的属性,例如 Transform,它具有 translationrotation 等属性。

import pymel.core as pm

cube = pm.polyCube()[0]

cube.translationX.set(1)
cube.translation.translationX.set(2)
cube.tx.set(3)
cube.t.tx.set(4)

# and more

我不明白这些属性是如何找到的,因为我找不到任何列出属性的文档? Transform 是否具有所有这些属性,其中每个属性都指向 DAG 节点的相应基础属性?映射发生在哪里以便找到正确的属性?

您可以只使用:

cube.listAttr()

我不确定他们是否包装了所有属性。

我自己有一个简单的 cmds 包装器,我只是通过覆盖动态添加节点的任何属性:getitemgetattr

这是 git 上的完整代码:https://github.com/DrWeeny/Whosebug/blob/master/59185039.py 这只是一个例子

class MAttr(object):
    """Represent a maya attribute

    Args:
        node (str): a string for the maya node affected
        attr (str): a string that represent the attribute
    Attributes:
        attr_bypass (str): regex to bypass the compound attributes, because i need to connect and getattr
    """
    attr_bypass = re.compile('\[(\d+)?:(\d+)?\]')

    def __init__(self, node, attr='result'):
        self.__dict__['node'] = node  #: str: current priority node evaluated
        self.__dict__['attribute'] = attr  #: str: current priority node evaluated
        self.__dict__['idx'] = 0  #: str: current priority node evaluated

    def __getitem__(self, item):
        """
        getitem has been overrided so you can select the compound attributes
        ``mn = MayaNode('cluster1')``
        ``mn.node.weightList[0]``
        ``mn.node.weightList[1].weights[0:100]``

        Notes:
            the notations with list[0:0:0] is class slice whereas list[0] is just and int

        Args:
            item (Any): should be slice class or an int

        Returns:
            cls : MAttr is updated with the chosen index/slice
        """
        if isinstance(item, int):
            self.__dict__['attribute'] = '{}[{}]'.format(self.attr, item)
        else:
            if not item.start and not item.stop and not item.step:
                item = ':'
            else:
                item = ':'.join([str(i) for i in [item.start, item.stop, item.step] if i != None])
            self.__dict__['attribute'] = '{}[{}]'.format(self.attr, item)
        return self

    def __getattr__(self, attr):
        """
        __getattr__ is overriden in order to select attributes
        Args:
            attr (str): name of the attribute, even if we loop throught,

        Returns:
            str: it join all the attributes that has been chained : weightList[0].weight

        """
        myattr = '{}.{}'.format(self.attr, attr)
        if myattr in self.listAttr(myattr):
            return MAttr(self._node, '{}.{}'.format(self.attr, attr))
        else:
            return self.__getattribute__(attr)

class MayaNode(object):
    """Represent a maya node as a class like pymel

    Only provide the name as a string, if you use preset, you can create a new node

    Note:
        Should use maya api for getting the node

    Args:
        name (str): a string for the maya node you want to encapsulate
        preset (:obj:`dict`, optional): Used for creating a new node from 'attrPreset'
            you can also just specify the nodeType with a string instead

    Attributes:
        maya_attr_name (maya_data): Any attribute from the name will look for actual maya attribute

    """

    def __init__(self, name, preset={}, blendValue=1):

        # this dict method is used to avoid calling __getattr__
        self.__dict__['node'] = name  #: str: current priority node evaluated
        self.__dict__['item'] = 1  #: int: can be either 0 or 1 and should be exented with Mesh or Cluster
        if preset:
            targ_ns = name.rsplit(':', 1)[0]
            self.loadNode(preset, blendValue, targ_ns)

    def __getitem__(self, item):
        """
        getitem has been overrided so you can select the main nodes sh or tr so when you do:
        ``mn = MayaNode('pCube1')``
        ``mn[0].node`` result as the transform
        ``mn[1].node`` result as the shape

        Note:
            By default ``mn.node`` is the transform
        """
        return self.setNode(item)

    def __getattr__(self, attr):
        """
        getattr has been overrided so you can select maya attributes and set them
        if you type an attribute, it will try to find if it exists in either shape or transform
        if it exists in both, it will always warn you that it returns shape in priority
        ``mn = MayaNode('pCube1')``
        ``mn.translateX = 10`` result in doing a cmds.setAttr
        ``mn.translateX.set(10)``
        ``mn.translateX.get()`` note that you to use get in order to do getAttr otherwise it __repr__ or __str__

        ``mn = MayaNode('cluster1')``
        ``mn.weightList[1].weights.get()`` is equivalent of cmds.getAttr('cluster1.weightList[1].weights[:]')

        Note:
            You cant have the value without .get()
        """
        if attr in self.listAttr(attr):
            return MAttr(self.node, attr)
        elif attr in self.__dict__:
            return self.__dict__[attr]
        else:
            try:
                return self.__getattribute__(attr)
            except AttributeError:
                cmds.warning('{} doesn\'t exists, return None instead')
                return None