1
2 """
3 Contains patch classes that are altering their respective api classes
4
5 The classes here are rather verbose and used as patch-template which can be
6 handled correctly by epydoc, and whose method will be used to patch the respective
7 api classes.
8
9 As they are usually derived from the class they patch , they could also be used directly
10
11 :note: **never import classes directly in here**, import the module instead, thus
12 **not**: thisImportedClass **but**: module.thisImportedClass !
13 """
14 __docformat__ = "restructuredtext"
15
16 import base
17 import mrv.maya.undo as undo
18 import mrv.util as util
19 from mrv.interface import iDagItem
20
21 import maya.OpenMaya as api
22 import maya.cmds as cmds
23
24 import inspect
25 import itertools
26 import it
27 import os
34 """Called by package __init__ method to finally apply the patch according to
35 the template classes
36 Template classes must derive from the to-be-patched api class first, and can derive
37 from helper classes providing basic patch methods.
38 Helper classes must derive from Abstract to indicate their purpose
39
40 If a class has an _applyPatch method, it will be called and not additional. If
41 it returns True, the class members will be applied as usual, if False the method will stop
42
43 :note: overwritten api methods will be renamed to _api_methodname
44 :note: currently this method works not recursively"""
45 module = __import__( "mrv.maya.nt.apipatch", globals(), locals(), ['apipatch'] )
46 classes = [ v for v in globals().values() if inspect.isclass(v) ]
47 forbiddenMembers = [ '__module__','_applyPatch','__dict__','__weakref__','__doc__' ]
48 apply_globally = int(os.environ.get('MRV_APIPATCH_APPLY_GLOBALLY', 0))
49
50 ns = None
51 if apply_globally:
52 ns = 'm'
53
54
55
56 for cls in classes:
57
58
59 templateclasses = [ cls ]
60 templateclasses.extend( cls.__bases__[ 1: ] )
61
62
63
64 templateclasses.reverse()
65
66
67 if cls is Abstract or cls.__bases__[0] is Abstract:
68 continue
69
70 apicls = cls.__bases__[0]
71
72
73
74 if hasattr( cls, "_applyPatch" ):
75 if not cls._applyPatch( ):
76 continue
77
78 for tplcls in templateclasses:
79 util.copyClsMembers( tplcls, apicls, overwritePrefix="_api_",
80 forbiddenMembers = forbiddenMembers,
81 copyNamespaceGlobally=ns)
82
83
84 pass
85
88 """Class flagging that subclasses should be abstract and are only to be used
89 as superclass """
90 pass
91
95 """Base patch class for all indicated classes
96
97 :note: idea for patches from pymel"""
98 - def __str__( self ): return str(float(self))
99 - def __int__( self ): return int(float(self))
100
101
102
103 if hasattr(api.MTime, 'asUnits'):
104 - def __float__( self ): return self.asUnits(self.uiUnit())
105 else:
106 - def __float__( self ): return getattr(self, 'as')(self.uiUnit())
107
108 - def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, float(self) )
109
110
111 -class MTime( api.MTime, TimeDistanceAngleBase ) :
113
114 -class MDistance( api.MDistance, TimeDistanceAngleBase ) :
116
117 -class MAngle( api.MAngle, TimeDistanceAngleBase ) :
119
123 """:note: Classes derived from this base should not be used directly"""
124 @classmethod
126 """Read per-class values from self and create appropriate methods and
127 set them as well
128
129 :note: idea from pymel"""
130 def __len__(self):
131 """ Number of components in Maya api iterable """
132 return self._length
133
134 type.__setattr__( cls.__bases__[0], '__len__', __len__ )
135
136 def __iter__(self):
137 """ Iterates on all components of a Maya base iterable """
138 for i in range( self._length ) :
139 yield self.__getitem__( i )
140
141 type.__setattr__( cls.__bases__[0], '__iter__', __iter__)
142
143 def __str__( self ):
144 return "[ %s ]" % " ".join( str( f ) for f in self )
145
146
147 type.__setattr__( cls.__bases__[0], '__str__', __str__)
148
149 def __repr__( self ):
150 return "%s([ %s ])" % (type(self).__name__, " ".join( str( f ) for f in self ))
151
152
153 type.__setattr__( cls.__bases__[0], '__repr__', __repr__)
154
155
156 return True
157
158 -class PatchMatrix( Abstract, PatchIterablePrimitives ):
159 """Only for matrices"""
160 @classmethod
169
170 type.__setattr__( cls.__bases__[0], '__iter__', __iter__ )
171
172
173 def __str__( self ):
174 return "\n".join( str( v ) for v in self )
175
176
177 type.__setattr__( cls.__bases__[0], '__str__', __str__)
178
179 return True
180
181
182
183 -class MVector( api.MVector, PatchIterablePrimitives ):
185
186 -class MFloatVector( api.MFloatVector, PatchIterablePrimitives ):
188
189 -class MPoint( api.MPoint, PatchIterablePrimitives ):
191
192 -class MFloatPoint( api.MFloatPoint, PatchIterablePrimitives ):
194
195 -class MColor( api.MColor, PatchIterablePrimitives ):
197
198 -class MQuaternion( api.MQuaternion, PatchIterablePrimitives ):
200
203
204 -class MMatrix( api.MMatrix, PatchMatrix ):
207
211
225
232
238
242
246
252 """Create a function setting a value with undo support
253
254 :param dataTypeId: string naming the datatype, like "Bool" - capitalization is
255 important
256 :note: if undo is globally disabled, we will resolve to implementing a faster
257 function instead as we do not store the previous value.
258 :note: to use the orinal method without undo, use api.MPlug.setX(your_plug, value)"""
259
260 getattrfunc = getattroverride
261 if not getattrfunc:
262 getattrfunc = getattr( api.MPlug, "as"+dataTypeId )
263 setattrfunc = getattr( api.MPlug, "set"+dataTypeId )
264
265
266
267
268 finalWrappedSetAttr = None
269 if dataTypeId == "MObject":
270 def wrappedSetAttr( self, data ):
271
272 try:
273 curdata = getattrfunc( self )
274 except RuntimeError:
275 curdata = api.MObject()
276 op = undo.GenericOperation( )
277
278 op.setDoitCmd( setattrfunc, self, data )
279 op.setUndoitCmd( setattrfunc, self, curdata )
280
281 op.doIt()
282
283 finalWrappedSetAttr = wrappedSetAttr
284 else:
285 def wrappedSetAttr( self, data ):
286
287 curdata = getattrfunc( self )
288 op = undo.GenericOperation( )
289
290 op.setDoitCmd( setattrfunc, self, data )
291 op.setUndoitCmd( setattrfunc, self, curdata )
292
293 op.doIt()
294
295 finalWrappedSetAttr = wrappedSetAttr
296
297
298
299 wrappedUndoableSetAttr = undoable( finalWrappedSetAttr )
300 if wrappedUndoableSetAttr is finalWrappedSetAttr:
301 return setattrfunc
302
303
304 return wrappedUndoableSetAttr
305
306
307 -class MPlug( api.MPlug ):
308 """Patch applying mrv specific functionality to the MPlug. These methods will be
309 available through methods with the 'm' prefix.
310
311 Other methods are overridden to allow more pythonic usage of the MPlug class
312 if and only if it is not specific to mrv.
313
314 Additionally it provides aliases for all MPlug methods that are getters, but
315 don't start with a 'get'.
316
317 :note: Theoretically the MPlug would satisfy the 'iDagItem' interface, but due
318 to the method prefixes, it could not work here as it calls un-prefixed methods only."""
319
320 pa = api.MPlugArray( )
321 pa.setLength( 1 )
322
323
324
326 """
327 :return: number of physical elements in the array, but only if they are
328 not connected. If in doubt, run evaluateNumElements beforehand
329 :note: cannot use __len__ as it would break printing of pymel"""
330 if not self.isArray( ): return 0
331 return self.numElements( )
332
334 """:return: iterator object"""
335 for i in xrange(self.length()):
336 yield self.elementByPhysicalIndex(i)
337
338 __str__ = api.MPlug.name
339
341 """:return: our class representation"""
342 return "MPlug(%s)" % self.name()
343
345 """Compare plugs,handle elements correctly"""
346 if not api.MPlug._api___eq__( self, other ):
347 return False
348
349
350 if self.isElement():
351 return self.logicalIndex( ) == other.logicalIndex()
352
353 return True
354
356 return not( self.__eq__( other ) )
357
358
359
360
362 """:return: parent of this plug or None
363 :note: for array plugs, this is the array, for child plugs the actual parent """
364 p = None
365 if self.isChild():
366 p = self.parent()
367 elif self.isElement():
368 p = self.array()
369
370 if p.isNull( ):
371 return None
372 return p
373
374 - def mchildren( self , predicate = lambda x: True):
375 """:return: list of intermediate child plugs, [ plug1 , plug2 ]
376 :param predicate: return True to include x in result"""
377 outchildren = []
378 if self.isCompound():
379 nc = self.numChildren()
380 for c in xrange( nc ):
381 child = self.child( c )
382 if predicate( child ):
383 outchildren.append( child )
384
385
386
387 return outchildren
388
390 """:return: MPlug with the given childname
391 :raise AttributeError: if no child plug of the appropriate name could be found
392 :raise TypeError: self is not a compound plug"""
393 if not self.isCompound( ):
394 raise TypeError( "Plug %s is not a compound plug" % self )
395
396
397 nc = self.numChildren( )
398 for c in xrange( nc ):
399 child = self.child( c )
400 if ( child.partialName( ).split('.')[-1] == childname or
401 child.partialName( 0, 0, 0, 0, 0, 1 ).split('.')[-1] == childname ):
402 return child
403
404
405 raise AttributeError( "Plug %s has no child plug called %s" % ( self, childname ) )
406
407 - def msubPlugs( self , predicate = lambda x: True):
408 """
409 :return: list of intermediate sub-plugs that are either child plugs or element plugs.
410 Returned list will be empty for leaf-level plugs
411 :param predicate: return True to include x in result
412 :note: use this function recursively for easy deep traversal of all
413 combinations of array and compound plugs"""
414 if self.isCompound( ):
415 outchildren = []
416 nc = self.numChildren( )
417 for c in xrange( nc ):
418 child = self.child( c )
419 if predicate( child ):
420 outchildren.append( child )
421
422 return outchildren
423 elif self.isArray( ):
424 return [ elm for elm in self ]
425
426
427 return []
428
429
430
431
432
439
440 @undoable
444
445 @undoable
447 """if True, the plug may be set using animation curves"""
448 self._mhandleAttrSet( state, self.isKeyable, self.setKeyable )
449
450 @undoable
452 """if True, the plug's value will be cached, preventing unnecessary computations"""
453 self._mhandleAttrSet( state, self.isCachingFlagSet, self.setCaching )
454
455 @undoable
457 """if True, the plug will be visible in the channelbox, even though it might not
458 be keyable or viceversa """
459 self._mhandleAttrSet( state, self.isChannelBoxFlagSet, self.setChannelBox )
460
461
462
463
464
465
466 @classmethod
467 @undoable
469 """Connect multiple source plugs to the same amount of detsination plugs.
470
471 :note: This method provides the most efficient way to connect a large known
472 amount of plugs to each other
473 :param iter_source_destination: Iterator yielding pairs of source and destination plugs to connect
474 :param force: If True, existing input connections on the destination side will
475 be broken automatically. Otherwise the whole operation will fail if one
476 connection could not be made.
477 :note: Both iterators need to yield the same total amount of plugs
478 :note: In the current implementation, performance will be hurt if force
479 is specified as each destination has to be checked for a connection in advance"""
480 mod = undo.DGModifier( )
481 for source, dest in iter_source_destination:
482 if force:
483 destinputplug = dest.minput()
484 if not destinputplug.isNull():
485 if source == destinputplug:
486 continue
487
488 mod.disconnect(destinputplug, dest)
489
490
491 mod.connect(source, dest)
492
493 mod.doIt()
494 return mod
495
496
497 @undoable
499 """Connect this plug to the right hand side plug
500
501 :param destplug: the plug to which to connect this plug to.
502 :param force: if True, the connection will be created even if another connection
503 has to be broken to achieve that.
504 If False, the connection will fail if destplug is already connected to another plug
505 :return: destplug allowing chained connections a.connectTo(b).connectTo(c)
506 :raise RuntimeError: If destination is already connected and force = False"""
507 mod = undo.DGModifier( )
508
509
510
511 if force:
512 destinputplug = destplug.minput()
513 if not destinputplug.isNull():
514
515 if self == destinputplug:
516 return destplug
517
518
519 mod.disconnect( destinputplug, destplug )
520
521
522
523 mod.connect( self, destplug )
524
525 try:
526 mod.doIt( )
527 except RuntimeError:
528 raise RuntimeError("Failed to connect %s to %s as destination is already connected or incompatible" % (self, destplug))
529
530 return destplug
531
532 @undoable
533 - def mconnectToArray( self, arrayplug, force = True, exclusive_connection = False ):
534 """Connect self an element of the given arrayplug.
535
536 :param arrayplug: the array plug to which you want to connect to
537 :param force: if True, the connection will be created even if another connection
538 has to be broken to achieve that.
539 :param exclusive_connection: if True and destplug is an array, the plug will only be connected
540 to an array element if it is not yet connected
541 :return: newly created element plug or the existing one"""
542
543
544 if arrayplug.isArray( ):
545 if exclusive_connection:
546 arrayplug.evaluateNumElements( )
547 for delm in arrayplug:
548 if self == delm.minput():
549 return delm
550
551
552
553
554
555 return self.mconnectTo( arrayplug.mnextLogicalPlug( ), force = force )
556
557 raise AssertionError( "Given plug %r was not an array plug" % arrayplug )
558
559 @undoable
561 """Completely disconnect all inputs and outputs of this plug. The plug will not
562 be connected anymore.
563
564 :return: self, allowing chained commands"""
565 self.mdisconnectInput()
566 self.mdisconnectOutputs()
567 return self
568
569 @undoable
582
583 @undoable
585 """Disconnect all outgoing connections if they exist
586
587 :return: self, allowing chained commands"""
588 outputplugs = self.moutputs()
589 if not len( outputplugs ):
590 return self
591
592 mod = undo.DGModifier()
593 for destplug in outputplugs:
594 mod.disconnect( self, destplug )
595 mod.doIt()
596 return self
597
598 @undoable
600 """Disconnect this plug from other plug if they are connected
601
602 :param other: MPlug that will be disconnected from this plug
603 :return: other plug allowing to chain disconnections"""
604 try:
605 mod = undo.DGModifier( )
606 mod.disconnect( self, other )
607 mod.doIt()
608 except RuntimeError:
609 pass
610 return other
611
612 @undoable
614 """Disconnect this plug from the given node if they are connected
615
616 :param other: Node that will be completely disconnected from this plug"""
617 for p in self.moutputs():
618 if p.mwrappedNode() == other:
619 self.mdisconnectFrom(p)
620
621
622
623
624
625
626 @staticmethod
628 """:return: True if lhsplug and rhs plug are connected - the direction does not matter
629 :note: equals lhsplug & rhsplug"""
630 return lhsplug.misConnectedTo( rhsplug ) or rhsplug.misConnectedTo( lhsplug )
631
633 """:return: True if this plug is connected to destination plug ( in that order )
634 :note: return true for self.misConnectedTo(destplug) but false for destplug.misConnectedTo(self)
635 :note: use the mhaveConnection method whether both plugs have a connection no matter which direction
636 :note: use `misConnected` to find out whether this plug is connected at all"""
637 return destplug in self.moutputs()
638
640 """:return: MPlugArray with all plugs having this plug as source
641 :todo: should the method be smarter and deal nicer with complex array or compound plugs ?"""
642 outputs = api.MPlugArray()
643 self.connectedTo( outputs, False, True )
644 return outputs
645
647 """
648 :return: first plug that has this plug as source of a connection, or null plug
649 if no such plug exists.
650 :note: convenience method"""
651 outputs = self.moutputs()
652 if len( outputs ) == 0:
653 return self.pa[0]
654 return outputs[0]
655
672
693
695 """
696 :return: graph iterator with self as root, args and kwargs are passed to `it.iterGraph`.
697 Plugs are returned by default, but this can be specified explicitly using
698 the plug=True kwarg"""
699 import it
700 kwargs['plug'] = kwargs.get('plug', True)
701 return it.iterGraph(self, *args, **kwargs)
702
710
712 """
713 :return: iterator over the graph starting at this plug in output(downstream) direction.
714 Plugs will be returned by default
715 :note: see `it.iterGraph` for valid args and kwargs"""
716 kwargs['input'] = False
717 return self.miterGraph(*args, **kwargs)
718
720 """:return: tuple with input and outputs ( inputPlug, outputPlugs )"""
721 return ( self.minput( ), self.moutputs( ) )
722
723
724
725
727 """:return: list of plugs on this node that this plug affects or is being affected by
728 :param by: if false, affected attributplugs will be returned, otherwise the attributeplugs affecting this one
729 :note: you can also use the `base.DependNode.dependencyInfo` method on the node itself if plugs are not
730 required - this will also be faster
731 :note: have to use MEL :("""
732 ownnode = self.mwrappedNode()
733 attrs = cmds.affects( self.mwrappedAttribute().name() , ownnode.name(), by=by ) or list()
734 outplugs = list()
735 depfn = api.MFnDependencyNode( ownnode.object() )
736
737 for attr in attrs:
738 outplugs.append( depfn.findPlug( attr ) )
739 return outplugs
740
742 """:return: list of plugs affected by this one"""
743 return self.mdependencyInfo( by = False )
744
746 """:return: list of plugs affecting this one"""
747 return self.mdependencyInfo( by = True )
748
749
750
751
753 """:return: index of logical indexed plug that does not yet exist
754 :note: as this method does a thorough search, it is relatively slow
755 compared to a simple numPlugs + 1 algorithm
756 :note: only makes sense for array plugs"""
757 indices = api.MIntArray()
758 self.getExistingArrayAttributeIndices( indices )
759
760 logicalIndex = 0
761 numIndices = indices.length()
762
763
764 if numIndices == 1:
765 logicalIndex = indices[0] + 1
766 else:
767
768 for i in xrange( numIndices - 1 ):
769 if indices[i+1] - indices[i] > 1:
770 logicalIndex = indices[i] + 1
771 break
772 else:
773 logicalIndex = indices[i+1] + 1
774
775
776 return logicalIndex
777
779 """:return: plug at newly created logical index
780 :note: only valid for array plugs"""
781 return self.elementByLogicalIndex(self.mnextLogicalIndex())
782
784 """:return: Attribute instance of our underlying attribute"""
785 return base.Attribute(self.attribute())
786
788 """
789 :return: wrapped Node of the plugs node
790 :note: instance information gets lost this way, the respective instance
791 can be re-retrieved using the instance information on this instanced
792 attribute, if this is an instanced attribute"""
793 return base.NodeFromObj(self.node())
794
795 - def masData( self, *args, **kwargs ):
796 """:return: our data Mobject wrapped in `base.Data`
797 :note: args and kwagrs have to be provided as MDGContext.fsNormal
798 does not exist in maya 8.5, so we have to hide that fact."""
799 return base.Data(self.asMObject(*args, **kwargs))
800
802 """
803 :return: string returning the absolute and fully qualified name of the
804 plug. It might take longer to evaluate but is safe to use if you want to
805 convert the resulting string back to the actual plug"""
806 return self.partialName(1, 1, 1, 0, 1, 1)
807
808
809
810
811
812
813
814 msetBool = _mplug_createUndoSetFunc( "Bool" )
815 msetChar = _mplug_createUndoSetFunc( "Char" )
816 msetShort = _mplug_createUndoSetFunc( "Short" )
817 msetInt = _mplug_createUndoSetFunc( "Int" )
818 msetFloat = _mplug_createUndoSetFunc( "Float" )
819 msetDouble = _mplug_createUndoSetFunc( "Double" )
820 msetString = _mplug_createUndoSetFunc( "String" )
821 msetMAngle = _mplug_createUndoSetFunc( "MAngle" )
822 msetMDistance = _mplug_createUndoSetFunc( "MDistance" )
823 msetMTime = _mplug_createUndoSetFunc( "MTime" )
824 msetMObject = _mplug_createUndoSetFunc( "MObject" )
825
826
827
828
829 mctf = lambda self,other: self.mconnectTo( other, force=True )
830 mct = lambda self,other: self.mconnectTo( other, force=False )
831 mict = misConnectedTo
832 mhc = lambda lhs,rhs: MPlug.mhaveConnection( lhs, rhs )
833 mdc = mdisconnectFrom
834 mwn = mwrappedNode
835 mwa = mwrappedAttribute
836
837
838
839
840 if int(os.environ.get('MRV_DEBUG_MPLUG_SETX', 0)):
842 """Get attribute for MPlug which will raise if a setX method is used.
843 This could cause undo bugs that you'd better catch before they hit the user"""
844 if attr.startswith('set'):
845 raise AssertionError("%s method called on MPlug - this causes undo-issues if it happens unintended" % attr)
846 return api.MPlug._api___getattribute__(self, attr)
847
848
849
850 MPlug.__getattribute__ = __getattribute__
851
852
853
854
855
856
857
858
859 -class ArrayBase( Abstract ):
860 """ Base class for all maya arrays to easily fix them
861
862 :note: set _apicls class variable to your api base class """
863
866
868 """:note: does not work as it expects a pointer type - probably a bug"""
869 return self.set( item, index )
870
871 @classmethod
873 """:return: Array created from the given elements"""
874 ia = cls()
875 ia.setLength(len(args))
876
877 ci = 0
878 for elm in args:
879 ia[ci] = elm
880 ci += 1
881
882
883 return ia
884
885 @classmethod
887 """:return: Array created from elements yielded by iter
888 :note: this one is less efficient than `mfromList` as the final length
889 of the array is not predetermined"""
890 ia = cls()
891 append = ia.append
892 for index in iter:
893 append(index)
894 return ia
895
896 @classmethod
898 """:return: Array created from the given list of elements"""
899 ia = cls()
900 ia.setLength(len(list))
901
902 ci = 0
903 set = ia.set
904 for elm in list:
905 set(elm, ci)
906 ci += 1
907
908
909 return ia
910
911
912 _plugarray_getitem = api.MPlugArray.__getitem__
913 _objectarray_getitem = api.MObjectArray.__getitem__
914 _colorarray_getitem = api.MColorArray.__getitem__
915 _pointarray_getitem = api.MPointArray.__getitem__
916 _floatpointarray_getitem = api.MFloatPointArray.__getitem__
917 _doublearray_getitem = api.MDoubleArray.__getitem__
918 _floatarray_getitem = api.MFloatArray.__getitem__
919 _floatvectorarray_getitem = api.MFloatVectorArray.__getitem__
920 _vectorarray_getitem = api.MVectorArray.__getitem__
922 """ Wrap MPlugArray to make it compatible to pythonic contructs
923
924 :note: for performance reasons, we do not provide negative index support"""
925 _apicls = api.MPlugArray
926
928 """:return: iterator object"""
929 for i in xrange(len(self)):
930 yield api.MPlug(_plugarray_getitem( self, i ))
931
935
938 """ Wrap MObject to make it compatible to pythonic contructs.
939
940 :note: This array also fixes an inherent issue that comes into play when
941 MObjects are returned using __getitem__, as the reference count does not natively
942 get incremented, and the MObjects will be obsolete once the parent-array goes out
943 of scope
944 :note: for performance reasons, we do not provide negative index support"""
945 _apicls = api.MObjectArray
946
948 """:return: iterator object"""
949 for i in xrange(len(self)):
950 yield api.MObject(_objectarray_getitem( self, i ))
951
953 """Copy the MObjects we return to assure their ref count gets incremented"""
954 return api.MObject(_objectarray_getitem( self, index ))
955
958 """ Wrap MColor to make it compatible to pythonic contructs.
959
960 :note: for performance reasons, we do not provide negative index support"""
961 _apicls = api.MColorArray
962
964 """:return: iterator object"""
965 for i in xrange(len(self)):
966 yield _colorarray_getitem( self, i )
967
970 """ Wrap MPoint to make it compatible to pythonic contructs.
971
972 :note: for performance reasons, we do not provide negative index support"""
973 _apicls = api.MPointArray
974
976 """:return: iterator object"""
977 for i in xrange(len(self)):
978 yield _pointarray_getitem( self, i )
979
982 """ Wrap MFloatVector to make it compatible to pythonic contructs.
983
984 :note: for performance reasons, we do not provide negative index support"""
985 _apicls = api.MFloatVectorArray
986
991
994 """:note: for performance reasons, we do not provide negative index support"""
995 _apicls = api.MVectorArray
996
998 """:return: iterator object"""
999 for i in xrange(len(self)):
1000 yield _vectorarray_getitem( self, i )
1001
1004 """ Wrap MFloatPoint to make it compatible to pythonic contructs.
1005
1006 :note: for performance reasons, we do not provide negative index support"""
1007 _apicls = api.MFloatPointArray
1008
1013
1016 """:note: for performance reasons, we do not provide negative index support"""
1017 _apicls = api.MDoubleArray
1018
1020 """:return: iterator object"""
1021 for i in xrange(len(self)):
1022 yield _doublearray_getitem( self, i )
1023
1026 """:note: for performance reasons, we do not provide negative index support"""
1027 _apicls = api.MFloatArray
1028
1030 """:return: iterator object"""
1031 for i in xrange(len(self)):
1032 yield _floatarray_getitem( self, i )
1033
1034
1035 -class MIntArray( api.MIntArray, ArrayBase ):
1036 """Attach additional creator functions"""
1037 _apicls = api.MIntArray
1038
1039 @classmethod
1041 """:return: An MIntArray initialized with integers ranging from i to j
1042 :param i: first integer of the returned array
1043 :param j: last integer of returned array will have the value j-1"""
1044 if j < i:
1045 raise ValueError("j < i violated")
1046 if j < 0 or i < 0:
1047 raise ValueError("negative ranges are not supported")
1048
1049 ia = api.MIntArray()
1050 l = j - i
1051 ia.setLength(l)
1052
1053
1054 ci = 0
1055 set = ia.set
1056 for i in xrange(i, j):
1057 set(i, ci)
1058 ci += 1
1059
1060
1061
1062
1063
1064
1065
1066 return ia
1067
1070 _apicls = api.MSelectionList
1071
1073 """:return: True if we contain rhs
1074 :note: As we check for Nodes as well as MayaAPI objects, we are possibly slow"""
1075 if isinstance(rhs, base.DagNode):
1076 return self.hasItem(rhs.dagPath())
1077 elif isinstance(rhs, base.DependNode):
1078 return self.hasItem(rhs.object())
1079 else:
1080 return self.hasItem(rhs)
1081
1082
1083 @staticmethod
1085 """:return: MSelectionList initialized from the given iterable of strings
1086 :param kwargs: passed to `base.toSelectionListFromNames`"""
1087 return base.toSelectionListFromNames(iter_strings, **kwargs)
1088
1089 @staticmethod
1091 """
1092 :return: MSelectionList as initialized from the given iterable of Nodes,
1093 MObjects, MDagPaths, MPlugs or strings
1094 :param kwargs: passed to `base.toSelectionList`"""
1095 return base.toSelectionList(iter_items, **kwargs)
1096
1097
1098 mfromIter = mfromList
1099
1100 @staticmethod
1104
1105 @staticmethod
1107 """
1108 :return: MSelectionList as initialized from the given list of tuple( DagNode, Component ),
1109 Component can be a filled Component object or null MObject
1110 :param kwargs: passed to `base.toComponentSelectionList`"""
1111 return base.toComponentSelectionList(iter_components, **kwargs)
1112
1113 - def mtoList( self, *args, **kwargs ):
1114 """:return: list with the contents of this MSelectionList
1115 :note: all args and kwargs passed to `it.iterSelectionList`"""
1116 return list(self.mtoIter(*args, **kwargs))
1117
1118 - def mtoIter( self, *args, **kwargs ):
1119 """:return: iterator yielding of Nodes and MPlugs stored in this given selection list
1120 :note: all args and kwargs are passed to `it.iterSelectionList`"""
1121 return it.iterSelectionList( self, *args, **kwargs )
1122
1124 """
1125 :return: Iterator yielding node, component pairs, component is guaranteed
1126 to carry a component, implying that this iterator applies a filter
1127 :param kwargs: passed on to `it.iterSelectionList`"""
1128 kwargs['handleComponents'] = True
1129 pred = lambda pair: not pair[1].isNull()
1130 kwargs['predicate'] = pred
1131 return it.iterSelectionList( self, **kwargs )
1132
1134 """:return: Iterator yielding all plugs on this selection list.
1135 :param kwargs: passed on to `it.iterSelectionList`"""
1136 kwargs['handlePlugs'] = True
1137 pred = lambda n: isinstance(n, api.MPlug)
1138 kwargs['predicate'] = pred
1139 return it.iterSelectionList( self, **kwargs )
1140
1143 """Provides common functionality for all MItMesh classes"""
1144
1146 """:return: Iterator yielding self for each item in the iteration
1147 :note: the iteration will be reset before beginning it
1148 :note: extract the information you are interested in yourself"""
1149 self.reset()
1150 next = self.next
1151 if hasattr(self, 'count'):
1152 for i in xrange(self.count()):
1153 yield self
1154 next()
1155
1156 else:
1157 isDone = self.isDone
1158 while not isDone():
1159 yield self
1160 next()
1161
1162
1163
1164 -class MItMeshVertex( api.MItMeshVertex, MeshIteratorBase ):
1166
1167 -class MItMeshEdge( api.MItMeshEdge, MeshIteratorBase ):
1169
1172
1175
1176