初始化顺序导致类实例问题

时间:2015-09-09 12:05:11

标签: python class maya

我要发布到目前为止的内容并尝试描述问题。

下面的脚本跟踪具有自定义属性的变换对象。它创建了一个易于__get____set__到maya节点属性的界面。这样可以轻松地将属性值保存到可以在将来加载场景的场景中。在脚本中,我使用OpenMaya来跟踪dagObject,但是简化为首先尝试解决问题。如果要使用此代码,请查看MDagPath和MSelectionList。

现在.. 需要在Attributes()之外声明__init__才能正常工作。 Attributes()就像现在一样,在创建时需要Transform()。 如果我在Transform()中的__init__之外创建Clip(),则生成的Transform()实例将引用此方法创建的最新Transform()(图片)

无法在没有声望的情况下发布图片,因此描述性地: 三个名为_new_anim _,_ new_anim_1,_new_anim_2的剪辑。 运行脚本时,列表中的输出都是_new_anim_2,这是最初初始化的转换。

在创建属性后

__init__发生。 我需要将__init__ Transform实例传递给已初始化的Attribute实例。

如何?

clip.transform = correctTransform似乎无法替换correctTransfrom的引用。我需要一种方法将类实例传递给在__init__之外初始化的类变量。

import maya.cmds as cmds

class Attribute(object):
    def __init__(self,transform,attr,*args):
        self.transform = transform
        self.attr = attr
        self.string = "string" in args
    def __set__(self, instance, value):
        if self.string:
            cmds.setAttr(self.transform.path()+"."+self.attr,value,dt="string")
        else:
            cmds.setAttr(self.transform.path()+"."+self.attr,value)
    def __get__(self, instance, owner):
        if self.string:
            return     cmds.getAttr(self.transform.path()+"."+self.attr,dt="string")
        return cmds.getAttr(self.transform.path()+"."+self.attr)

class Transform(object):
    def __init__(self):
        self.parent = ""
        self.name = ""
    def setObject(self,transform):
        self.parent = cmds.listRelatives(transform,p=1)[0]
        self.name = cmds.ls(transform,sn=1)[0]
    def path(self):
        return self.parent+"|"+self.name
    def getName(self):
        return cmds.ls(self.path(),sn=1)[0]
    def rename(self,value):
        self.name = cmds.ls(cmds.rename(self.path(),value),sn=1)[0]

class Clip(object):
    transform = Transform()
    start = Attribute(transform,"STA")
    end = Attribute(transform,"END")
    loop = Attribute(transform,"Loop")
    relative = Attribute(transform,"RelativeToStart")
    speedState = Attribute(transform,"SpeedState")
    speed = Attribute(transform,"SpeedVal")

    def __init__(self,transform):
        self.transform.setObject(transform)

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,看起来您希望transform类中的Clip变量是特定于实例的值,但是您遇到问题因为它需要是由Attribute描述符访问,您还要添加到Clip,这需要声明为类变量。

我认为解决这个问题的方法是让Attribute类的__get____set__方法在transform上传递instance,而不是self

试试这个:

class Attribute(object):
    def __init__(self,attr,*args): # no transform parameter or instance variable
        self.attr = attr
        self.string = "string" in args
    def __set__(self, instance, value): # look up transform on instance, rather than self
        if self.string:
            cmds.setAttr(instance.transform.path()+"."+self.attr,value,dt="string")
        else:
            cmds.setAttr(instance.transform.path()+"."+self.attr,value)
    def __get__(self, instance, owner): # here too
        if self.string:
            return     cmds.getAttr(instance.transform.path()+"."+self.attr,dt="string")
        return cmds.getAttr(instance.transform.path()+"."+self.attr)

# Transform can stay the same, though you could merge set_object into __init__

class Clip(object):
    # no more transform class variable
    start = Attribute("STA") # no more transform argument passed to the Attributes
    end = Attribute("END")
    loop = Attribute("Loop")
    relative = Attribute("RelativeToStart")
    speedState = Attribute("SpeedState")
    speed = Attribute("SpeedVal")

    def __init__(self,transform):
        self.transform = Transform() # create transform as an instance variable
        self.transform.setObject(transform)