def set_pose_bone_matrix_world(obj, bone_name, matrix) -> None: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] bone.matrix = obj.matrix_world.inverted() @ matrix exit_mode_if(entered, active, mode)
def sync_bone_positions(armature_old): armature_new = bpy.context.active_object # armature_new.matrix_world = armature_old.matrix_world active, mode = modes.enter_mode(armature_old, modes.MODE_EDIT) edit_bone_dict = get_edit_bone_data_dict(armature_old) print("edit bone data dict length: {0}".format(len(edit_bone_dict.keys()))) entered, active, mode = modes.enter_mode_if(modes.EDIT_MODE, armature_new) for bone in armature_new.data.edit_bones: bone_name = bone.name # print('Checking for bone {0}'.format(bone_name)) bone = get_edit_bone(bone_name) if not bone_name in edit_bone_dict: print("{0} not found".format(bone_name)) # for key in edit_bone_dict.keys(): # print('KEY: {0}'.format(key)) continue dict_values = edit_bone_dict[bone_name] bone.head = dict_values[0] bone.tail = dict_values[1] bone.roll = dict_values[2] bone.use_connect = dict_values[3] exit_mode_if(entered, active, mode)
def set_pose_bone_matrix_object(obj, bone_name, matrix) -> None: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] bone.matrix = matrix.copy() exit_mode_if(entered, active, mode)
def set_edit_bone_matrix_world(obj, bone_name, matrix) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] bone.matrix = matrix @ obj.matrix_world.inverted() exit_mode_if(entered, active, mode)
def reset_pose_bone_transform(obj, bone_name) -> None: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] bone.matrix = get_pose_bone_rest_matrix_object(obj, bone_name) exit_mode_if(entered, active, mode)
def set_edit_bone_matrix(obj, bone_name, matrix, bone_length=1.0) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] bone.matrix = matrix bone.length = bone_length exit_mode_if(entered, active, mode)
def set_local_tail(obj, bone_name, tail) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] bone.tail = tail exit_mode_if(entered, active, mode)
def get_pose_bone_matrix_object(obj, bone_name) -> Matrix: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] bone_matrix_obj = bone.matrix exit_mode_if(entered, active, mode) return bone_matrix_obj.copy()
def set_edit_bone_matrix_by_object(obj, bone_name, target_object, bone_length=1.0) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) set_edit_bone_matrix(obj, bone_name, target_object.matrix_local, bone_length) exit_mode_if(entered, active, mode)
def set_world_tail(obj, bone_name, tail) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] matrix = obj.matrix_world bone.tail = matrix.inverted() @ tail exit_mode_if(entered, active, mode)
def set_local_head_tail(obj, bone_name, head, tail, roll=0) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] bone.head = head bone.tail = tail bone.roll = roll exit_mode_if(entered, active, mode)
def remove_bone(obj, bone_name) -> None: if not bone_name in obj.data.bones: return entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] edit_bones.remove(bone) exit_mode_if(entered, active, mode)
def get_edit_bone_matrices(obj: Object) -> Dict[str, Matrix]: entered, active, mode = enter_mode_if(MODE_EDIT, obj) bone_matrices = {} for bone in obj.data.edit_bones: bone_matrices[bone.name] = bone.matrix.copy() exit_mode_if(entered, active, mode) return bone_matrices
def set_bone_parenting(obj, bone_name, parent_name, use_connect) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] if parent_name in edit_bones: bone.parent = edit_bones[parent_name] bone.use_connect = use_connect exit_mode_if(entered, active, mode)
def copy_local_head_tail(obj, bone_name, copy_bone_name) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] copy_bone = edit_bones[copy_bone_name] bone.head = copy_bone.head bone.tail = copy_bone.tail bone.roll = copy_bone.roll exit_mode_if(entered, active, mode)
def remove_bones(obj, bone_names) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) for bone_name in bone_names: if not bone_name in edit_bones: continue bone = edit_bones[bone_name] edit_bones.remove(bone) exit_mode_if(entered, active, mode)
def shift_bones(obj, matrix) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) for bone in edit_bones: if not bone.use_connect: bone.head = matrix @ bone.head bone.tail = matrix @ bone.tail exit_mode_if(entered, active, mode)
def get_pose_bone_matrices(obj: Object) -> Dict[str, Matrix]: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone_matrices = {} for bone in obj.pose.bones: bone_matrices[bone.name] = bone.matrix.copy() exit_mode_if(entered, active, mode) return bone_matrices
def get_pose_bone_matrix_world(obj, bone_name) -> Matrix: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] obj_matrix_world = obj.matrix_world bone_matrix_obj = bone.matrix bone_world_matrix = bone_matrix_obj @ obj_matrix_world exit_mode_if(entered, active, mode) return bone_world_matrix
def set_world_head_tail_xaxis(obj: Object, bone_name, head, tail, x_axis) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] matrix = obj.matrix_world bone.head = matrix.inverted() @ head bone.tail = matrix.inverted() @ tail align_bone_x_axis(bone, x_axis) exit_mode_if(entered, active, mode)
def remove_bones_startwith(obj, prefix) -> None: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) removing = [] for edit_bone in edit_bones: if edit_bone.name.startswith(prefix): removing.append(edit_bone) for edit_bone in removing: edit_bones.remove(edit_bone) exit_mode_if(entered, active, mode)
def get_world_head_tail( obj: Object, bone_name: str) -> Tuple[Matrix, Vector, Vector, Vector]: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) bone = edit_bones[bone_name] matrix = obj.matrix_world head = matrix @ bone.head tail = matrix @ bone.tail x_axis = matrix @ bone.x_axis exit_mode_if(entered, active, mode) return matrix, head, tail, x_axis
def create_or_get_bone(obj, bone_name) -> Bone: if bone_name in obj.data.bones: return obj.data.bones[bone_name] entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) ebone = edit_bones.new(bone_name) ebone.tail = Vector([0.0, 0.0, 1.0]) exit_mode_if(entered, active, mode) if "EDIT" not in bpy.context.mode: return obj.data.bones[bone_name] return ebone
def get_edit_bone_data_dict( obj: Object, ) -> Dict[str, Tuple[Vector, Vector, float, bool]]: entered, active, mode = enter_mode_if(MODE_EDIT, obj) edit_bones = get_edit_bones(obj) edit_bone_dict = {} for bone in edit_bones: edit_bone_dict[bone.name] = ( bone.head.copy(), bone.tail.copy(), bone.roll, bone.use_connect, ) exit_mode_if(entered, active, mode) return edit_bone_dict
def reset_pose_bone_rotation(obj, bone_name) -> None: entered, active, mode = enter_mode_if(MODE_POSE, obj) bone = obj.pose.bones[bone_name] rest_matrix = get_pose_bone_rest_matrix_object(obj, bone_name) current_matrix = bone.matrix _, rr, _ = rest_matrix.decompose() cl, cr, cs = current_matrix.decompose() ml = Matrix.Translation(cl) mr = rr.to_matrix().to_4x4() msc = Matrix.Diagonal(cs).to_4x4() ms = ml @ mr @ msc bone.matrix = ms exit_mode_if(entered, active, mode)
def create_root_motion_setup(context, armature): scene = context.scene sc = scene.collection orig_entered, orig_active, orig_mode = modes.enter_mode_if( modes.MODE_OBJECT, armature) to_rest_position(armature) settings = armature.data.root_motion_settings rmc = get_or_create_collection(context, "Root Motion", sc) rm_ac = get_or_create_collection(context, "1_Root Adjustment", rmc) rm_sc = get_or_create_collection(context, "2_Settings", rmc) rm_rc = get_or_create_collection(context, "3_Root", rmc) rm_pc = get_or_create_collection(context, "4_Pelvis", rmc) dt = EMPTY.DISPLAY_TYPE new = get_or_create_empty c = context _00_basis = new(c, "_00_basis", None, rm_ac, 0.10, dt.PLAIN_AXES) _01_current = new(c, "_01_current", None, rm_ac, 0.11, dt.PLAIN_AXES) _02_tracking = new(c, "_02_tracking", None, rm_ac, 0.13, dt.ARROWS) _03_offset = new(c, "_03_offset", None, rm_ac, 0.15, dt.ARROWS) _05_common_adjustment = new(c, "_05_common_adjustment", None, rm_ac, 0.18, dt.ARROWS) _10_start = new(c, "_10_start", None, rm_ac, 0.21, dt.ARROWS) _21_baked_rot = new(c, "_21_baked_rot", None, rm_sc, 0.25, dt.ARROWS) _22_baked_loc = new(c, "_22_baked_loc", None, rm_sc, 0.29, dt.ARROWS) _28_aggregate_loc = new(c, "_28_aggregate_loc", None, rm_sc, 0.34, dt.ARROWS) _29_aggregate = new(c, "_29_aggregate", None, rm_sc, 0.39, dt.ARROWS) _80_root_adjustment_rot = new(c, "_80_root_adjustment_rot", None, rm_rc, 0.45, dt.ARROWS) _81_root_adjustment_loc = new(c, "_81_root_adjustment_loc", None, rm_rc, 0.51, dt.ARROWS) _89_rootmotion_final = new(c, "_89_rootmotion_final", None, rm_rc, 0.57, dt.ARROWS) _01_pose = new(c, "_01_pose", None, rm_pc, 0.20, dt.SPHERE) _82_hip_adjustment_rot = new(c, "_82_hip_adjustment_rot", None, rm_pc, 0.40, dt.SPHERE) _83_hip_adjustment_loc = new(c, "_83_hip_adjustment_loc", None, rm_pc, 0.45, dt.SPHERE) _99_hips_final = new(c, "_99_hips_final", None, rm_pc, 0.10, dt.SPHERE) Hips = new(c, "Hips", None, rmc, 0.25, dt.CUBE) RootMotion = new(c, "RootMotion", None, rmc, 1.00, dt.ARROWS) if settings.root_bone_name == "": settings.root_bone_name = "Root" if settings.hip_bone_name == "": settings.hip_bone_name = "Hips" settings.root_node = _02_tracking settings.root_bone_offset = _89_rootmotion_final settings.hip_bone_offset = _99_hips_final settings.root_final = RootMotion objs = [ _00_basis, _01_current, _02_tracking, _03_offset, _05_common_adjustment, _10_start, _22_baked_loc, _21_baked_rot, _28_aggregate_loc, _29_aggregate, _80_root_adjustment_rot, _81_root_adjustment_loc, _89_rootmotion_final, _01_pose, _82_hip_adjustment_rot, _83_hip_adjustment_loc, _99_hips_final, Hips, RootMotion, ] for obj in objs: obj.matrix_world = Matrix.Identity(4) _00_basis.matrix_world = get_pose_bone_rest_matrix_world( armature, settings.original_root_bone) add_copy_transform_constraint(_01_current, "Copy Transforms", armature, settings.original_root_bone) add_copy_transform_constraint(_02_tracking, "Copy Transforms", _00_basis, None) add_child_of_constraint(_02_tracking, "Child Of", _01_current) add_driver( _03_offset, "location", 0, DRIVER.TYPE.SCRIPTED, armature, "root_motion_x_offset", "offset", "-offset", ) add_driver( _03_offset, "location", 1, DRIVER.TYPE.SCRIPTED, armature, "root_motion_y_offset", "offset", "-offset", ) add_driver( _03_offset, "location", 2, DRIVER.TYPE.SCRIPTED, armature, "root_motion_z_offset", "offset", "-offset", ) add_driver( _03_offset, "rotation_euler", 2, DRIVER.TYPE.SCRIPTED, armature, "root_motion_rot_offset", "offset", "offset * 0.0174533", ) add_driver( _05_common_adjustment, "location", 0, DRIVER.TYPE.AVERAGE, armature, "root_node_start_location_0", "v", "", ) add_driver( _05_common_adjustment, "location", 1, DRIVER.TYPE.AVERAGE, armature, "root_node_start_location_1", "v", "", ) add_driver( _05_common_adjustment, "location", 2, DRIVER.TYPE.AVERAGE, armature, "root_node_start_location_2", "v", "", ) add_driver( _05_common_adjustment, "rotation_euler", 0, DRIVER.TYPE.AVERAGE, armature, "root_node_start_rotation_0", "v", "", ) add_driver( _05_common_adjustment, "rotation_euler", 1, DRIVER.TYPE.AVERAGE, armature, "root_node_start_rotation_1", "v", "", ) add_driver( _05_common_adjustment, "rotation_euler", 2, DRIVER.TYPE.AVERAGE, armature, "root_node_start_rotation_2", "v", "", ) add_copy_transform_constraint(_10_start, "Copy Transforms", _02_tracking, None) add_copy_location_constraint(_10_start, "Copy Location", _05_common_adjustment, use_offset=True) add_copy_rotation_constraint(_10_start, "Copy Rotation", _05_common_adjustment, mix_mode=MIX_MODE.AFTER) add_copy_location_constraint( _22_baked_loc, "_rm_x_bake_into", _10_start, use_offset=False, use_x=True, use_y=False, use_z=False, ) add_copy_location_constraint( _22_baked_loc, "_rm_y_bake_into", _10_start, use_offset=False, use_x=False, use_y=True, use_z=False, ) add_copy_location_constraint( _22_baked_loc, "_rm_z_bake_into", _10_start, use_offset=False, use_x=False, use_y=False, use_z=True, ) add_driver( _22_baked_loc, 'constraints["_rm_x_bake_into"].influence', -1, DRIVER.TYPE.SCRIPTED, armature, "root_motion_x_bake_into", "v", "1.0-v", ) add_driver( _22_baked_loc, 'constraints["_rm_y_bake_into"].influence', -1, DRIVER.TYPE.SCRIPTED, armature, "root_motion_y_bake_into", "v", "1.0-v", ) add_driver( _22_baked_loc, 'constraints["_rm_z_bake_into"].influence', -1, DRIVER.TYPE.SCRIPTED, armature, "root_motion_z_bake_into", "v", "1.0-v", ) add_copy_rotation_constraint(_21_baked_rot, "_05_rot_bake_into", _10_start, use_x=False, use_y=False) add_driver( _21_baked_rot, 'constraints["_05_rot_bake_into"].influence', -1, DRIVER.TYPE.SCRIPTED, armature, "root_motion_rot_bake_into", "v", "1.0-v", ) add_child_of_constraint(_28_aggregate_loc, "Child Of", _21_baked_rot) add_copy_location_constraint(_28_aggregate_loc, _22_baked_loc.name, _22_baked_loc, use_offset=False) add_copy_transform_constraint(_29_aggregate, "Copy Transforms", _28_aggregate_loc, None) offset_params = [ (_80_root_adjustment_rot, "root", "rotation_euler", "rotation", None), ( _81_root_adjustment_loc, "root", "location", "location", _80_root_adjustment_rot, ), (_82_hip_adjustment_rot, "hip", "rotation_euler", "rotation", None), (_83_hip_adjustment_loc, "hip", "location", "location", _82_hip_adjustment_rot), ] for offset_param in offset_params: target = offset_param[0] bone_name = offset_param[1] data_path = offset_param[2] var_token = offset_param[3] childof = offset_param[4] for i in range(3): full_key = "{0}_bone_offset_{1}_{2}".format( bone_name, var_token, i) add_driver( target, data_path, i, DRIVER.TYPE.AVERAGE, armature, full_key, "v", "1.0-v", ) if childof: add_child_of_constraint(target, "Child Of", childof) add_copy_transform_constraint(_89_rootmotion_final, "Copy Transforms", _29_aggregate, None) add_child_of_constraint(_89_rootmotion_final, "Child Of", _81_root_adjustment_loc) add_limit_loc_constraint(_89_rootmotion_final, "Limit Location") t = _89_rootmotion_final base = 'constraints["Limit Location"]' for axis in ["x", "y", "z"]: for mm in ["min", "max"]: mm_axis = "{0}_{1}".format(mm, axis) path_a = "{0}.use_{1}".format(base, mm_axis) path_b = "{0}.{1}".format(base, mm_axis) trgt_a = "root_motion_{0}_limit_{1}".format( axis, "neg" if mm == "min" else "pos") trgt_b = trgt_a + "_val" add_driver(t, path_a, -1, DRIVER.TYPE.AVERAGE, armature, trgt_a, "v", "") add_driver(t, path_b, -1, DRIVER.TYPE.AVERAGE, armature, trgt_b, "v", "") add_copy_transform_constraint(_01_pose, "Copy Transforms", _01_current, None, mix_mode=MIX_MODE.AFTER) add_copy_transform_constraint(_99_hips_final, "Copy Transforms", _01_pose, None) add_child_of_constraint(_99_hips_final, "Child Of", _83_hip_adjustment_loc) add_copy_transform_constraint(Hips, "Copy Transforms", _99_hips_final, None) add_copy_transform_constraint(RootMotion, "Copy Transforms", _89_rootmotion_final, None) add_copy_location_constraint(RootMotion, "Copy Location", _03_offset, use_offset=True) add_copy_rotation_constraint(RootMotion, "Copy Rotation", _03_offset, mix_mode=MIX_MODE.AFTER, invert_z=True) if settings.original_root_bone == settings.root_bone_name: print("Bone name collision! [{0}]".format(settings.root_bone_name)) settings.root_bone_name = "{0}_NEW".format(settings.root_bone_name) if settings.original_root_bone == settings.hip_bone_name: print("Bone name collision! [{0}]".format(settings.hip_bone_name)) settings.hip_bone_name = "{0}_NEW".format(settings.hip_bone_name) entered, active, mode = modes.enter_mode_if(modes.MODE_EDIT, armature) root_edit_bone = bones.create_or_get_bone(armature, settings.root_bone_name) hip_edit_bone = bones.create_or_get_bone(armature, settings.hip_bone_name) original_root_bone = bones.create_or_get_bone(armature, settings.original_root_bone) try: hip_edit_bone.parent = root_edit_bone except AttributeError: pass bones.set_local_head_tail(armature, settings.root_bone_name, Vector([0, 0, 0]), Vector([0, 0.5, 0]), 0) bones.copy_local_head_tail(armature, settings.hip_bone_name, settings.original_root_bone) for child in original_root_bone.children: bones.set_bone_parenting(armature, child.name, settings.hip_bone_name, False) modes.exit_mode_if(entered, active, mode) entered, active, mode = modes.enter_mode_if(modes.MODE_POSE, armature) root_bone = armature.pose.bones[settings.root_bone_name] c = root_bone.constraints.get("Copy Transforms") if not c: c = root_bone.constraints.new("COPY_TRANSFORMS") c.name = "Copy Transforms" c.target = RootMotion hip_bone = armature.pose.bones[settings.hip_bone_name] c = hip_bone.constraints.get("Copy Transforms") if not c: c = hip_bone.constraints.new("COPY_TRANSFORMS") c.name = "Copy Transforms" c.target = Hips modes.exit_mode_if(entered, active, mode) to_pose_position(armature) for mesh in [obj for obj in bpy.data.objects if obj.type == "MESH"]: for vg in mesh.vertex_groups: if vg.name == settings.original_root_bone: vg.name = settings.hip_bone_name to_rest_position(armature) refresh_child_of_matrices(armature) refresh_child_of_matrices(armature) refresh_child_of_matrices(armature) to_pose_position(armature) rm_ac.hide_viewport = True rm_sc.hide_viewport = True rm_rc.hide_viewport = True rm_pc.hide_viewport = True