# FK_IK Nodal Setup Script

Great progress today!

I was able to figure out the nodal setup to smoothly blend from FK to IK using orient constraints. My script has lots of comments, so hopefully you can follow along.

```import maya.cmds as cmds

"""
This is a class that will take a set of 3 bones plus a driver attr and make a orient blend for them.
The driver must already have the attribute "IK_FK_Blend" on it.

Numerically, this node system does this:
1    1    1   .5     0
0   .5    1    1     1
"""

class ikFkBlend(object):
def __init__(self,ik,fk,bind,switch):
# init the ik fk and bind variables. These are just the names of the joints given
self.ik = ik
self.fk = fk
self.bind = bind
self.switch = switch

# create the orient constraint that orients the bind to a blend of those two joints (1 and 1)
self.orientConst = cmds.orientConstraint(ik,fk,bind)

# our md_blend node divides our switch attribute value by -10 so that it will work with our weights which are between 1 and 0
self.md_blend = cmds.createNode("multiplyDivide",n="md_blend#")
cmds.setAttr(self.md_blend + ".i2x",-10)
# an op of 2 is divide
cmds.setAttr(self.md_blend + ".op",2)
cmds.connectAttr(self.switch + ".IK_FK_Blend",self.md_blend + ".i1x")

# our reverse_fk node takes our md_blend value and flips it so that we go from 1 down to zero when our switch value goes over 0.
# If we didn't have this the values would go 1 1 1 .1 .2 .3 instead of 1 1 1 .9 .8 .7
self.reverse_fk = cmds.createNode("reverse",n="reverse_fk#")
cmds.connectAttr(self.md_blend + ".ox",self.reverse_fk + ".ix")

# our fk_cond is a less than condition. If the swtich value is less than 0 it is equal to the reverse_fk value. Otherwise it's 1
self.fk_cond = cmds.createNode("condition",n="fk_cond#")
# an op of 4 is "less than"
cmds.setAttr(self.fk_cond + ".op",4)
cmds.setAttr(self.fk_cond + ".st",0)
cmds.setAttr(self.fk_cond + ".cfr",1)
cmds.connectAttr(self.reverse_fk + ".ox",self.fk_cond + ".ctr")
cmds.connectAttr(self.switch + ".IK_FK_Blend",self.fk_cond + ".ft")

# that should read as something like "b_shoulder_orientConstraint1.fk_shoulderW0"
cmds.connectAttr(self.fk_cond + ".ocr",self.orientConst[0] + "." + self.fk + "W1")

# this takes our blend node and multiplies it by -1
self.ik_inv = cmds.createNode("multiplyDivide",n="ik_inv#")
cmds.setAttr(self.ik_inv + ".i2x",-1)
cmds.connectAttr(self.md_blend + ".ox",self.ik_inv + ".i1x")

# this node reverses that value, allowing the value to count up from 0
# If we hadn't reversed the md_blend value, the values would be 1 - -.5 and would give us values outside of our weight range
self.reverse_ik = cmds.createNode("reverse",n="reverse_ik#")
cmds.connectAttr(self.ik_inv + ".ox",self.reverse_ik + ".ix")

# our ik condition is a greater than op that makes the out value 1 unless the switch value is greater than 0. If it is, the value is equal to teh reverse_ik val.
self.ik_cond = cmds.createNode("condition",n="ik_condition#")
# set the op to 2, or "greater than"
cmds.setAttr(self.ik_cond + ".op",2)
cmds.setAttr(self.ik_cond + ".st",0)
cmds.setAttr(self.ik_cond + ".cfr",1)
cmds.connectAttr(self.switch + ".IK_FK_Blend",self.ik_cond + ".ft")
cmds.connectAttr(self.reverse_ik + ".ox",self.ik_cond + ".ctr")

cmds.connectAttr(self.ik_cond + ".ocr",self.orientConst[0] + "." + self.ik + "W0")

elbowBlend = ikFkBlend("ik_elbow","fk_elbow","b_elbow","ik_fk_blend")

```