Updated 4/11/2015: fixing the embedded code that was busted by Blogger.
I’m still working on the followup to Rescuing Maya GUI From Itself, but while I was at it this StackOverflow question made me realize that the same trick works for pyMel-style property access to things like position or rotation. If you’re a member of the anti-pyMel brigade you might find this a useful trick for things like pCube1.translation = (0,10,0)
. Personally I use pyMel most of the time, but this is a good supplement or alternative for haterz or for special circumstance where pymel is too heavy.
The goal is to be able to write something like
from xform import Xform example = Xform('pCube1') print example.translation # [0,0,0] example.rotation = (0,40, 0)
The process s about as simple as it can get thanks to the magic of descriptors. This example spotlights one advantage of descriptors over getter/setter property functions: by inheriting the two classes (BBoxProperty
and WorldXformProperty
) I can get 4 distinct behaviors (world and local, read-write and read-only) with very little code and no if-checks.
''' xform.py Exposes the xform class: a simple way to set maya position, rotation and similar properties with point notation. (c) 2014 Steve Theodore. Distributed under the MIT License (http://opensource.org/licenses/MIT) TLDR: Use, change and share, please retain this copyright notice. ''' import maya.cmds as cmds class XformProperty( object ): CMD = cmds.xform ''' Descriptor that allows for get-set access of transform properties ''' def __init__( self, flag ): self.Flag = flag self._q_args = {'q':True, flag:True} self._e_args = {flag: 0} def __get__( self, obj, objtype ): return self.CMD( obj, **self._q_args ) def __set__( self, obj, value ): self._e_args[self.Flag] = value self.CMD( obj, **self._e_args ) class WorldXformProperty( XformProperty ): ''' Get-set property in world space ''' def __init__( self, flag ): self.Flag = flag self._q_args = {'q':True, flag:True, 'ws':True} self._e_args = {flag: 0, 'ws':True} class BBoxProperty ( XformProperty ): ''' Read only property for bounding boxes ''' def __set__( self, obj, value ): raise RuntimeError ( "bounding box is a read-only property!" ) class WorldBBoxProperty ( WorldXformProperty, BBoxProperty ): ''' Read only property for bounding boxes ''' pass class Xform( object ): ''' Thin wrapper providing point-notation access to transform attributes example = Xform('pCube1') # |pCube1 example.translation # [0,0,0] example.translation = [0,10,0] For most purposes Xforms are just Maya unicode object names. Note this does NOT track name changes automatically. You can, however, use 'rename': example = Xform('pCube1') example.rename('fred') print example.Object # |fred ''' def __init__( self, obj ): self.Object = cmds.ls( obj, l=True )[0] def __repr__( self ): return unicode( self.Object ) # so that the command will work on the string name of the object # property descriptors These are descriptors so they live at the class level, # not inside __init__! translation = XformProperty( 'translation' ) rotation = XformProperty( 'rotation' ) scale = XformProperty( 'scale' ) pivots = XformProperty( 'pivots' ) world_translation = WorldXformProperty( 'translation' ) world_rotation = WorldXformProperty( 'rotation' ) world_pivots = WorldXformProperty( 'pivots' ) # maya does not allow 'world scale' - it's dependent on the parent scale # always local scaleTranslation = XformProperty( 'scaleTranslation' ) rotateTranslation = XformProperty( 'rotateTranslation' ) boundingBox = BBoxProperty( 'boundingBox' ) world_boundingBox = WorldBBoxProperty( 'boundingBox' ) def rename( self, new_name ): self.Object = cmds.ls( cmds.rename( self.Object, new_name ), l=True )[0] @classmethod def ls( cls, *args, **kwargs ): ''' Returns a list of Xforms, using the same arguments and flags as the default ls command ''' try: nodes = cmds.ls( *cmds.ls( *args, **kwargs ), type='transform' ) return map ( Xform, nodes ) except: return []
You may note the absence of a __metaclass__
. In this case, with only a single class, a meta would be an unnecessary complication. Meanwhile the code for MayaGUI itself is up on GitHub. Comments and/or contributions welcome!
No comments:
Post a Comment