def getSpaceTargetsNames(src): ''' this procedure returns a 2-tuple: a list of all targets, and a list of user specified names - for the right click menus ''' constraint = findConstraint(src) if constraint is None: return [], [] space = findSpace(src, constraint) if space is None: return [], [] constraintType = nodeType(constraint) constraintFunc = getattr(cmd, constraintType) targetsOnConstraint = constraintFunc(constraint, q=True, tl=True) trigger = Trigger(src) SPECIAL_STRING = 'parent to ' LEN_SPECIAL_STRING = len(SPECIAL_STRING) tgts, names = [], [] for slotIdx, slotName, slotCmd in trigger.iterMenus(): if slotName.startswith(SPECIAL_STRING): names.append(slotName[LEN_SPECIAL_STRING:]) cmdStrObj = ChangeSpaceCmd(slotCmd) cmdIndex = cmdStrObj.getIndex() tgts.append(targetsOnConstraint[cmdIndex]) return tgts, names
def getSpaceTargetsNames( src ): ''' this procedure returns a 2-tuple: a list of all targets, and a list of user specified names - for the right click menus ''' constraint = findConstraint( src ) if constraint is None: return [], [] space = findSpace( src, constraint ) if space is None: return [], [] constraintType = nodeType( constraint ) constraintFunc = getattr( cmd, constraintType ) targetsOnConstraint = constraintFunc( constraint, q=True, tl=True ) trigger = Trigger( src ) SPECIAL_STRING = 'parent to ' LEN_SPECIAL_STRING = len( SPECIAL_STRING ) tgts, names = [], [] for slotIdx, slotName, slotCmd in trigger.iterMenus(): if slotName.startswith( SPECIAL_STRING ): names.append( slotName[ LEN_SPECIAL_STRING: ] ) cmdStrObj = ChangeSpaceCmd( slotCmd ) cmdIndex = cmdStrObj.getIndex() tgts.append( targetsOnConstraint[ cmdIndex ] ) return tgts, names
def getControlsFromObjs( control ): ''' attempts to retrieve the pole vector control, the ik handle and all fk controls given an ik rig control. The information is returned in a 3 tuple containing: ikHandle, poleControl, fkControls ''' errorValue = None, None, None, None try: part = rigPrimitives.RigPart.InitFromItem( control ) return part.getControl( 'control' ), part.getIkHandle(), part.getControl( 'poleControl' ), part.getFkControls() except rigPrimitives.RigPartError: pass #so if the control we've been given isn't a rig primitive, lets try to extract whatever information we can from right click commands - if any exist trigger = Trigger( ikControl ) switchCmdStr = None for n, cmdName, cmdStr in trigger.iterMenus(): if cmdName.lower() == _IK_CMD_NAME: switchCmdStr = trigger.resolve( cmdStr ) break if switchCmdStr is None: printWarningStr( "Cannot find the %s command - aborting!" % _IK_CMD_NAME ) return errorValue #extract the control handle from the switch command - it may or may not exist, depending on which rexStr = re.compile( '-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE ) match = rexStr.search( switchCmdStr ) if not match: if match.groups()[0]: control = match.groups()[0] #extract the ik handle from the switch command rexStr = re.compile( '-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE ) match = rexStr.search( switchCmdStr ) if not match: printWarningStr( "Could not determine the ik handle from the given control" ) return errorValue handle = match.groups()[0] if handle is None: printWarningStr( "Could not find the ik handle at the given connect index!" ) return errorValue #now extract the pole control from the switch command rexStr = re.compile( '-pole \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE ) match = rexStr.search( switchCmdStr ) if not match: printWarningStr( "Could not determine the pole vector control from the given control" ) return errorValue poleControl = match.groups()[0] if poleControl is None: printWarningStr( "Could not find the ik handle at the given connect index!" ) return errorValue return control, poleControl, handle, getJointsFromIkHandle( handle )
def removeSpace( src, tgt ): ''' removes a target (or space) from a "space switching" object ''' tgts, names = getSpaceTargetsNames( src ) tgt_mobject = asMObject( tgt ) name = None for index, (aTgt, aName) in enumerate( zip( tgts, names ) ): aTgt = asMObject( aTgt ) if aTgt == tgt_mobject: name = aName break if name is None: raise AttributeError( "no such target" ) delete = False if len( tgts ) == 1: delete = True constraint = findConstraint( src ) parentAttrOn = findSpaceAttrNode( src ) space = findSpace( src ) srcTrigger = Trigger( src ) cmds = srcTrigger.iterMenus() if delete: delete( constraint ) deleteAttr( '%s.parent' % src ) else: constraintType = nodeType( constraint ) constraintFunc = getattr( cmd, constraintType ) constraintFunc( tgt, constraint, rm=True ) for slot, cmdName, cmdStr in srcTrigger.iterMenus(): if cmdName == ( "parent to %s" % name ): srcTrigger.removeMenu( slot ) #rebuild the parent attribute newNames = names[:] newNames.pop( index ) addAttr( '%s.parent' % parentAttrOn, e=True, enumName=':'.join( newNames ) ) #now we need to update the indicies in the right click command - all targets that were beyond the one we #just removed need to have their indices decremented for slot, cmdName, cmdStr in srcTrigger.iterMenus(): if not cmdName.startswith( 'parent to ' ): continue cmdStrObj = ChangeSpaceCmd( cmdStr ) cmdIndex = cmdStrObj.getIndex() if cmdIndex < index: continue cmdStrObj = cmdStrObj.setIndex( cmdIndex-1 ) srcTrigger.setMenuCmd( slot, cmdStrObj )
def findSpaceAttrNode(obj): ''' returns the node that contains the parent attribute for the space switch ''' parentAttrOn = "" trigger = Trigger(obj) for slotIdx, slotName, slotCmd in trigger.iterMenus(): if slotName.startswith('parent to '): cmdStrObj = ChangeSpaceCmd(slotCmd) connectToken = cmdStrObj.getConnectToken() return trigger.resolve(connectToken)
def findSpaceAttrNode( obj ): ''' returns the node that contains the parent attribute for the space switch ''' parentAttrOn = ""; trigger = Trigger( obj ) for slotIdx, slotName, slotCmd in trigger.iterMenus(): if slotName.startswith( 'parent to ' ): cmdStrObj = ChangeSpaceCmd( slotCmd ) connectToken = cmdStrObj.getConnectToken() return trigger.resolve( connectToken )
def _build( cls, **kw ): scale = kw.get( 'scale', skeletonBuilder.TYPICAL_HEIGHT ) scale /= 1.5 world = buildControl( 'main', shapeDesc=ShapeDesc( None, 'hex', AX_Y ), oriented=False, scale=scale, niceName='The World' ) parts = group( empty=True, name='parts_grp' ) qss = sets( empty=True, text="gCharacterSet", n="body_ctrls" ) masterQss = sets( empty=True, text="gCharacterSet", n="all_ctrls" ) exportRelative = buildControl( 'exportRelative', shapeDesc=ShapeDesc( None, 'cube', AX_Y_NEG ), pivotModeDesc=PivotModeDesc.BASE, oriented=False, size=(1, 0.5, 1), scale=scale ) parentConstraint( world, exportRelative ) attrState( exportRelative, ('t', 'r', 's'), *LOCK_HIDE ) attrState( exportRelative, 'v', *HIDE ) setAttr( '%s.v' % exportRelative, False ) #turn scale segment compensation off for all joints in the scene for j in ls( type='joint' ): setAttr( '%s.ssc' % j, False ) sets( qss, add=masterQss ) attrState( world, 's', *NORMAL ) connectAttr( '%s.scale' % world, '%s.scale' % parts ) connectAttr( '%s.scaleX' % world, '%s.scaleY' % world ) connectAttr( '%s.scaleX' % world, '%s.scaleZ' % world ) #add right click items to the world controller menu worldTrigger = Trigger( str( world ) ) qssIdx = worldTrigger.connect( str( masterQss ) ) #add world control to master qss sets( world, add=masterQss ) sets( exportRelative, add=masterQss ) #turn unwanted transforms off, so that they are locked, and no longer keyable attrState( world, 's', *NO_KEY ) attrState( world, ('sy', 'sz'), *LOCK_HIDE ) attrState( parts, [ 't', 'r', 's', 'v' ], *LOCK_HIDE ) controls = world, exportRelative namedNodes = parts, masterQss, qss return controls, namedNodes
def createLineOfActionMenu( controls, joints ): ''' deals with adding a "draw line of action" menu to each control in the controls list. the line is drawn through the list of joints passed ''' if not joints: return if not isinstance( controls, (list, tuple) ): controls = [ controls ] joints = list( joints ) jParent = getNodeParent( joints[ 0 ] ) if jParent: joints.insert( 0, jParent ) for c in controls: cTrigger = Trigger( c ) spineConnects = [ cTrigger.connect( j ) for j in joints ] Trigger.CreateMenu( c, "draw line of action", "zooLineOfAction;\nzooLineOfAction_multi { %s } \"\";" % ', '.join( '"%%%d"'%idx for idx in spineConnects ) )
def getControlsFromObjs(control): ''' attempts to retrieve the pole vector control, the ik handle and all fk controls given an ik rig control. The information is returned in a 3 tuple containing: ikHandle, poleControl, fkControls ''' errorValue = None, None, None, None try: part = rigPrimitives.RigPart.InitFromItem(control) return part.getControl('control'), part.getIkHandle(), part.getControl( 'poleControl'), part.getFkControls() except rigPrimitives.RigPartError: pass #so if the control we've been given isn't a rig primitive, lets try to extract whatever information we can from right click commands - if any exist trigger = Trigger(ikControl) switchCmdStr = None for n, cmdName, cmdStr in trigger.iterMenus(): if cmdName.lower() == _IK_CMD_NAME: switchCmdStr = trigger.resolve(cmdStr) break if switchCmdStr is None: printWarningStr("Cannot find the %s command - aborting!" % _IK_CMD_NAME) return errorValue #extract the control handle from the switch command - it may or may not exist, depending on which rexStr = re.compile('-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE) match = rexStr.search(switchCmdStr) if not match: if match.groups()[0]: control = match.groups()[0] #extract the ik handle from the switch command rexStr = re.compile('-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE) match = rexStr.search(switchCmdStr) if not match: printWarningStr( "Could not determine the ik handle from the given control") return errorValue handle = match.groups()[0] if handle is None: printWarningStr( "Could not find the ik handle at the given connect index!") return errorValue #now extract the pole control from the switch command rexStr = re.compile('-pole \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE) match = rexStr.search(switchCmdStr) if not match: printWarningStr( "Could not determine the pole vector control from the given control" ) return errorValue poleControl = match.groups()[0] if poleControl is None: printWarningStr( "Could not find the ik handle at the given connect index!") return errorValue return control, poleControl, handle, getJointsFromIkHandle(handle)
def add(src, tgt, name=None, space=None, maintainOffset=True, nodeWithParentAttr=None, skipTranslationAxes=(), skipRotationAxes=(), constraintType=CONSTRAINT_PARENT): global AXES AXES = list(AXES) if space is None: space = listRelatives(src, p=True, pa=True)[0] if nodeWithParentAttr is None: nodeWithParentAttr = src if not name: name = getNiceName(tgt) if name is None: name = camelCaseToNice(str(tgt)) #if there is an existing constraint, check to see if the target already exists in its target list - if it does, return the condition used it uses attrState(space, ('t', 'r'), lock=False) existingConstraint = findConstraint(src) if existingConstraint: constraintType = nodeType(existingConstraint) constraintFunc = getattr(cmd, constraintType) targetsOnConstraint = constraintFunc(existingConstraint, q=True, tl=True) if tgt in targetsOnConstraint: idx = targetsOnConstraint.index(tgt) aliases = constraintFunc(existingConstraint, q=True, weightAliasList=True) cons = listConnections('%s.%s' % (existingConstraint, aliases[idx]), type='condition', d=False) return cons[0] #when skip axes are specified maya doesn't handle things properly - so make sure #ALL transform channels are connected, and remove unwanted channels at the end... preT, preR = getAttr('%s.t' % space)[0], getAttr('%s.r' % space)[0] if existingConstraint: chans = CONSTRAINT_CHANNELS[constraintType] for channel, constraintAttr in zip(*chans): for axis in AXES: spaceAttr = '%s.%s%s' % (space, channel, axis) conAttr = '%s.%s%s' % (existingConstraint, constraintAttr, axis) if not isConnected(conAttr, spaceAttr): connectAttr(conAttr, spaceAttr) #get the names for the parents from the parent enum attribute cmdOptionKw = {'mo': True} if maintainOffset else {} if objExists('%s.parent' % nodeWithParentAttr): srcs, names = getSpaceTargetsNames(src) addAttr('%s.parent' % nodeWithParentAttr, e=True, enumName=':'.join(names + [name])) #if we're building a pointConstraint instead of a parent constraint AND we already #have spaces on the object, we need to turn the -mo flag off regardless of what the #user set it to, as the pointConstraint maintain offset has different behaviour to #the parent constraint if constraintType in (CONSTRAINT_POINT, CONSTRAINT_ORIENT): cmdOptionKw = {} else: addAttr(nodeWithParentAttr, ln='parent', at="enum", en=name) setAttr('%s.parent' % nodeWithParentAttr, keyable=True) #now build the constraint constraintFunction = getattr(cmd, constraintType) constraint = constraintFunction(tgt, space, **cmdOptionKw)[0] weightAliasList = constraintFunction(constraint, q=True, weightAliasList=True) targetCount = len(weightAliasList) constraintAttr = weightAliasList[-1] condition = shadingNode('condition', asUtility=True, n='%s_to_space_%s#' % (getShortName(src), getShortName(tgt))) setAttr('%s.secondTerm' % condition, targetCount - 1) setAttr('%s.colorIfTrue' % condition, 1, 1, 1) setAttr('%s.colorIfFalse' % condition, 0, 0, 0) connectAttr('%s.parent' % nodeWithParentAttr, '%s.firstTerm' % condition) connectAttr('%s.outColorR' % condition, '%s.%s' % (constraint, constraintAttr)) #find out what symbol to use to find the parent attribute parentAttrIdx = 0 if not apiExtensions.cmpNodes(space, src): parentAttrIdx = triggered.addConnect(src, nodeWithParentAttr) #add the zooObjMenu commands to the object for easy space switching Trigger.CreateMenu(src, "parent to %s" % name, ChangeSpaceCmd.Create(targetCount - 1, parentAttrIdx)) #when skip axes are specified maya doesn't handle things properly - so make sure #ALL transform channels are connected, and remove unwanted channels at the end... for axis, value in zip(AXES, preT): if axis in skipTranslationAxes: attr = '%s.t%s' % (space, axis) delete(attr, icn=True) setAttr(attr, value) for axis, value in zip(AXES, preR): if axis in skipRotationAxes: attr = '%s.r%s' % (space, axis) delete(attr, icn=True) setAttr(attr, value) #make the space node non-keyable and lock visibility attrState(space, ['t', 'r', 's'], lock=True) attrState(space, 'v', *control.HIDE) return condition