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
Example #3
0
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 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 )
Example #8
0
	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
Example #9
0
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 ) )
Example #10
0
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