def execute(self, context): scene = context.scene if not ObjectService.object_is_basemesh(context.active_object): self.report({'ERROR'}, "Rigs can only be added to the base mesh") return {'FINISHED'} basemesh = context.active_object from mpfb.ui.addrig.addrigpanel import ADD_RIG_PROPERTIES # pylint: disable=C0415 import_weights = ADD_RIG_PROPERTIES.get_value("import_weights", entity_reference=scene) standard_rig = ADD_RIG_PROPERTIES.get_value("standard_rig", entity_reference=scene) rigs_dir = LocationService.get_mpfb_data("rigs") standard_dir = os.path.join(rigs_dir, "standard") rig_file = os.path.join(standard_dir, "rig." + standard_rig + ".json") rig = Rig.from_json_file_and_basemesh(rig_file, basemesh) armature_object = rig.create_armature_and_fit_to_basemesh() basemesh.parent = armature_object if import_weights: weights_file = os.path.join(standard_dir, "weights." + standard_rig + ".json") weights = dict() with open(weights_file, 'r') as json_file: weights = json.load(json_file) RigService.apply_weights(armature_object, basemesh, weights) self.report({'INFO'}, "A rig was added") return {'FINISHED'}
def _sided_rotation_locks(self, finger_number, armature_object): bpy.ops.object.mode_set(mode='POSE', toggle=False) for segment_number in [1, 2, 3]: locks = {} if finger_number == 1: if segment_number == 1: locks = _ROTATION_LOCKS["thumb_first_segment"] else: locks = _ROTATION_LOCKS["thumb_following_segments"] else: if segment_number == 1: locks = _ROTATION_LOCKS["thumb_first_segment"] else: locks = _ROTATION_LOCKS["thumb_following_segments"] x = "X" in locks and locks["X"] y = "Y" in locks and locks["Y"] z = "Z" in locks and locks["Z"] name = self._sided("finger" + str(finger_number) + "-" + str(segment_number)) RigService.add_ik_rotation_lock_to_pose_bone(name, armature_object, lock_x=x, lock_y=y, lock_z=z)
def _create_knee_ik_bone(self, armature_object): _LOG.enter() bpy.ops.object.mode_set(mode='EDIT', toggle=False) bones = armature_object.data.edit_bones bone = bones.new(self.which_leg + "_knee_ik") bone.head = self._bone_info["pose_bones"][ self.get_upper_leg_name()]["head"] bone.tail = self._bone_info["pose_bones"][ self.get_upper_leg_name()]["tail"] length = bone.tail - bone.head bone.tail = bone.tail + length / 5 bone.head = bone.head + length bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='POSE', toggle=False) RigService.display_pose_bone_as_empty(armature_object, self.which_leg + "_knee_ik", empty_type="SPHERE") pose_bone = RigService.find_pose_bone_by_name( self.which_leg + "_knee_ik", armature_object) for i in range(3): pose_bone.lock_scale[i] = True
def _create_point_ik_bone(self, finger_number, armature_object): _LOG.enter() bpy.ops.object.mode_set(mode='EDIT', toggle=False) tip_name = self.get_last_segment_name_of_finger(finger_number) head = self._bone_info["pose_bones"][tip_name]["head"] tail = self._bone_info["pose_bones"][tip_name]["tail"] roll = self._bone_info["edit_bones"][tip_name]["roll"] length = tail - head tail = tail + length head = head + length bone_name = self._get_point_ik_bone_name_for_finger(finger_number) bones = armature_object.data.edit_bones bone = bones.new(bone_name) bone.head = head bone.tail = tail bone.roll = roll # Needed to save bone bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='POSE', toggle=False) RigService.display_pose_bone_as_empty(armature_object, bone_name, empty_type="SPHERE") pose_bone = RigService.find_pose_bone_by_name(bone_name, armature_object) scales = [0.5, 0.5, 0.5, 0.5, 0.7] pose_bone.custom_shape_scale = scales[finger_number - 1] _LOG.debug("scale", pose_bone.custom_shape_scale)
def _apply_individual_grip(self, armature_object): _LOG.enter() for finger_number in [1, 2, 3, 4, 5]: self._create_grip_bone(finger_number, armature_object) grip_name = self._get_grip_bone_name_for_finger(finger_number) bpy.ops.object.mode_set(mode='EDIT', toggle=False) parent_name = self.get_immediate_parent_name_of_finger(finger_number) parent_bone = RigService.find_edit_bone_by_name(parent_name, armature_object) grip_bone = RigService.find_edit_bone_by_name(grip_name, armature_object) grip_bone.parent = parent_bone bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='POSE', toggle=False) finger_segments = self.get_reverse_list_of_bones_in_finger(finger_number) for bone_name in finger_segments: constraint = RigService.add_copy_rotation_constraint_to_pose_bone(bone_name, grip_name, armature_object, copy_y=False, copy_z=False) constraint.influence = 1.0 / len(finger_segments) bone_name = finger_segments[-1] constraint = RigService.add_copy_rotation_constraint_to_pose_bone(bone_name, grip_name, armature_object, copy_x=False) if self.settings["hide_fk"]: self._hide_bones(armature_object, finger_segments)
def _set_shoulder_ik_target(self, armature_object, chain_length): _LOG.enter() bpy.ops.object.mode_set(mode='POSE', toggle=False) shoulder_name = self.get_shoulder_name() shoulder_ik_name = self.which_arm + "_shoulder_ik" shoulder_bone = RigService.find_pose_bone_by_name(shoulder_ik_name, armature_object) self.add_shoulder_rotation_constraints(armature_object) RigService.add_ik_constraint_to_pose_bone(shoulder_name, armature_object, shoulder_bone, chain_length)
def _set_finger_ik_target(self, finger_number, armature_object, chain_length): _LOG.enter() bpy.ops.object.mode_set(mode='POSE', toggle=False) tip_name = self.get_last_segment_name_of_finger(finger_number) ik_name = self._get_point_ik_bone_name_for_finger(finger_number) ik_bone = RigService.find_pose_bone_by_name(ik_name, armature_object) self.add_finger_rotation_constraints(finger_number, armature_object) RigService.add_ik_constraint_to_pose_bone(tip_name, armature_object, ik_bone, chain_length)
def _set_upper_arm_ik_target(self, armature_object, chain_length): _LOG.enter() bpy.ops.object.mode_set(mode='POSE', toggle=False) upper_arm_name = self.get_upper_arm_name() elbow_name = self.which_arm + "_elbow_ik" elbow_bone = RigService.find_pose_bone_by_name(elbow_name, armature_object) self.add_upper_arm_rotation_constraints(armature_object) RigService.add_ik_constraint_to_pose_bone(upper_arm_name, armature_object, elbow_bone, chain_length)
def _set_hip_ik_target(self, armature_object, chain_length): _LOG.enter() bpy.ops.object.mode_set(mode='POSE', toggle=False) hip_name = self.get_hip_name() hip_ik_name = self.which_leg + "_hip_ik" hip_bone = RigService.find_pose_bone_by_name(hip_ik_name, armature_object) self.add_hip_rotation_constraints(armature_object) RigService.add_ik_constraint_to_pose_bone(hip_name, armature_object, hip_bone, chain_length)
def _set_lower_leg_ik_target(self, armature_object, chain_length): _LOG.enter() bpy.ops.object.mode_set(mode='POSE', toggle=False) lower_leg_name = self.get_lower_leg_name() foot_name = self.which_leg + "_foot_ik" foot_bone = RigService.find_pose_bone_by_name(foot_name, armature_object) self.add_lower_leg_rotation_constraints(armature_object) RigService.add_ik_constraint_to_pose_bone(lower_leg_name, armature_object, foot_bone, chain_length)
def _sided_rotation_limit(self, unsided_name, armature_object): bpy.ops.object.mode_set(mode='POSE', toggle=False) if unsided_name in _ROTATION_LIMITS: for axis_name in _ROTATION_LIMITS[unsided_name].keys(): name = self._sided(unsided_name) limits = _ROTATION_LIMITS[unsided_name][axis_name] RigService.set_ik_rotation_limits(name, armature_object, axis=axis_name, min_angle=limits[0], max_angle=limits[1])
def _set_parent(self, armature_object, has_elbow_ik=False, has_shoulder_ik=False): _LOG.enter() bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='EDIT', toggle=False) if not "arm_parenting_strategy" in self.settings: return strategy = self.settings["arm_parenting_strategy"] if not strategy or strategy == "NONE": return hand_ik = RigService.find_edit_bone_by_name(self.which_arm + "_hand_ik", armature_object) elbow_ik = None shoulder_ik = None if has_elbow_ik: elbow_ik = RigService.find_edit_bone_by_name(self.which_arm + "_elbow_ik", armature_object) if has_shoulder_ik: shoulder_ik = RigService.find_edit_bone_by_name(self.which_arm + "_shoulder_ik", armature_object) if strategy == "ROOT": root_bone = RigService.find_edit_bone_by_name(self.get_root(), armature_object) hand_ik.parent = root_bone if elbow_ik: elbow_ik.parent = root_bone if shoulder_ik: shoulder_ik.parent = root_bone if strategy == "SPINE": spine_bone = RigService.find_edit_bone_by_name(self.get_shoulders_immediate_parent(), armature_object) hand_ik.parent = spine_bone if elbow_ik: elbow_ik.parent = spine_bone if shoulder_ik: shoulder_ik.parent = spine_bone if strategy == "OUTER": if elbow_ik: elbow_ik.parent = hand_ik if shoulder_ik: shoulder_ik.parent = elbow_ik if strategy == "INNER": if elbow_ik: hand_ik.parent = elbow_ik if shoulder_ik: elbow_ik.parent = shoulder_ik bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
def _sided_rotation_lock(self, unsided_name, armature_object): bpy.ops.object.mode_set(mode='POSE', toggle=False) if unsided_name in _ROTATION_LOCKS: locks = _ROTATION_LOCKS[unsided_name] x = "X" in locks and _ROTATION_LOCKS[unsided_name]["X"] y = "Y" in locks and _ROTATION_LOCKS[unsided_name]["Y"] z = "Z" in locks and _ROTATION_LOCKS[unsided_name]["Z"] name = self._sided(unsided_name) RigService.add_ik_rotation_lock_to_pose_bone(name, armature_object, lock_x=x, lock_y=y, lock_z=z)
def _set_parent(self, armature_object, has_knee_ik=False, has_hip_ik=False): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='EDIT', toggle=False) if not "leg_parenting_strategy" in self.settings: return strategy = self.settings["leg_parenting_strategy"] if not strategy or strategy == "NONE": return foot_ik = RigService.find_edit_bone_by_name( self.which_leg + "_foot_ik", armature_object) knee_ik = None hip_ik = None if has_knee_ik: knee_ik = RigService.find_edit_bone_by_name( self.which_leg + "_knee_ik", armature_object) if has_hip_ik: hip_ik = RigService.find_edit_bone_by_name( self.which_leg + "_hip_ik", armature_object) if strategy == "ROOT": root_bone = RigService.find_edit_bone_by_name( self.get_root(), armature_object) foot_ik.parent = root_bone if knee_ik: knee_ik.parent = root_bone if hip_ik: hip_ik.parent = root_bone if strategy == "OUTER": if knee_ik: knee_ik.parent = foot_ik if hip_ik: hip_ik.parent = knee_ik if strategy == "INNER": if knee_ik: foot_ik.parent = knee_ik if hip_ik: knee_ik.parent = hip_ik bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
def _apply_master_without_individual_for_finger(self, armature_object, finger_number): master_name = self._get_master_grip_bone_name() finger_segments = self.get_reverse_list_of_bones_in_finger(finger_number) for bone_name in finger_segments: constraint = RigService.add_copy_rotation_constraint_to_pose_bone(bone_name, master_name, armature_object, copy_y=False, copy_z=False) constraint.influence = 1.0 / len(finger_segments) bone_name = finger_segments[-1] constraint = RigService.add_copy_rotation_constraint_to_pose_bone(bone_name, master_name, armature_object, copy_x=False) if self.settings["hide_fk"]: self._hide_bones(armature_object, finger_segments)
def execute(self, context): _LOG.enter() _LOG.debug("click") blender_object = context.active_object bpy.ops.object.mode_set(mode='EDIT', toggle=False) ball_r = RigService.find_edit_bone_by_name("ball_r", blender_object) bpy.ops.object.mode_set(mode='OBJECT', toggle=False) if not ball_r: self.report( {'ERROR'}, "Only the \"Game engine\" skeleton is supported so far") return {'FINISHED'} bpy.ops.object.transform_apply(location=True, scale=False, rotation=False) from mpfb.ui.rigify.rigifypanel import RIGIFY_PROPERTIES settings = RIGIFY_PROPERTIES.as_dict(entity_reference=context.scene) helpers = RigifyHelpers.get_instance(settings) helpers.convert_to_rigify(blender_object) self.report({'INFO'}, "Converted to rigify") return {'FINISHED'}
def _apply_master_with_individual_for_finger(self, armature_object, finger_number): master_name = self._get_master_grip_bone_name() bone_name = self._get_grip_bone_name_for_finger(finger_number) constraint = RigService.add_copy_rotation_constraint_to_pose_bone(bone_name, master_name, armature_object) constraint.name = 'Add rotation' constraint.mix_mode = 'ADD'
def execute(self, context): _LOG.enter() if context.object is None or context.object.type != 'ARMATURE': self.report({'ERROR'}, "Must have armature as active object") return {'FINISHED'} armature_object = context.object basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives( armature_object, mpfb_type_name="Basemesh") if basemesh is None: self.report({ 'ERROR' }, "Could not find related basemesh. It should have been parent or child of armature object." ) return {'FINISHED'} absolute_file_path = bpy.path.abspath(self.filepath) _LOG.debug("absolute_file_path", absolute_file_path) weights = RigService.get_weights(armature_object, basemesh) with open(absolute_file_path, "w") as json_file: json.dump(weights, json_file, indent=4, sort_keys=True) self.report({'INFO'}, "JSON file written to " + absolute_file_path) return {'FINISHED'}
def _clear_master_grip(self, armature_object): bone_name = self._get_master_grip_bone_name() bpy.ops.object.mode_set(mode='EDIT', toggle=False) bone = RigService.find_edit_bone_by_name(bone_name, armature_object) _LOG.debug("Master grip bone to remove, if any", bone) if bone: armature_object.data.edit_bones.remove(bone) bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
def _clear_finger_ik(self, finger_number, armature_object): _LOG.enter() bpy.ops.object.mode_set(mode='EDIT', toggle=False) bone_name = self._get_point_ik_bone_name_for_finger(finger_number) bone = RigService.find_edit_bone_by_name(bone_name, armature_object) _LOG.debug("Point bone to remove, if any", bone) if bone: armature_object.data.edit_bones.remove(bone)
def _create_foot_ik_bone(self, armature_object): _LOG.enter() bpy.ops.object.mode_set(mode='EDIT', toggle=False) foot_name = self.get_foot_name() bones = armature_object.data.edit_bones bone = bones.new(self.which_leg + "_foot_ik") bone.head = self._bone_info["pose_bones"][foot_name]["head"] bone.tail = self._bone_info["pose_bones"][foot_name]["tail"] bone.roll = self._bone_info["edit_bones"][foot_name]["roll"] bone.matrix = self._bone_info["pose_bones"][foot_name]["matrix"] # Needed to save bone bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='POSE', toggle=False) RigService.display_pose_bone_as_empty(armature_object, self.which_leg + "_foot_ik", empty_type="CIRCLE") pose_bone = RigService.find_pose_bone_by_name( self.which_leg + "_foot_ik", armature_object) pose_bone.custom_shape_scale = 0.5 if self.settings["leg_target_rotates_foot"]: bpy.ops.object.mode_set(mode='POSE', toggle=False) constraint = RigService.add_bone_constraint_to_pose_bone( self.get_foot_name(), armature_object, "COPY_ROTATION") constraint.target = armature_object constraint.subtarget = self.which_leg + "_foot_ik" if self.settings["leg_target_rotates_lower_leg"]: lower_leg_segments = self.get_reverse_list_of_bones_in_leg( False, True, False, False) for name in lower_leg_segments: constraint = RigService.add_bone_constraint_to_pose_bone( name, armature_object, "COPY_ROTATION") constraint.target = armature_object constraint.subtarget = self.which_leg + "_foot_ik" constraint.use_x = False constraint.use_z = False constraint.influence = 0.4 / len(lower_leg_segments) for i in range(3): pose_bone.lock_scale[i] = True
def _setup_head(self, armature_object): _LOG.enter() head = self.get_list_of_head_bones() # pylint: disable=E1111 _LOG.dump("Head", head) self._set_use_connect_on_bones(armature_object, head) bpy.ops.object.mode_set(mode='POSE', toggle=False) first_head_bone = RigService.find_pose_bone_by_name( head[0], armature_object) first_head_bone.rigify_type = 'spines.super_head'
def reposition_edit_bone(self): """Reposition bones to fit the current state of the basemesh.""" bpy.ops.object.mode_set(mode='EDIT', toggle=False) for bone_name in self.rig_definition.keys(): bone_info = self.rig_definition[bone_name] bone = RigService.find_edit_bone_by_name(bone_name, self.armature_object) bone.head = self._get_best_location_from_strategy(bone_info["head"]) bone.tail = self._get_best_location_from_strategy(bone_info["tail"]) bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
def _populate_human_info_with_rig_info(human_info, basemesh): armature_object = ObjectService.find_object_of_type_amongst_nearest_relatives(basemesh, "Skeleton") if not armature_object is None: rig_type = RigService.identify_rig(armature_object) if rig_type is None or rig_type == "unkown": raise ValueError("Could not identify rig type. Custom rigs cannot be serialized.") if rig_type is None or rig_type == "rigify_generated": raise ValueError("Generated rigify rigs cannot be serialized. If you want to serialize the rig you have to do it before generating the final rig.") human_info["rig"] = rig_type
def remove_ik(self, armature_object): """Remove rig helpers for arms and hands based on the settings that were provided when constructing the class, and information about the current status of the armature object.""" _LOG.enter() self._bone_info = RigService.get_bone_orientation_info_as_dict(armature_object) mode = str(RigHelpersProperties.get_value("arm_mode", entity_reference=armature_object)).strip() _LOG.debug("mode is", mode) include_shoulder = False if mode == "LOWERUPPERSHOULDER": include_shoulder = True if mode == "SHOULDERCHAIN": include_shoulder = True bpy.ops.object.mode_set(mode='POSE', toggle=False) bones_to_clear = self.get_reverse_list_of_bones_in_arm(True, True, True, include_shoulder) for bone_name in bones_to_clear: _LOG.debug("Will attempt to clear constraints from", bone_name) RigService.remove_all_constraints_from_pose_bone(bone_name, armature_object) self._show_bones(armature_object, bones_to_clear) bpy.ops.object.mode_set(mode='EDIT', toggle=False) ik_bones = [ self.which_arm + "_hand_ik", self.which_arm + "_elbow_ik", self.which_arm + "_shoulder_ik" ] for bone_name in ik_bones: bone = RigService.find_edit_bone_by_name(bone_name, armature_object) if bone: armature_object.data.edit_bones.remove(bone) bpy.ops.object.mode_set(mode='OBJECT', toggle=False) _LOG.debug("Done")
def _setup_shoulders(self, armature_object): _LOG.enter() for side in [True, False]: shoulder = self.get_list_of_shoulder_bones(side) # pylint: disable=E1111 _LOG.dump("Shoulder", shoulder) self._set_use_connect_on_bones(armature_object, shoulder) bpy.ops.object.mode_set(mode='POSE', toggle=False) first_shoulder_bone = RigService.find_pose_bone_by_name( shoulder[0], armature_object) first_shoulder_bone.rigify_type = 'basic.super_copy'
def update_edit_bone_metadata(self): """Assign metadata fitting for the edit bones.""" bpy.ops.object.mode_set(mode='EDIT', toggle=False) for bone_name in self.rig_definition.keys(): bone_info = self.rig_definition[bone_name] bone = RigService.find_edit_bone_by_name(bone_name, self.armature_object) if bone_info["parent"]: bone.parent = RigService.find_edit_bone_by_name(bone_info["parent"], self.armature_object) bone.use_connect = bone_info["use_connect"] bone.use_local_location = bone_info["use_local_location"] bone.use_inherit_rotation = bone_info["use_inherit_rotation"] bone.inherit_scale = bone_info["inherit_scale"] if "layers" in bone_info: i = 0 for layer in bone_info["layers"]: bone.layers[i] = layer i = i + 1 bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
def _setup_legs(self, armature_object): _LOG.enter() for side in [True, False]: leg = self.get_list_of_leg_bones(side) # pylint: disable=E1111 _LOG.dump("Leg", leg) self._set_use_connect_on_bones(armature_object, leg) bpy.ops.object.mode_set(mode='POSE', toggle=False) first_leg_bone = RigService.find_pose_bone_by_name( leg[0], armature_object) first_leg_bone.rigify_type = 'limbs.paw'
def _apply_point(self, armature_object): _LOG.enter() for finger_number in [1, 2, 3, 4, 5]: self._create_point_ik_bone(finger_number, armature_object) ik_name = self._get_point_ik_bone_name_for_finger(finger_number) bpy.ops.object.mode_set(mode='EDIT', toggle=False) parent_name = self.get_immediate_parent_name_of_finger(finger_number) parent_bone = RigService.find_edit_bone_by_name(parent_name, armature_object) ik_bone = RigService.find_edit_bone_by_name(ik_name, armature_object) ik_bone.parent = parent_bone chain_length = self.get_finger_segment_count(finger_number) self._set_finger_ik_target(finger_number, armature_object, chain_length) if self.settings["hide_fk"]: bones_to_hide = self.get_reverse_list_of_bones_in_finger(finger_number) self._hide_bones(armature_object, bones_to_hide)
def add_standard_rig(basemesh, rig_name, import_weights=True): rigs_dir = LocationService.get_mpfb_data("rigs") standard_dir = os.path.join(rigs_dir, "standard") rig_file = os.path.join(standard_dir, "rig." + rig_name + ".json") rig = Rig.from_json_file_and_basemesh(rig_file, basemesh) armature_object = rig.create_armature_and_fit_to_basemesh() basemesh.parent = armature_object armature_object.location = basemesh.location basemesh.location = (0.0, 0.0, 0.0) if import_weights: weights_file = os.path.join(standard_dir, "weights." + rig_name + ".json") weights = dict() with open(weights_file, 'r') as json_file: weights = json.load(json_file) RigService.apply_weights(armature_object, basemesh, weights) return armature_object