def matchIkToFk(ikControl, ikPole, offset=100.0, msgAttr='fkjoints', autoKey=True):
    """
    Matches ikControl and ikPole Vector control to match the current pose of underlying
    fk duplicate joint chains
    Finds the fk joints using a previously created message connection to the attribute msgAttr
    """

    fkJoints = pmc.listConnections('{0}.{1}'.format(ikControl, msgAttr),
                                   destination=False, source=True)

    attr = pmc.listConnections('{0}.ikfk'.format(ikControl), destination=False,
                               source=True, plugs=True, scn=True)[0]
    switchControl = attr.node()
    switchAttr = attr.name(includeNode=False)

    frameBeforeCurrent = pmc.currentTime(q=True) - 1
    if autoKey:
        pmc.setKeyframe(switchControl, attribute=switchAttr, time=frameBeforeCurrent,
                        value=1, outTangentType='step')
        pmc.setKeyframe([ikControl, ikPole], time=frameBeforeCurrent, outTangentType='step')

        pmc.setKeyframe(switchControl, attribute=switchAttr, value=0, outTangentType='step')

    alignObjects(ikControl, fkJoints[-1])
    loc = getPoleVectorPosition(fkJoints, offset, curveGuide=False)
    alignObjects(ikPole, loc, position=True, rotation=False)
    pmc.delete(loc)

    if autoKey:
        pmc.setKeyframe([ikControl, ikPole], time=frameBeforeCurrent)

    pmc.headsUpMessage('BAMF!')
def matchIkToFk(ikControl,
                ikPole,
                offset=100.0,
                msgAttr='fkjoints',
                autoKey=True):
    """
    Matches ikControl and ikPole Vector control to match the current pose of underlying
    fk duplicate joint chains
    Finds the fk joints using a previously created message connection to the attribute msgAttr
    """

    fkJoints = pmc.listConnections('{0}.{1}'.format(ikControl, msgAttr),
                                   destination=False,
                                   source=True)

    attr = pmc.listConnections('{0}.ikfk'.format(ikControl),
                               destination=False,
                               source=True,
                               plugs=True,
                               scn=True)[0]
    switchControl = attr.node()
    switchAttr = attr.name(includeNode=False)

    frameBeforeCurrent = pmc.currentTime(q=True) - 1
    if autoKey:
        pmc.setKeyframe(switchControl,
                        attribute=switchAttr,
                        time=frameBeforeCurrent,
                        value=1,
                        outTangentType='step')
        pmc.setKeyframe([ikControl, ikPole],
                        time=frameBeforeCurrent,
                        outTangentType='step')

        pmc.setKeyframe(switchControl,
                        attribute=switchAttr,
                        value=0,
                        outTangentType='step')

    alignObjects(ikControl, fkJoints[-1])
    loc = getPoleVectorPosition(fkJoints, offset, curveGuide=False)
    alignObjects(ikPole, loc, position=True, rotation=False)
    pmc.delete(loc)

    if autoKey:
        pmc.setKeyframe([ikControl, ikPole], time=frameBeforeCurrent)

    pmc.headsUpMessage('BAMF!')
def matchFkToIk(fkControls, msgAttr='ikjoints', autoKey=True):
    """
    Matches fkControls to match the current pose of the underlying ik duplicate joint chains
    Finds the ik joints using a previously created message connection to the attribute msgAttr
    """

    ikJoints = None
    switchControl = None
    switchAttr = None
    for ctl in fkControls:
        if pmc.hasAttr(ctl, msgAttr):
            ikJoints = pmc.listConnections('{0}.{1}'.format(ctl, msgAttr),
                                           destination=False,
                                           source=True)

            attr = pmc.listConnections('{0}.ikfk'.format(ctl),
                                       destination=False,
                                       source=True,
                                       plugs=True,
                                       scn=True)[0]
            switchControl = attr.node()
            switchAttr = attr.name(includeNode=False)
            break

    if autoKey:
        frameBeforeCurrent = pmc.currentTime(q=True) - 1
        pmc.setKeyframe(switchControl,
                        attribute=switchAttr,
                        time=frameBeforeCurrent,
                        value=0,
                        outTangentType='step')
        pmc.setKeyframe(fkControls,
                        attribute='rotate',
                        time=frameBeforeCurrent,
                        outTangentType='step')

        pmc.setKeyframe(switchControl,
                        attribute=switchAttr,
                        value=1,
                        outTangentType='step')

    for ikj, ctl in izip(ikJoints, fkControls):
        alignObjects(ctl, ikj, position=False, rotation=True)

    if autoKey:
        pmc.setKeyframe(fkControls, attribute='rotate')

    pmc.headsUpMessage('BAMF!')
