Reputation: 103
I'm just going to post what I have so far and try to describe the problem.
The script bellow tracks a transform object with custom attributes. It creates an interface to easily __get__
and __set__
to a maya node's attributes. This makes it easy to save attribute values into a scene that can load with the scene in the future. In the script I was using OpenMaya to track a dagObject, but simplified to try to work through the problem first. If you want to use this code, look into MDagPath and MSelectionList.
Now..
Attributes()
need to be declared outside of __init__
to work correctly.
Attributes()
as they are now, require a Transform() at creation.
If I create a Transform()
outside of an __init__
in the Clip()
, the resulting Transform()
instance will reference whatever latest Transform()
was created by this method (image)
Can't post image without reputation, so descriptively: three clips called _new_anim_, _new_anim_1, _new_anim_2. When script bellow runs, the output from the list is all _new_anim_2, which is the last transform that was initialized.
__init__
happens after the Attributes are created.
I need to pass a __init__
Transform
instance to an already initialized Attribute instance.
How?
Saying clip.transform = correctTransform
doesn't seem to replace the reference to correctTransfrom
. I need a way to pass a class instance to a class variables that are initialized outside of the __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)
Upvotes: 1
Views: 80
Reputation: 104762
If I am understanding your question correctly, it looks like you want the transform
variable in your Clip
class to be a instance-specific value, but you're having problems because it needs to be accessed by the Attribute
descriptors you're also adding to Clip
, which need to be declared as class variables.
I think the solution to this is to have the Attribute
class's __get__
and __set__
methods look for transform
on the instance
they are passed in, rather than on self
.
Try this:
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)
Upvotes: 1