def fix_toe_roll(): """ The Toe controller bone may have a bad automated roll, so recalculate it """ mode = Get.mode(rig) Set.mode(bpy.context, 'EDIT', rig) bones = rig.data.edit_bones ebones = bpy.context.selected_bones for ebone in ebones: ebone.select = False bone = tweak = None def get(name): nonlocal bone, tweak bone = bones.get(name) tweak = bones.get(name.replace('_master', '')) return (bone and tweak) def roll(name): if get(name): bone.select = True bones.active = tweak bpy.ops.armature.calculate_roll(type='ACTIVE') bone.select = False for lr in ('L', 'R'): for ind in range(1, 6): roll(f'toe{ind}.01_master.{lr}') roll(f'thumb.01_master.{lr}') roll(f'f_index.01_master.{lr}') roll(f'f_middle.01_master.{lr}') roll(f'f_ring.01_master.{lr}') roll(f'f_pinky.01_master.{lr}') for ebone in ebones: ebone.select = True Set.mode(bpy.context, mode, rig)
def fix_poles(): def op(**args): eval('bpy.ops.pose.rigify_limb_toggle_pole_' + rig.data["rig_id"])( dict(active_object=rig), 'INVOKE_DEFAULT', **args) poles = dict() def getmat(bone, active): """Helper function for visual transform copy, gets the active transform in bone space """ obj_bone = bone.id_data obj_active = active.id_data data_bone = obj_bone.data.bones[bone.name] # all matrices are in armature space unless commented otherwise active_to_selected = obj_bone.matrix_world.inverted( ) @ obj_active.matrix_world active_matrix = active_to_selected @ active.matrix otherloc = active_matrix # final 4x4 mat of target, location. bonemat_local = data_bone.matrix_local.copy() # self rest matrix if data_bone.parent: parentposemat = obj_bone.pose.bones[ data_bone.parent.name].matrix.copy() parentbonemat = data_bone.parent.matrix_local.copy() else: parentposemat = parentbonemat = Matrix() if parentbonemat == parentposemat or not data_bone.use_inherit_rotation: newmat = bonemat_local.inverted() @ otherloc else: bonemat = parentbonemat.inverted() @ bonemat_local newmat = bonemat.inverted() @ parentposemat.inverted( ) @ otherloc return newmat def rotcopy(item, mat): """Copy rotation to item from matrix mat depending on item.rotation_mode""" if item.rotation_mode == 'QUATERNION': item.rotation_quaternion = mat.to_3x3().to_quaternion() elif item.rotation_mode == 'AXIS_ANGLE': rot = mat.to_3x3().to_quaternion().to_axis_angle( ) # returns (Vector((x, y, z)), w) axis_angle = rot[1], rot[0][0], rot[0][1], rot[0][ 2] # convert to w, x, y, z item.rotation_axis_angle = axis_angle else: item.rotation_euler = mat.to_3x3().to_euler(item.rotation_mode) def get_pole(pole, line): from math import radians from mathutils import Matrix bone["pole_vector"] = 0 pole = get(pole) line = get(line) # lock rotation/scale, since bone only suppose to be moved pole.rotation_mode = 'XYZ' pole.lock_rotation_w = True pole.lock_rotation = (True, True, True) pole.lock_scale = (True, True, True) utils.update(bpy.context) mat = getmat(pole, line) @ Matrix.Rotation(radians(180), 4, 'X') rotcopy(pole, mat) utils.update(bpy.context) poles[pole.name] = Get.matrix(pole) rotcopy(pole, Matrix()) pole.location = (0, 0, 0) if get('thigh_parent.L'): op(prop_bone="thigh_parent.L", ik_bones= "[\"thigh_ik.L\", \"MCH-shin_ik.L\", \"MCH-thigh_ik_target.L\"]", ctrl_bones= "[\"thigh_ik.L\", \"foot_ik.L\", \"thigh_ik_target.L\"]", extra_ctrls= "[\"foot_ik_pivot.L\", \"foot_heel_ik.L\", \"foot_spin_ik.L\"]") get_pole('thigh_ik_target.L', 'VIS_thigh_ik_pole.L') if get('thigh_parent.R'): op(prop_bone="thigh_parent.R", ik_bones= "[\"thigh_ik.R\", \"MCH-shin_ik.R\", \"MCH-thigh_ik_target.R\"]", ctrl_bones= "[\"thigh_ik.R\", \"foot_ik.R\", \"thigh_ik_target.R\"]", extra_ctrls= "[\"foot_ik_pivot.R\", \"foot_heel_ik.R\", \"foot_spin_ik.R\"]") get_pole('thigh_ik_target.R', 'VIS_thigh_ik_pole.R') if get('upper_arm_parent.L'): op(prop_bone="upper_arm_parent.L", ik_bones= "[\"upper_arm_ik.L\", \"MCH-forearm_ik.L\", \"MCH-upper_arm_ik_target.L\"]", ctrl_bones= "[\"upper_arm_ik.L\", \"hand_ik.L\", \"upper_arm_ik_target.L\"]", extra_ctrls="[\"hand_ik_pivot.L\", \"hand_ik_wrist.L\"]") get_pole('upper_arm_ik_target.L', 'VIS_upper_arm_ik_pole.L') if get('upper_arm_parent.R'): op(prop_bone="upper_arm_parent.R", ik_bones= "[\"upper_arm_ik.R\", \"MCH-forearm_ik.R\", \"MCH-upper_arm_ik_target.R\"]", ctrl_bones= "[\"upper_arm_ik.R\", \"hand_ik.R\", \"upper_arm_ik_target.R\"]", extra_ctrls="[\"hand_ik_pivot.R\", \"hand_ik_wrist.R\"]") get_pole('upper_arm_ik_target.R', 'VIS_upper_arm_ik_pole.R') if poles: utils.update(bpy.context) mode = Get.mode(rig) Set.mode(bpy.context, 'EDIT', rig) for (name, mat) in poles.items(): edit_bone = rig.data.edit_bones[name] Set.matrix(edit_bone, mat) Set.mode(bpy.context, mode, rig)