1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import maya, os
27 import maya.mel as meval
28 import maya.cmds as m
29 import maya.OpenMaya as OpenMaya
30 from slum import *
31
33 '''
34 wraps a maya node as if it was a dictionary. Attrs are dictionary keys and
35 adding a new key will add and attribute in the node.
36 this class makes use of color/vector classes (color.py and vector.py) to create color/vectors attributes
37 see slum for more info about color/vector classes
38
39 classNode also have some special methods that wraps some really usefull api methods, like setConnectable and
40 setInternal.
41 Also, some low level api methos to return an MObject of the node, a MFnDependecyNode object of the node and
42 MFnAttribute of the specified key (attribute)
43 '''
45 self.node = node
46 if data != None:
47 if type(data) != dict:
48 raise Exception("'%s' can only be initialized with a dict" % self.__class__.__name__)
49 self.update(data)
50
51 - def attr(self, key):
52 return "%s.%s" % (self.node, key)
53
54 - def addAttr(self, key, item, hidden=False):
55 t = eval(item.__class__.__name__)
56
57 if not m.objExists( self.attr(key) ):
58 if t in [int,long]:
59 m.addAttr( self.node, ln=key, at='long', hidden=hidden )
60 elif t==float:
61 m.addAttr( self.node, ln=key, at='float', hidden=hidden )
62 elif t==bool:
63 m.addAttr( self.node, ln=key, at='bool', hidden=hidden )
64 elif t == str:
65 m.addAttr( self.node, ln=key, dt='string', hidden=hidden )
66 elif t in [vector, normal, color, point]:
67 isColor = False
68 dataTypes={
69 vector: ['X','Y','Z'],
70 point: ['PX','PY','PZ'],
71 normal: ['NX','NY','NZ'],
72 color: ['R','G','B'],
73 }
74 children=dataTypes[t]
75 maya.cmds.addAttr( self.node, ln=key, at="float3", usedAsColor=t is color, hidden=False )
76 maya.cmds.addAttr( self.node, ln="%s%s" % (key,children[0]), at="float", dv=int(item[0]), keyable=True, parent=key, hidden=False )
77 maya.cmds.addAttr( self.node, ln="%s%s" % (key,children[1]), at="float", dv=int(item[1]), keyable=True, parent=key, hidden=False )
78 maya.cmds.addAttr( self.node, ln="%s%s" % (key,children[2]), at="float", dv=int(item[2]), keyable=True, parent=key, hidden=False )
79 else:
80
81 m.addAttr( self.node, ln=key, dt='string', hidden=True )
82
84 self.addAttr(key, item)
85 t = item.__class__.__name__
86 if t=='str':
87 m.setAttr( self.attr(key), item, type="string" )
88 elif t in ['vector', 'normal', 'color', 'point']:
89 m.setAttr( self.attr(key), item[0], item[1], item[2], type="double3" )
90 elif t in ['dict','_dict','list','tuple']:
91 m.setAttr( self.attr(key), "%s/%s" % (item.__class__.__name__,str(item)), type="string" )
92 else:
93 m.setAttr( self.attr(key), item )
94
96 if not m.objExists( self.attr(key) ):
97 raise Exception( 'Attribute %s does not exist in node.' % self.attr(key) )
98 value = m.getAttr(self.attr(key))
99 ret = value
100 t = type(ret)
101 if t in [str, unicode]:
102 ret = str(value)
103
104 dataType = ret.split('/')[0]
105 if dataType in ['dict','list','tuple']:
106 data = eval(ret.replace('%s/' % dataType,''))
107
108 ret = self._dict(self, key)
109 ret.update(data, callingFromClassNode=True)
110
111 elif t in [list]:
112 if m.objExists( "%sX" % self.attr(key) ):
113 ret = vector(value[0][0], value[0][1], value[0][2])
114 elif m.objExists( "%sPX" % self.attr(key) ):
115 ret = point(value[0][0], value[0][1], value[0][2])
116 elif m.objExists( "%sNX" % self.attr(key) ):
117 ret = normal(value[0][0], value[0][1], value[0][2])
118 elif m.objExists( "%sR" % self.attr(key) ):
119 ret = color(value[0][0], value[0][1], value[0][2])
120 else:
121 ret = [value[0][0], value[0][1], value[0][2]]
122 return ret
123
126
129
131 name = self.__class__.__name__
132 list = {}
133 for each in self.keys():
134 list[each] = self.getAttr(each)
135 return "%s('%s',%s)" % (name, self.node, str(list) )
138
140 return len(m.listAttr(self.node))
141
143 excluded = ['message']
144 excludedTypes = ['TdataCompound']
145 list = []
146 for each in m.listAttr(self.node):
147 try:
148 if each not in excluded and '.' not in each:
149 if m.getAttr(self.attr(each), type=True) not in excludedTypes :
150 list.append(str(each))
151 except:
152 pass
153 return list
154
156 return f in m.listAttr(self.node)
157
159 if type(f) != dict:
160 raise Exception('%s.update only accepts dicts' % self.__class__.__name__)
161 for each in f:
162 self.setAttr(each, f[each])
163
165 m.deleteAttr(self.attr(key))
166
167
168
169
171 list = OpenMaya.MSelectionList()
172 list.add( self.node )
173 mobj = OpenMaya.MObject()
174 list.getDependNode( 0, mobj )
175 return mobj
176
179
182
184 ret=[key]
185 if self.__getitem__(key).__class__.__name__ in ['color']:
186 ret.extend(['%sR' % key,'%sG' % key,'%sB' % key])
187 elif self.__getitem__(key).__class__.__name__ in ['vector','normal','point']:
188 ret.extend(['%sX' % key,'%sY' % key,'%sZ' % key])
189 return ret
190
194
198
202
206
210
214
216 '''
217 _classNode = classNode that own this data
218 key = original key(attr) in the classnode
219 index = all the keys that are needed to get to this data from the original classNode attr(list)
220 '''
222 if not self.updatingFrom:
223 self.updatingFrom = True
224 dict.clear(self)
225 data = self._classNode.getAttr(self.key)
226 data.updatingFrom = True
227 index = "['%s']" % ']['.join(self.index)
228 if not self.index:
229 index=""
230 dict.update( self, eval( 'data%s' % index ) )
231 data.updatingFrom = False
232 self.updatingFrom = False
233
235 if not self.updating:
236 self.updating = True
237 data = self._classNode.getAttr(self.key)
238 data.updatingFrom = True
239 index = "['%s']" % ']['.join(self.index)
240 if not self.index:
241 index=""
242 exec( 'data%s=%s' % ( index, dict.__repr__(self) ) )
243 self._classNode.setAttr(self.key, data)
244
245 self.updating = False
246
247 - def __init__(self, _classNode, key, index=[]):
248 self.updating = False
249 self.updatingFrom = False
250 dict.__init__(self)
251 self.key = key
252 self._classNode = _classNode
253 self.index = index
261 - def update(self, data, callingFromClassNode=False):
286
287
288