import maya.cmds as cmds def _getHierarchyRootJoint( joint="" ): """ Function to find the top parent joint node from the given 'joint' maya node Args: joint (string) : name of the maya joint to traverse from Returns: A string name of the top parent joint traversed from 'joint' Example: topParentJoint = _getHierarchyRootJoint( joint="LShoulder" ) """ # Search through the rootJoint's top most joint parent node rootJoint = joint while (True): parent = cmds.listRelatives( rootJoint, parent=True, type='joint' ) if not parent: break; rootJoint = parent[0] return rootJoint
I've used this particular function for part of the traversal from mesh->skinCluster->influence->top parent joint. I've used it for mostly exporter, animation tools and for rigging purposes - building an export skeleton layer on a game rig.
For the purposes of my personal project - the code needs to be as fast as possible for the utility functions. I like to stay away from plugin dependencies for Maya tools where possible, so I am working with Maya commands engine for my Maya utility code - it's not as Pythonic as PyMel, but is faster and worth spending the extra time to consider if you are worried about speed of the tool. It's a trade off to consider when thinking of the needs of the tool. For instance the Rigging System that I've been blogging about was written with PyMel, where as most of the animation tools I've worked with I have used the Maya commands engine. With my timing decorator on I am averaging about 0.0075-0.008s for this function traversing about 250 joints up the chain.
Speaking of the time decorator, here is mine that I created to track/debug my utility stuff. I would suggest using logging instead of print, print is bloated and would provide less accurate data for you to analyze.
from functools import wraps import time import logging import maya.utils
# Create debug logger within in - a few Maya version block the basic logger logger = logging.getLogger( "MyDebugLogger" ) logger.propagate = False handler = maya.utils.MayaGuiLogHandler() handler.setLevel( logging.INFO ) formatter = logging.Formatter( "%(message)s" ) handler.setFormatter( formatter ) logger.addHandler( handler )
def timeDecorator( f ): """ Decorator function to apply a timing process to a function given Args: f (object) : Python function passed through the decorator tag Returns: return the value from the function wrapped with the decorator function process Examples: @timeDecorator def myFunc( arg1, arg2 ): """ @wraps(f) def wrapped( *args, **kwargs ): """ Wrapping the timing calculation around the function call Returns: Result of the called wrapped function """ # log the process time t0 = time.clock() r = f( *args, **kwargs ) logger.warning( "{funcName} processing took : {processTime}".format( funcName=f.__name__, processTime= + time.clock() - t0 ) ) return r return wrapped