def matchFkToIk(fkControls, msgAttr='ikjoints', autoKey=True):
    """
    Matches fkControls to match the current pose of the underlying ik duplicate joint chains
    Finds the ik joints using a previously created message connection to the attribute msgAttr
    """

    ikJoints = None
    switchControl = None
    switchAttr = None
    for ctl in fkControls:
        if pmc.hasAttr(ctl, msgAttr):
            ikJoints = pmc.listConnections('{0}.{1}'.format(ctl, msgAttr),
                                           destination=False, source=True)

            attr = pmc.listConnections('{0}.ikfk'.format(ctl), destination=False,
                                       source=True, plugs=True, scn=True)[0]
            switchControl = attr.node()
            switchAttr = attr.name(includeNode=False)
            break

    if autoKey:
        frameBeforeCurrent = pmc.currentTime(q=True) - 1
        pmc.setKeyframe(switchControl, attribute=switchAttr, time=frameBeforeCurrent,
                        value=0, outTangentType='step')
        pmc.setKeyframe(fkControls, attribute='rotate', time=frameBeforeCurrent,
                        outTangentType='step')

        pmc.setKeyframe(switchControl, attribute=switchAttr, value=1, outTangentType='step')

    for ikj, ctl in izip(ikJoints, fkControls):
        alignObjects(ctl, ikj, position=False, rotation=True)

    if autoKey:
        pmc.setKeyframe(fkControls, attribute='rotate')

    pmc.headsUpMessage('BAMF!')
