create_fk_ik_chain_switch
Already made something like this years ago for my mock auto rigging. Making this one again for a manual rigging tasks on custom game model
import maya.cmds as cmds
import pymel.core as pm
def create_joint_chain():
# Create the main joint chain
joints = []
joint_names = ["shoulder_jnt", "elbow_jnt", "hand_jnt"]
positions = [(0, 10, 0), (1, 5, 0), (0, 0, 0)]
for name, pos in zip(joint_names, positions):
jnt = pm.joint(name=name, position=pos)
joints.append(jnt)
pm.select(clear=True)
return joints
def duplicate_joint_chain(joint_chain, prefix):
new_joint_chain = pm.duplicate(joint_chain)
for joint in new_joint_chain:
new_name = prefix + joint.nodeName().split("1")[0]
pm.rename(joint, new_name)
return new_joint_chain
def setup_ik_fk_switch(main_chain, fk_chain, ik_chain, ik_con, ik_pole_con, fk_con_list, switch_con):
# IK SETUP
ik_handle, effector = pm.ikHandle(startJoint=ik_chain[0], endEffector=ik_chain[-1], solver="ikRPsolver", name="arm_ikHandle")
effector.rename(ik_chain[-1] + "_eff")
pm.poleVectorConstraint(ik_pole_con, ik_handle)
pm.orientConstraint(ik_con,ik_chain[-1], maintainOffset=True)
ik_obj = None
if not ik_con:
ik_obj = pm.circle(name="ik_ctrl", normal=[0, 1, 0])[0]
pm.delete(pm.parentConstraint(ik_chain[-1], ik_obj))
else:
ik_obj = ik_con
pm.parent(ik_handle, ik_con)
# FK SETUP
fk_obj_list = None
if not fk_con_list:
fk_controls = []
for fk_jnt in fk_chain:
fk_ctrl = pm.circle(name=fk_jnt.name().replace("_jnt", "_ctrl"), normal=[0, 1, 0])[0]
pm.delete(pm.parentConstraint(fk_jnt, fk_ctrl))
pm.parentConstraint(fk_ctrl, fk_jnt, maintainOffset=True)
fk_controls.append(fk_ctrl)
pm.parent(fk_controls[2], fk_controls[1])
pm.parent(fk_controls[1], fk_controls[0])
fk_obj_list = fk_controls
else:
fk_obj_list = fk_con_list
for fk_jnt, fk_con in zip(fk_chain, fk_con_list):
pm.parentConstraint(fk_con, fk_jnt, maintainOffset=True)
# IK FK SWITCH SETUP
switch_obj = None
if not switch_con:
switch_obj = pm.circle(name="ik_fk_switch_ctrl", normal=[1, 0, 0])[0]
switch_obj.addAttr("FK_IK_Switch", attributeType="float", minValue=0, maxValue=1, defaultValue=0, keyable=True)
else:
switch_obj = switch_con
print ("Weee")
if not switch_obj.hasAttr('FK_IK_Switch'):
print ("Waaa")
switch_obj.addAttr("FK_IK_Switch", attributeType="float", minValue=0, maxValue=1, defaultValue=0, keyable=True)
rev_node = None
for main_jnt, fk_jnt, ik_jnt in zip(main_chain, fk_chain, ik_chain):
orient_constr = pm.orientConstraint(fk_jnt, ik_jnt, main_jnt)
pm.connectAttr(switch_obj.FK_IK_Switch, orient_constr.attr(ik_jnt.nodeName() + "W1"))
rev_node = pm.createNode("reverse", name=main_jnt.nodeName() + "_ikFkRev")
pm.connectAttr(switch_obj.FK_IK_Switch, rev_node + ".inputX")
pm.connectAttr(rev_node + ".outputX", orient_constr.attr(fk_jnt.nodeName() + "W0"))
pm.connectAttr(switch_obj.FK_IK_Switch, ik_con.visibility)
pm.connectAttr(switch_obj.FK_IK_Switch, ik_pole_con.visibility)
pm.connectAttr(rev_node + ".outputX", fk_con_list[0].visibility)
pm.connectAttr(rev_node + ".outputX", fk_con_list[1].visibility)
pm.connectAttr(rev_node + ".outputX", fk_con_list[2].visibility)
# CLEAN UP
obj = ik_pole_con
attributes = ['rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ']
for attr in attributes:
obj.attr(attr).set(lock=True, keyable=False)
obj = switch_con
attributes = ['translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ']
for attr in attributes:
obj.attr(attr).set(lock=True, keyable=False)
parent = pm.listRelatives(switch_con, parent=True)
pm.parentConstraint(main_chain[2], parent, maintainOffset=True)
if __name__ == "__main__":
#main_joints = create_joint_chain()
main_joints = [pm.PyNode('hip_L_jnt'), pm.PyNode('knee_L_jnt'), pm.PyNode('ankle_L_jnt')]
fk_joints = duplicate_joint_chain(main_joints, "FK_")
ik_joints = duplicate_joint_chain(main_joints, "IK_")
ik_con = pm.PyNode('foot_IK_L_con')
ik_pole_con = pm.PyNode('leg_pole_IK_L_con')
fk_con_list = [pm.PyNode('hip_FK_L_con'), pm.PyNode('knee_FK_L_con'), pm.PyNode('ankle_FK_L_con')]
switch_con = pm.PyNode('leg_IKFK_L_switch_con')
setup_ik_fk_switch(main_joints, fk_joints, ik_joints, ik_con, ik_pole_con, fk_con_list, switch_con)
main_joints = [pm.PyNode('hip_R_jnt'), pm.PyNode('knee_R_jnt'), pm.PyNode('ankle_R_jnt')]
fk_joints = duplicate_joint_chain(main_joints, "FK_")
ik_joints = duplicate_joint_chain(main_joints, "IK_")
ik_con = pm.PyNode('foot_IK_R_con')
ik_pole_con = pm.PyNode('leg_pole_IK_R_con')
fk_con_list = [pm.PyNode('hip_FK_R_con'), pm.PyNode('knee_FK_R_con'), pm.PyNode('ankle_FK_R_con')]
switch_con = pm.PyNode('leg_IKFK_R_switch_con')
setup_ik_fk_switch(main_joints, fk_joints, ik_joints, ik_con, ik_pole_con, fk_con_list, switch_con)
main_joints = [pm.PyNode('shoulder_L_jnt'), pm.PyNode('elbow_L_jnt'), pm.PyNode('wrist_L_jnt')]
fk_joints = duplicate_joint_chain(main_joints, "FK_")
ik_joints = duplicate_joint_chain(main_joints, "IK_")
ik_con = pm.PyNode('hand_IK_L_con')
ik_pole_con = pm.PyNode('arm_pole_IK_L_con')
fk_con_list = [pm.PyNode('shoulder_FK_L_con'), pm.PyNode('elbow_FK_L_con'), pm.PyNode('wrist_FK_L_con')]
switch_con = pm.PyNode('arm_IKFK_L_switch_con')
setup_ik_fk_switch(main_joints, fk_joints, ik_joints, ik_con, ik_pole_con, fk_con_list, switch_con)
main_joints = [pm.PyNode('shoulder_R_jnt'), pm.PyNode('elbow_R_jnt'), pm.PyNode('wrist_R_jnt')]
fk_joints = duplicate_joint_chain(main_joints, "FK_")
ik_joints = duplicate_joint_chain(main_joints, "IK_")
ik_con = pm.PyNode('hand_IK_R_con')
ik_pole_con = pm.PyNode('arm_pole_IK_R_con')
fk_con_list = [pm.PyNode('shoulder_FK_R_con'), pm.PyNode('elbow_FK_R_con'), pm.PyNode('wrist_FK_R_con')]
switch_con = pm.PyNode('arm_IKFK_R_switch_con')
setup_ik_fk_switch(main_joints, fk_joints, ik_joints, ik_con, ik_pole_con, fk_con_list, switch_con)
# A
parent_a = pm.PyNode('shoulder_L_jnt')
parent_b = pm.PyNode('elbow_L_jnt')
['feather_A_00_L_con_grp', 'feather_B_00_L_con_grp','feather_C_00_L_con_grp']
parent_a = pm.PyNode('elbow_L_jnt')
parent_b = pm.PyNode('wrist_L_jnt')
['feather_D_00_L_con_grp', 'feather_E_00_L_con_grp','feather_F_00_L_con_grp', 'feather_G_00_L_con_grp', 'feather_H_00_L_con_grp']
def weighted_parent_child_constraint_MOD (parent_a, parent_b, children_list):
for i, (child, weight) in enumerate(children_list):
constraint = pm.parentConstraint(parent_a, parent_b, child, maintainOffset=True)
constraint.interpType.set(2)
constraintWeightAttrA = constraint.getWeightAliasList()[0]
constraintWeightAttrB = constraint.getWeightAliasList()[1]
weight_a = weight
weight_b = 1 - weight
constraintWeightAttrA.set(weight_a)
constraintWeightAttrB.set(weight_b)
parent_a = 'shoulder_L_jnt'
parent_b = 'elbow_L_jnt'
children_list = [
('feather_A_00_L_con_grp', 1.0),
('feather_B_00_L_con_grp', 0.5),
('feather_C_00_L_con_grp', 0.0),
]
weighted_parent_child_constraint_MOD (parent_a, parent_b, children_list)
parent_a = 'elbow_L_jnt'
parent_b = 'wrist_L_jnt'
children_list = [
('feather_D_00_L_con_grp', 1.0),
('feather_E_00_L_con_grp', 0.8),
('feather_F_00_L_con_grp', 0.7),
('feather_G_00_L_con_grp', 0.5),
('feather_H_00_L_con_grp', 0.0),
]
weighted_parent_child_constraint_MOD (parent_a, parent_b, children_list)
Base Ver
import maya.cmds as cmds
import pymel.core as pm
def create_joint_chain():
# Create the main joint chain
joints = []
joint_names = ["shoulder_jnt", "elbow_jnt", "hand_jnt"]
positions = [(0, 10, 0), (1, 5, 0), (0, 0, 0)]
for name, pos in zip(joint_names, positions):
jnt = pm.joint(name=name, position=pos)
joints.append(jnt)
pm.select(clear=True)
return joints
def duplicate_joint_chain(joint_chain, prefix):
new_joint_chain = pm.duplicate(joint_chain)
for joint in new_joint_chain:
new_name = prefix + joint.nodeName().split("1")[0]
pm.rename(joint, new_name)
return new_joint_chain
def setup_ik_fk_switch(main_chain, fk_chain, ik_chain):
# Create IK Handle for the IK chain
ik_handle, effector = pm.ikHandle(startJoint=ik_chain[0], endEffector=ik_chain[-1], solver="ikRPsolver", name="arm_ikHandle")
effector.rename(ik_chain[-1] + "_eff")
# Create a control for the IK handle
ik_control = pm.circle(name="ik_ctrl", normal=[0, 1, 0])[0]
pm.delete(pm.parentConstraint(ik_chain[-1], ik_control))
pm.parent(ik_handle, ik_control)
# Create FK controls
fk_controls = []
for fk_jnt in fk_chain:
fk_ctrl = pm.circle(name=fk_jnt.name().replace("_jnt", "_ctrl"), normal=[0, 1, 0])[0]
pm.delete(pm.parentConstraint(fk_jnt, fk_ctrl))
pm.parentConstraint(fk_ctrl, fk_jnt, maintainOffset=True)
fk_controls.append(fk_ctrl)
pm.parent(fk_controls[2], fk_controls[1])
pm.parent(fk_controls[1], fk_controls[0])
# Create IK/FK switch attribute
switch_ctrl = pm.circle(name="ik_fk_switch_ctrl", normal=[0, 1, 0])[0]
switch_ctrl.addAttr("IK_FK_Switch", attributeType="float", minValue=0, maxValue=1, defaultValue=0, keyable=True)
# Constrain the main joints to the FK and IK joints
for main_jnt, fk_jnt, ik_jnt in zip(main_chain, fk_chain, ik_chain):
orient_constr = pm.orientConstraint(fk_jnt, ik_jnt, main_jnt)
pm.connectAttr(switch_ctrl.IK_FK_Switch, orient_constr.attr(ik_jnt.nodeName() + "W1"))
rev_node = pm.createNode("reverse", name=main_jnt.nodeName() + "_ikFkRev")
pm.connectAttr(switch_ctrl.IK_FK_Switch, rev_node + ".inputX")
pm.connectAttr(rev_node + ".outputX", orient_constr.attr(fk_jnt.nodeName() + "W0"))
# # Organize in groups
# pm.group(main_chain[0], name="main_joints_grp")
# pm.group(fk_controls, name="fk_controls_grp")
# pm.group(ik_control, ik_chain[0], name="ik_controls_grp")
# pm.group(switch_ctrl, name="ik_fk_switch_grp")
if __name__ == "__main__":
main_joints = create_joint_chain()
fk_joints = duplicate_joint_chain(main_joints, "FK_")
#print (fk_joints[0].name())
ik_joints = duplicate_joint_chain(main_joints, "IK_")
#print (ik_joints[0].name())
setup_ik_fk_switch(main_joints, fk_joints, ik_joints)