def squishySplineIk(startLoc, endLoc):
    ikJoints = list()
    startJoint = pmc.createNode('joint')
    adv.alignObjects(startJoint, startLoc)

    endJoint = pmc.createNode('joint')
    adv.alignObjects(endJoint, endLoc)
    pmc.parent(endJoint, startJoint)

    startJoint.orientJoint('xzy', secondaryAxisOrient='zup')
    pmc.makeIdentity(endJoint, apply=True, jointOrient=True)

    Splitter.doSplit(startJoint, 10)

    ikJoints.append(startJoint)
    ikJoints.extend(reversed(startJoint.getChildren(ad=True, type='joint')))

    for i, ikj in enumerate(ikJoints):
        ikj.radius.set(2)
        ikj.rename('ikj_spine{0:02d}'.format(i))

    # Create second set of joints
    rigJoints = adv.makeDuplicateJoints(joints=ikJoints, search='ikj_', replace='local_rig_', connectBone=False)
    # HACK I haven't figured out how to create SDK nodes procedurally,
    # so making some dummy locs to make the curve I need
    a = pmc.createNode('transform')
    b = pmc.createNode('transform')

    pmc.setKeyframe(a.ty, t=0, value=2.5, inTangentType='flat', outTangentType='flat')
    pmc.setKeyframe(a.ty, t=10, value=0, inTangentType='flat', outTangentType='flat')
    pmc.keyTangent(a.ty, index=[0], inAngle=0)
    pmc.keyTangent(a.ty, index=[1], inAngle=-30)
    pmc.keyTangent(a.ty, index=[0], outAngle=0)
    pmc.keyTangent(a.ty, index=[1], outAngle=-30)

    animSquashCurve = a.ty.listConnections()[0]
    animSquashCurve.output.disconnect(a.ty)
    animSquashCurve.rename('squash_ramp')

    pmc.setKeyframe(a.tx, t=0, value=0, inTangentType='flat', outTangentType='flat')
    pmc.setKeyframe(a.tx, t=5, value=1, inTangentType='flat', outTangentType='flat')
    pmc.setKeyframe(a.tx, t=10, value=0, inTangentType='flat', outTangentType='flat')

    animTwistCurve = a.tx.listConnections()[0]
    animTwistCurve.output.disconnect(a.tx)
    animTwistCurve.rename('twist_ramp')

    pmc.delete(a, b)

    animControls = dict()
    animControls['lower_spine'] = adv.makeControlNode('ctl_lower_spine', targetObject=rigJoints[2], alignRotation=False)
    animControls['middle_spine'] = adv.makeControlNode('ctl_middle_spine')
    animControls['upper_spine'] = adv.makeControlNode('ctl_upper_spine', targetObject=rigJoints[-2],
                                                      alignRotation=False)

    animControls['lower_spine'][0].rotateOrder.set(adv.ROO_YXZ)
    animControls['middle_spine'][0].rotateOrder.set(adv.ROO_YXZ)
    animControls['upper_spine'][0].rotateOrder.set(adv.ROO_YXZ)

    pmc.pointConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0],
                        animControls['middle_spine'][1], mo=False)

    pmc.orientConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0],
                         animControls['middle_spine'][1], mo=False)

    splineIk = pmc.ikHandle(sj=ikJoints[0], ee=ikJoints[-1], sol='ikSplineSolver', parentCurve=False,
                            createCurve=True, simplifyCurve=True, numSpans=2, rootOnCurve=False, n='sik_spine')

    splineIkHandle = splineIk[0]
    spline = splineIk[2]
    spline.rename('crv_spine')
    clusterJoints = list()
    clusterJoints.append(pmc.createNode('joint', n='clj_spine0'))
    pmc.parentConstraint(animControls['lower_spine'][0], clusterJoints[-1])

    clusterJoints.append(pmc.createNode('joint', n='clj_spine1'))
    pmc.parentConstraint(animControls['middle_spine'][0], clusterJoints[-1])

    clusterJoints.append(pmc.createNode('joint', n='clj_spine2'))
    pmc.parentConstraint(animControls['upper_spine'][0], clusterJoints[-1])

    pmc.skinCluster(clusterJoints, spline, maximumInfluences=3)

    pmc.parentConstraint(animControls['lower_spine'][0], ikJoints[0], maintainOffset=True)

    for clj in clusterJoints:
        clj.radius.set(3)

    splineIkHandle.dTwistControlEnable.set(1)
    splineIkHandle.dWorldUpType.set(4)
    splineIkHandle.dWorldUpAxis.set(0)
    splineIkHandle.dWorldUpVector.set([0.0, 0.0, 1.0])
    splineIkHandle.dWorldUpVectorEnd.set([0.0, 0.0, 1.0])

    animControls['lower_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrix)
    animControls['upper_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrixEnd)

    normalizeNode = stretchySplineIk(splineIkHandle, useScale=True, globalScaleAttr='ctl_main.size')
    sqrtScale = pmc.createNode('multiplyDivide', n='sqrt_spine_scale')
    sqrtScale.operation.set(3)
    sqrtScale.input2X.set(0.5)
    normalizeNode.outputX.connect(sqrtScale.input1X)

    invScale = pmc.createNode('multiplyDivide', n='div_spine_inverse_scale')
    invScale.operation.set(2)
    invScale.input1X.set(1.0)
    sqrtScale.outputX.connect(invScale.input2X)

    jointGroups = list()
    for i, jnt in enumerate(rigJoints):
        preTransform = adv.zeroOut(jnt, 'pre')
        jointGroups.append(preTransform)

        ikNode = adv.zeroOut(jnt, 'hlp_ik')
        pmc.pointConstraint(ikJoints[i], ikNode)
        pmc.orientConstraint(ikJoints[i], ikNode)

        twistNode = adv.zeroOut(jnt, 'hlp_twist')
        twistCache = pmc.createNode('frameCache', n='frm_{0}_twist'.format(jnt))
        animTwistCurve.output.connect(twistCache.stream)
        twistCache.varyTime.set(i)

        rotateMultiplier = pmc.createNode('multiplyDivide', n='mul_{0}_twist'.format(jnt.shortName()))

        twistCache.varying.connect(rotateMultiplier.input2X)
        animControls['middle_spine'][0].rotateY.connect(rotateMultiplier.input1X)
        rotateMultiplier.outputX.connect(twistNode.rotateX)

        volumeCache = pmc.createNode('frameCache', n='frm_{0}_volume'.format(jnt.shortName()))
        animSquashCurve.output.connect(volumeCache.stream)
        volumeCache.varyTime.set(i)

        pow_ = pmc.createNode('multiplyDivide', n='pow_{0}'.format(jnt.shortName()))
        pow_.operation.set(3)
        invScale.outputX.connect(pow_.input1X)
        volumeCache.varying.connect(pow_.input2X)
        pow_.outputX.connect(jnt.scaleY)
        pow_.outputX.connect(jnt.scaleZ)

    pmc.group(animControls['lower_spine'][1], animControls['upper_spine'][1], animControls['middle_spine'][1],
              n='grp_spine_anim')
    pmc.group(splineIkHandle, spline, n='grp_spine_rig_systems')
    pmc.group(clusterJoints, startJoint, n='grp_spine_system_joints')
    pmc.group(jointGroups, n='grp_spine_bind_joints')

    return rigJoints
def makeMultiConstraint(targets,
                        source,
                        controller,
                        attrName='currentSpace',
                        enumNames=None,
                        addLocatorSpace=True,
                        translation=True,
                        rotation=True,
                        maintainOffset=False):
    """
    creates a constraint between all to the targets to the passed in source.

    """

    targets = map(pmc.PyNode, targets)
    source = pmc.PyNode(source)
    controller = pmc.PyNode(controller)
    loc = None

    if enumNames is None:
        enumNames = map(str, targets)

    if addLocatorSpace:
        loc = pmc.spaceLocator(n='loc_follow_' + source.shortName())
        alignObjects(loc, source)
        targets.append(loc)
        enumNames.append('locator')

    skipTranslate = 'none'
    if not translation:
        skipTranslate = ['x', 'y', 'z']

    skipRotate = 'none'
    if not rotation:
        skipRotate = ['x', 'y', 'z']

    constraints = list()
    for tgt, spaceName in izip(targets, enumNames):
        enumAttr = getAttribute(controller,
                                attrName,
                                at='enum',
                                enumName=spaceName,
                                keyable=True,
                                longName=attrName)

        spaceEnums = enumAttr.getEnums().keys()
        if spaceName not in spaceEnums:
            spaceEnums.append(spaceName)
            enumAttr.setEnums(spaceEnums)

        index = enumAttr.getEnums().value(spaceName)

        if tgt is loc:
            tgtTransform = loc
        else:
            tgtTransform = pmc.createNode('transform',
                                          n='tgt_{0}_to_{1}'.format(
                                              source.shortName(),
                                              tgt.shortName()))
            alignObjects(tgtTransform, source)
            pmc.parentConstraint(tgt,
                                 tgtTransform,
                                 maintainOffset=maintainOffset)

        orient = pmc.orientConstraint(tgtTransform,
                                      source,
                                      skip=skipRotate,
                                      maintainOffset=maintainOffset)
        orient.interpType.set(2)
        constraints.append(orient)

        point = pmc.pointConstraint(tgtTransform,
                                    source,
                                    skip=skipTranslate,
                                    maintainOffset=maintainOffset)
        constraints.append(point)

        orientWeightList = orient.getWeightAliasList()
        orientWeightAttr = orientWeightList[-1]

        pointWeightList = point.getWeightAliasList()
        pointWeightAttr = pointWeightList[-1]

        nodeName = 'con_{0}_to_{1}_weight_{2:d}'.format(
            source.shortName(), tgt.shortName(), index)

        weightConditionNode = pmc.createNode('condition', n=nodeName)

        enumAttr.connect(weightConditionNode.firstTerm)

        weightConditionNode.secondTerm.set(index)
        weightConditionNode.colorIfTrueR.set(1)
        weightConditionNode.colorIfFalseR.set(0)

        weightConditionNode.outColorR.connect(pointWeightAttr)
        weightConditionNode.outColorR.connect(orientWeightAttr)

    return loc
def makeMultiConstraint(targets, source, controller, attrName='currentSpace',
                        enumNames=None, addLocatorSpace=True, translation=True, rotation=True, maintainOffset=False):
    """
    creates a constraint between all to the targets to the passed in source.

    """

    targets = map(pmc.PyNode, targets)
    source = pmc.PyNode(source)
    controller = pmc.PyNode(controller)
    loc = None

    if enumNames is None:
        enumNames = map(str, targets)

    if addLocatorSpace:
        loc = pmc.spaceLocator(n='loc_follow_' + source.shortName())
        alignObjects(loc, source)
        targets.append(loc)
        enumNames.append('locator')

    skipTranslate = 'none'
    if not translation:
        skipTranslate = ['x', 'y', 'z']

    skipRotate = 'none'
    if not rotation:
        skipRotate = ['x', 'y', 'z']

    constraints = list()
    for tgt, spaceName in izip(targets, enumNames):
        enumAttr = getAttribute(controller, attrName,
                                at='enum', enumName=spaceName, keyable=True, longName=attrName)

        spaceEnums = enumAttr.getEnums().keys()
        if spaceName not in spaceEnums:
            spaceEnums.append(spaceName)
            enumAttr.setEnums(spaceEnums)

        index = enumAttr.getEnums().value(spaceName)

        if tgt is loc:
            tgtTransform = loc
        else:
            tgtTransform = pmc.createNode('transform',
                                          n='tgt_{0}_to_{1}'.format(source.shortName(), tgt.shortName()))
            alignObjects(tgtTransform, source)
            pmc.parentConstraint(tgt, tgtTransform, maintainOffset=maintainOffset)

        orient = pmc.orientConstraint(tgtTransform, source, skip=skipRotate, maintainOffset=maintainOffset)
        orient.interpType.set(2)
        constraints.append(orient)

        point = pmc.pointConstraint(tgtTransform, source, skip=skipTranslate, maintainOffset=maintainOffset)
        constraints.append(point)

        orientWeightList = orient.getWeightAliasList()
        orientWeightAttr = orientWeightList[-1]

        pointWeightList = point.getWeightAliasList()
        pointWeightAttr = pointWeightList[-1]

        nodeName = 'con_{0}_to_{1}_weight_{2:d}'.format(source.shortName(), tgt.shortName(), index)

        weightConditionNode = pmc.createNode('condition', n=nodeName)

        enumAttr.connect(weightConditionNode.firstTerm)

        weightConditionNode.secondTerm.set(index)
        weightConditionNode.colorIfTrueR.set(1)
        weightConditionNode.colorIfFalseR.set(0)

        weightConditionNode.outColorR.connect(pointWeightAttr)
        weightConditionNode.outColorR.connect(orientWeightAttr)

    return loc