def __init__(self, obj, bone, params): self.obj = obj self.params = params # Get the chain of 2 connected bones leg_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(leg_bones) != 2: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- leg bones != 2" % (strip_org(bone))) # Get the foot and heel foot = None heel = None for b in self.obj.data.bones[leg_bones[1]].children: if b.use_connect is True: if len(b.children) >= 1 and has_connected_children(b): foot = b.name else: heel = b.name if foot is None: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- could not find foot bone (that is, a bone with >1 children connected) attached to bone '%s'" % (strip_org(bone), strip_org(leg_bones[1]))) if heel is None: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- could not find heel bone (that is, a bone with no children connected) attached to bone '%s'" % (strip_org(bone), strip_org(leg_bones[1]))) # Get the toe toe = None for b in self.obj.data.bones[foot].children: if b.use_connect is True: toe = b.name if toe is None: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- toe is None" % (strip_org(bone))) self.org_bones = leg_bones + [foot, toe, heel] # Get rig parameters if params.separate_hose_layers: layers = list(params.hose_layers) else: layers = None use_complex_rig = params.use_complex_leg knee_base_name = params.knee_base_name primary_rotation_axis = params.primary_rotation_axis_legacy # Based on common limb self.rubber_hose_limb = limb_common.RubberHoseLimb( obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], use_complex_rig, knee_base_name, primary_rotation_axis, layers)
def __init__(self, obj, bone, params, ikfk_switch=False): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj self.params = params self.switch = ikfk_switch # Get the chain of 2 connected bones leg_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(leg_bones) != 2: raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) # Get the foot and heel foot = None heel = None rocker = None for b in self.obj.data.bones[leg_bones[1]].children: if b.use_connect == True: if len(b.children) >= 1 and has_connected_children(b): foot = b.name else: heel = b.name if len(b.children) > 0: rocker = b.children[0].name if foot is None or heel is None: print("blah") raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) # Get the toe toe = None for b in self.obj.data.bones[foot].children: if b.use_connect == True: toe = b.name # Get toe if toe is None: raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) self.org_bones = leg_bones + [foot, toe, heel, rocker] # Get rig parameters if params.separate_ik_layers: self.layers = list(params.ik_layers) else: self.layers = None self.bend_hint = params.bend_hint self.primary_rotation_axis = params.primary_rotation_axis
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj self.params = params # Get the chain of 2 connected bones leg_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(leg_bones) != 2: raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone))) # Get the foot and heel foot = None heel = None for b in self.obj.data.bones[leg_bones[1]].children: if b.use_connect == True: if len(b.children) == 0: heel = b.name else: foot = b.name if foot == None or heel == None: raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone))) # Get the toe toe = None for b in self.obj.data.bones[foot].children: if b.use_connect == True: toe = b.name # Get the toe if toe == None: raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone))) self.org_bones = leg_bones + [foot, toe, heel] # Get (optional) parent if self.obj.data.bones[bone].parent == None: self.org_parent = None else: self.org_parent = self.obj.data.bones[bone].parent.name # Get rig parameters if "layers" in params: self.layers = get_layers(params["layers"]) else: self.layers = None self.primary_rotation_axis = params.primary_rotation_axis
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj self.params = params # Get the chain of 2 connected bones leg_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(leg_bones) != 2: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) # Get the foot and heel foot = None heel = None for b in self.obj.data.bones[leg_bones[1]].children: if b.use_connect == True: if len(b.children) >= 1 and has_connected_children(b): foot = b.name else: heel = b.name if foot is None or heel is None: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) # Get the toe toe = None for b in self.obj.data.bones[foot].children: if b.use_connect == True: toe = b.name if toe is None: raise MetarigError( "RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone))) self.org_bones = leg_bones + [foot, toe, heel] # Get rig parameters self.use_thigh_twist = params.use_thigh_twist self.use_shin_twist = params.use_shin_twist
def get_mouth(self): """ Returns the main bones of the mouth chain :return: """ bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones lip_bones = [] for child in edit_bones[self.bones['org'][0]].children: if not child.use_connect: lip_bones.append(child.name) # Rule check if len(lip_bones) != 4: raise MetarigError( "Exactly 4 disconnected chains (lips) must be parented to main bone" ) mouth_bones_dict = {'top': [], 'bottom': []} self.lip_len = len(self.get_chain_bones(lip_bones[0])) # Check all half-lips have same length for lip in lip_bones: if len(self.get_chain_bones(lip)) != self.lip_len: raise MetarigError("All lip chains must be the same length") m_b_head_positions = [edit_bones[name].head for name in lip_bones] head_sum = m_b_head_positions[0] for h in m_b_head_positions[1:]: head_sum = head_sum + h mouth_center = head_sum / 4 chin_tail_position = edit_bones[self.main_mch].tail mouth_chin_distance = (mouth_center - chin_tail_position).magnitude for m_b in lip_bones: head = edit_bones[m_b].head if (head - chin_tail_position).magnitude < mouth_chin_distance: mouth_bones_dict['bottom'].append(m_b) elif (head - chin_tail_position).magnitude > mouth_chin_distance: mouth_bones_dict['top'].append(m_b) if not (len(mouth_bones_dict['top']) == len(mouth_bones_dict['bottom']) == 2): raise MetarigError("Badly drawn mouth") return mouth_bones_dict
def __init__(self, obj, bone_name, params): """ Gather and validate data about the rig. """ self.obj = obj self.org_bones = [bone_name] + connected_children_names(obj, bone_name) self.params = params # Collect control bone indices self.control_indices = [0, len(self.org_bones) - 1] temp = self.params.chain_bone_controls.split(",") for i in temp: try: j = int(i) - 1 except ValueError: pass else: if (j > 0) and (j < len( self.org_bones)) and (j not in self.control_indices): self.control_indices += [j] self.control_indices.sort() self.pivot_rest = self.params.rest_pivot_slide self.pivot_rest = max(self.pivot_rest, 1.0 / len(self.org_bones)) self.pivot_rest = min(self.pivot_rest, 1.0 - (1.0 / len(self.org_bones))) if len(self.org_bones) <= 1: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone_name)))
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of at least 3 bones" % (strip_org(bone))) # Get params if "layers" in params: layers = get_layers(params["layers"]) else: layers = None primary_rotation_axis = params.primary_rotation_axis_cessen # Arm is based on common limb self.fk_limb = limb_common.FKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], primary_rotation_axis, layers)
def get_bone_rigs(obj, bone_name, halt_on_missing=False): """ Fetch all the rigs specified on a bone. """ rigs = [] rig_type = obj.pose.bones[bone_name].rigify_type rig_type = rig_type.replace(" ", "") if rig_type == "": pass else: # Gather parameters try: params = obj.pose.bones[bone_name].rigify_parameters[0] except (KeyError, IndexError): params = None # Get the rig try: rig = get_rig_type(rig_type).Rig(obj, bone_name, params) except ImportError: message = "Rig Type Missing: python module for type '%s' not found (bone: %s)" % ( rig_type, bone_name) if halt_on_missing: raise MetarigError(message) else: print(message) print('print_exc():') traceback.print_exc(file=sys.stdout) else: rigs += [rig] return rigs
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj self.params = params # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone))) # Get (optional) parent if self.obj.data.bones[bone].parent is None: self.org_parent = None else: self.org_parent = self.obj.data.bones[bone].parent.name # Get the rig parameters if "layers" in params: self.layers = get_layers(params["layers"]) else: self.layers = None self.primary_rotation_axis = params.primary_rotation_axis
def __init__(self, obj, bone, params, ikfk_switch=False): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. ikfk_switch: if True, create an ik/fk switch slider """ self.obj = obj self.params = params self.switch = ikfk_switch # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone))) # Get the rig parameters if params.separate_ik_layers: self.layers = list(params.ik_layers) else: self.layers = None self.bend_hint = params.bend_hint self.primary_rotation_axis = params.primary_rotation_axis
def __init__(self, obj, bone, params, ikfk_switch=False): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. ikfk_switch: if True, create an ik/fk switch slider """ self.obj = obj self.params = params # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone))) # Get the rig parameters if params.separate_ik_layers: layers = list(params.ik_layers) else: layers = None bend_hint = params.bend_hint primary_rotation_axis = params.primary_rotation_axis_cessen pole_target_base_name = self.params.elbow_base_name + "_target" # Arm is based on common limb self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], None, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch)
def __init__(self, obj, bone, params): self.obj = obj self.params = params # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone))) # Get rig parameters if params.separate_hose_layers: layers = list(params.hose_layers) else: layers = None use_complex_rig = params.use_complex_arm elbow_base_name = params.elbow_base_name primary_rotation_axis = params.primary_rotation_axis_cessen # Based on common limb self.rubber_hose_limb = limb_common.RubberHoseLimb( obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], use_complex_rig, elbow_base_name, primary_rotation_axis, layers)
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ bb = obj.data.bones if bb[bone].children is None: raise MetarigError("RIGIFY ERROR: bone '%s': rig type requires one child" % org_name(bone.name)) if bb[bone].use_connect == True: raise MetarigError("RIGIFY ERROR: bone '%s': rig type cannot be connected to parent" % org_name(bone.name)) self.obj = obj self.org_bones = {"delta": bone, "child": bb[bone].children[0].name} self.org_names = [org_name(bone), org_name(bb[bone].children[0].name)]
def __init__(self, obj, bone_name, params): """ Gather and validate data about the rig. """ self.obj = obj self.org_bones = [bone_name] + connected_children_names(obj, bone_name) self.params = params self.make_controls = params.make_controls self.make_deforms = params.make_deforms if len(self.org_bones) <= 1: raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone_name)))
def get_eyelids(self): """ Returns the main bones of the lids chain :return: """ bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones lid_bones = [] for child in edit_bones[self.bones['org'][0]].children: if not child.use_connect: lid_bones.append(child.name) # Rule check if len(lid_bones) != 2: raise MetarigError( "Exactly 2 disconnected chains (lids) must be parented to main bone" ) eyelids_bones_dict = {'top': [], 'bottom': []} self.lid_len = len(self.get_chain_bones(lid_bones[0])) # Check both have same length for lid in lid_bones: if len(self.get_chain_bones(lid)) != self.lid_len: raise MetarigError("All lid chains must be the same length") if edit_bones[lid_bones[0]].tail.z < edit_bones[lid_bones[1]].tail.z: eyelids_bones_dict['top'].append(lid_bones[1]) eyelids_bones_dict['bottom'].append(lid_bones[0]) else: eyelids_bones_dict['top'].append(lid_bones[0]) eyelids_bones_dict['bottom'].append(lid_bones[1]) if not (len(eyelids_bones_dict['top']) == len( eyelids_bones_dict['bottom']) == 1): raise MetarigError("Badly drawn eyelids on %s" % self.bones['org'][0]) return eyelids_bones_dict
def get_mouth(self): """ Returns the mouth bones placeholders :return: """ bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones lip_bones = [] for child in edit_bones[self.bones['org'][0]].children: if not child.use_connect: lip_bones.append(child.name) # Rule check if len(lip_bones) != 4: raise MetarigError("Exactly 4 disconnected placeholder bones (lip angles) must be parented to main bone") mouth_bones_dict = {'top': [], 'corners': [], 'bottom': []} bpy.ops.object.mode_set(mode='OBJECT') pose_bones = self.obj.pose.bones for b in lip_bones: if pose_bones[b].rigify_parameters.bone_type == 'lip.T': mouth_bones_dict['top'].append(b) if pose_bones[b].rigify_parameters.bone_type == 'lip.B': mouth_bones_dict['bottom'].append(b) elif pose_bones[b].rigify_parameters.bone_type == 'lip.L' or\ pose_bones[b].rigify_parameters.bone_type == 'lip.R': mouth_bones_dict['corners'].append(b) if not len(mouth_bones_dict['top']) == 1 \ or not len(mouth_bones_dict['bottom']) == 1\ or not len(mouth_bones_dict['corners']) == 2: raise MetarigError("Exactly 4 bones w property rigify_parameters.bone_type = lip.X (T,B,L,R) must be parented to main bone") return mouth_bones_dict
def __init__(self, obj, bone_name, params): """ Gather and validate data about the rig. """ self.obj = obj self.org_bones = [bone_name] + connected_children_names(obj, bone_name) self.params = params if len(self.org_bones) <= 1: raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone_name))) self.isolate = False if self.obj.data.bones[bone_name].parent: self.isolate = True
def __init__(self, obj, bone_name, params): self.obj = obj self.params = params bones = self.obj.data.bones self.org_bone = bone_name if bones[bone_name].parent is not None: self.org_parent = bones[bone_name].parent.name else: self.org_parent = None if bones[bone_name].use_connect: raise MetarigError( "RIGIFY ERROR: Bone %s should not be connected. " "Check bone chain for multiple pantin.simple rigs" % (strip_org(self.org_parent)))
def __init__(self, obj, bone_name, params): self.obj = obj self.params = params eb = self.obj.data.edit_bones self.org_bones = [bone_name] + connected_children_names( self.obj, bone_name) if eb[bone_name].parent is not None: self.org_parent = eb[bone_name].parent.name else: self.org_parent = None if eb[bone_name].use_connect: raise MetarigError( "RIGIFY ERROR: Bone %s should not be connected. " "Check bone chain for multiple pantin.simple rigs" % (strip_org(self.org_parent))) if self.params.chain_type == 'Dynamic' and len(self.org_bones) > 1: self.params.chain_type = "Curve"
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. """ self.obj = obj self.org_bones = [bone] + connected_children_names(obj, bone) self.params = params if len(self.org_bones) <= 1: raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone))) # Get user-specified layers, if they exist if params.separate_extra_layers: self.ex_layers = list(params.extra_layers) else: self.ex_layers = None # Get other rig parameters self.primary_rotation_axis = params.primary_rotation_axis self.use_digit_twist = params.use_digit_twist
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. """ self.obj = obj self.params = params siblings = bone_siblings(obj, bone) if len(siblings) == 0: raise MetarigError("RIGIFY ERROR: Bone '%s': must have a parent and at least one sibling" % (strip_org(bone))) # Sort list by name and distance siblings.sort() siblings.sort(key=lambda b: bone_distance(obj, bone, b)) self.org_bones = [bone] + siblings # Get rig parameters self.palm_rotation_axis = params.palm_rotation_axis
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. Store any data or references to data that will be needed later on. In particular, store references to bones that will be needed, and store names of bones that will be needed. Do NOT change any data in the scene. This is a gathering phase only. """ self.obj = obj self.params = params # Get the chain of 3 connected bones self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2] if len(self.org_bones) != 3: raise MetarigError( "RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone))) # Get rig parameters self.use_upper_arm_twist = params.use_upper_arm_twist self.use_forearm_twist = params.use_forearm_twist
def get_subchains(self, name, exclude=None): """ :param name: :type name: parent chain bone name :parameter exclude: list of subchains to exclude :return: """ bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones if exclude is None: exclude = [] subchains = [] chain = self.get_chain_object_by_name(name) for bone in edit_bones[name].children: if self.obj.pose.bones[ bone. name].rigify_type == "" and not bone.use_connect and bone.name not in exclude: subchain = Chain(self.obj, bone.name, self.orientation_bone, chain_type=chain.chain_type, parent=chain) if subchain.length != chain.length: raise MetarigError( "Subchains of chain starting with %s are not the same length! assign a rig_type/" "unconnected children of main bone of chain" % name) else: subchains.append(bone.name) self.chain_objects[subchain.base_name] = subchain return subchains
def generate(self): def parent_ctrl(eb, child, parent_to=None): """This tries to parent the child to a .L/.R bone.""" # Get parent if none supplied if parent_to is None and eb[child].parent is not None: parent_to = eb[child].parent.name print(parent_to) if parent_to + self.params.object_side in eb: eb[child].parent = (eb[parent_to + self.params.object_side]) elif parent_to in eb: eb[child].parent = eb[parent_to] elif 'MCH-Flip' in eb: eb[child].parent = eb['MCH-Flip'] else: raise Exception( "RIGIFY ERROR: Bone %s does not have a %s side" % (strip_org(eb[b].parent.name), side)) if self.params.use_parent_Z_index and self.org_parent is not None: # Get parent's Z indices bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones def_parent_name = make_deformer_name(strip_org(self.org_parent)) if (self.params.object_side != ".C" and def_parent_name[-2:] not in ['.L', '.R']): def_parent_name += self.params.object_side if not def_parent_name in pb: raise Exception( "RIGIFY ERROR: Bone %s does not have a %s side" % (strip_org(self.org_parent), self.params.object_side)) parent_p = pb[def_parent_name] member_Z_index = parent_p['member_index'] bone_Z_index = 0 for b in pb: if b.bone.use_deform and b.name.startswith('DEF-'): if not 'member_index' in b: raise MetarigError( "RIGIFY ERROR: One rig bone with should not be connected. " "Check armature for connected bones.") if (b['member_index'] == member_Z_index and b['bone_index'] > bone_Z_index): bone_Z_index = b['bone_index'] bone_Z_index += 1 bpy.ops.object.mode_set(mode='EDIT') else: member_Z_index = self.params.member_Z_index bone_Z_index = self.params.first_bone_Z_index eb = self.obj.data.edit_bones ctrl_chain = [] mch_chain = [] # def_chain = [] # if self.params.duplicate_lr: # sides = ['.L', '.R'] # else: side = self.params.object_side if side == '.C': side = '' # IK control bone if self.params.chain_type == 'IK': last_bone = self.org_bones[-1] ctrl_bone = new_bone(self.obj, strip_org(last_bone) + ".ik" + side) ctrl_bone_e = eb[ctrl_bone] ctrl_bone_e.head = eb[last_bone].tail ctrl_bone_e.tail = eb[last_bone].tail + Vector((0.3, 0, 0)) align_bone_z_axis(self.obj, ctrl_bone, Vector((0, 1, 0))) ctrl_chain.append(ctrl_bone) # ctrl_bone_e.layers = layers for i, b in enumerate(self.org_bones): # Control bones if self.params.chain_type in {'Normal', 'Curve', 'Dynamic'}: if side in b: ctrl_bone_name = b else: ctrl_bone_name = b + side ctrl_bone_name = strip_org(ctrl_bone_name) ctrl_bone = copy_bone(self.obj, b, ctrl_bone_name) ctrl_bone_e = eb[ctrl_bone] ctrl_chain.append(ctrl_bone) if self.params.chain_type == 'Curve': ctrl_bone_e.use_connect = False if self.params.curve_parent_to_first: if i > 0: parent_ctrl(eb, ctrl_bone, parent_to=ctrl_chain[0]) else: parent_ctrl(eb, ctrl_bone, parent_to=self.org_parent) else: parent_ctrl(eb, ctrl_bone, parent_to=self.org_parent) ctrl_bone_e.tail = (ctrl_bone_e.head + Vector( (0, 0, 1)) * ctrl_bone_e.length) align_bone_z_axis(self.obj, ctrl_bone, Vector((0, 1, 0))) elif self.params.chain_type == 'Dynamic': # Create an empty object to use slow parent # What follows is quite dirty. # ctrl_bone_e.parent = eb[self.org_parent] parent_ctrl(eb, ctrl_bone) empty_name = self.obj.name + "_" + strip_org(b) + '.dyn' if empty_name in bpy.data.objects: empty_obj = bpy.data.objects[empty_name] else: empty_obj = bpy.data.objects.new(empty_name, None) if not empty_name in bpy.context.scene.objects: bpy.context.scene.objects.link(empty_obj) empty_obj.empty_draw_type = 'SPHERE' empty_obj.empty_draw_size = self.obj.data.bones[ b].length / 10 empty_obj.hide = True empty_obj.parent = self.obj empty_obj.parent_type = 'BONE' empty_obj.parent_bone = ctrl_bone empty_obj.matrix_local = Matrix() empty_obj.use_slow_parent = True empty_obj.slow_parent_offset = 1.0 # Mechanism bones if self.params.chain_type == 'Curve': stretch_bone = copy_bone( self.obj, b, make_mechanism_name(strip_org(b)) + '.stretch' + side) stretch_bone_e = eb[stretch_bone] stretch_bone_e.use_connect = False stretch_bone_e.parent = eb[ctrl_bone] mch_chain.append(stretch_bone) elif self.params.chain_type == 'IK': ik_bone = copy_bone( self.obj, b, make_mechanism_name(strip_org(b)) + '.ik' + side) ik_bone_e = eb[ik_bone] ik_bone_e.parent = eb[mch_chain[-1] if i > 0 else self. org_parent] mch_chain.append(ik_bone) elif self.params.chain_type == 'Dynamic': dyn_bone = copy_bone( self.obj, b, make_mechanism_name(strip_org(b)) + '.dyn' + side) dyn_bone_e = eb[dyn_bone] dyn_bone_e.parent = eb[ctrl_bone] mch_chain.append(dyn_bone) # Parenting # if self.params.chain_type == 'Normal': if (i == 0 and self.params.chain_type in ('Normal', 'Dynamic')): parent_ctrl(eb, ctrl_bone) # Def bones def_bone = pantin_utils.create_deformation(self.obj, b, member_Z_index, bone_Z_index + i, 0.0, b + side) if self.params.chain_type == 'Curve': # Curve end bone last_bone = self.org_bones[-1] ctrl_bone = new_bone(self.obj, strip_org(last_bone) + ".end" + side) ctrl_bone_e = eb[ctrl_bone] last_bone_e = eb[last_bone] ctrl_bone_e.use_connect = False if self.params.curve_parent_to_first: ctrl_bone_e.parent = eb[ctrl_chain[0]] else: parent_ctrl(eb, ctrl_bone, parent_to=self.org_parent) ctrl_bone_e.head = last_bone_e.tail ctrl_bone_e.tail = (ctrl_bone_e.head + (last_bone_e.tail - last_bone_e.head)) align_bone_z_axis(self.obj, ctrl_bone, Vector((0, 1, 0))) ctrl_chain.append(ctrl_bone) ctrl_bone_e.layers = last_bone_e.layers # ctrl_bone_e.layers = layers bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Pose bone settings if self.params.chain_type in ('IK', 'Curve', 'Dynamic'): pbone = pb[ctrl_chain[-1]] pbone.rotation_mode = 'XZY' pbone.lock_location = (False, False, True) pbone.lock_rotation = (True, True, False) pbone.lock_rotation_w = False pbone.lock_scale = (False, False, False) if self.params.chain_type in ('IK', 'Curve', 'Dynamic'): # Widgets for ctrl_bone in ctrl_chain: global_scale = pb[ctrl_bone].length # self.obj.dimensions[2] # member_factor = 0.06 widget_size = global_scale * 0.3 # * member_factor pantin_utils.create_aligned_circle_widget(self.obj, ctrl_bone, radius=widget_size) # Constraints for org, mch in zip(self.org_bones, mch_chain): con = pb[org].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = mch else: # Widgets widget_size = 0.5 for bone in ctrl_chain: pantin_utils.create_capsule_widget(self.obj, bone, length=widget_size, width=widget_size * 0.1, head_tail=0.5, horizontal=False) # Constraints for org, ctrl in zip(self.org_bones, ctrl_chain): con = pb[org].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = ctrl ui_script = "" if self.params.chain_type == 'Curve': for ctrl, mch in zip(ctrl_chain[1:], mch_chain): con = pb[mch].constraints.new('STRETCH_TO') con.name = "stretch_to" con.target = self.obj con.subtarget = ctrl con.volume = 'NO_VOLUME' con.keep_axis = 'PLANE_Z' elif self.params.chain_type == 'IK': last_bone = mch_chain[-1] con = pb[last_bone].constraints.new('IK') con.target = self.obj con.subtarget = ctrl_bone con.chain_count = len(self.org_bones) # # Pelvis follow # if self.params.do_flip: # pantin_utils.create_ik_child_of( # self.obj, ctrl_bone, self.params.pelvis_name) elif self.params.chain_type == 'Dynamic': for ctrl, mch in zip(ctrl_chain, mch_chain): con = pb[mch].constraints.new('DAMPED_TRACK') con.name = "damped_track" con.target = empty_obj # con.volume = 'NO_VOLUME' # con.keep_axis = 'PLANE_Z' # con.rest_length = pb[ctrl].length ui_script = script % (ctrl, dyn_bone) # % ctrl_bone, MCH-bone.dyn elif self.params.chain_type == 'Def': # Modify constraints to add side suffix if side in ('.L', '.R'): for b in self.org_bones: for con in pb[b].constraints: if (hasattr(con, 'subtarget') and con.subtarget + side in pb): con.subtarget += side return { 'script': [ui_script], 'imports': UI_IMPORTS, 'utilities': PANTIN_UTILS, 'register': PANTIN_REGISTER, 'register_props': REGISTER_PANTIN_PROPS, }
def generate(self): if self.params.use_parent_Z_index and self.org_parent is not None: # Get parent's Z indices bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones def_parent_name = make_deformer_name(strip_org(self.org_parent)) if (self.params.object_side != ".C" and def_parent_name[-2:] not in ['.L', '.R']): def_parent_name += self.params.object_side # print("DEF PARENT", def_parent_name) if not def_parent_name in pb: raise MetarigError( "RIGIFY ERROR: Bone %s does not have a %s side" % (strip_org(self.org_parent), self.params.object_side)) parent_p = pb[def_parent_name] member_Z_index = parent_p['member_index'] bone_Z_index = 0 for b in pb: if b.bone.use_deform and b.name.startswith('DEF-'): if (b['member_index'] == member_Z_index and b['bone_index'] > bone_Z_index): bone_Z_index = b['bone_index'] bone_Z_index += 1 bpy.ops.object.mode_set(mode='EDIT') else: member_Z_index = self.params.member_Z_index bone_Z_index = self.params.first_bone_Z_index eb = self.obj.data.edit_bones ctrl_chain = [] # mch_chain = [] # Control bones # Left left_ctrl = copy_bone(self.obj, self.org_bone, strip_org(self.params.eye_name) + '.L') left_ctrl_e = eb[left_ctrl] left_ctrl_e.use_connect = False left_ctrl_e.tail = (left_ctrl_e.tail + Vector( (0, 0, 1)) * left_ctrl_e.length) left_ctrl_e.head = eb[self.org_bone].tail align_bone_z_axis(self.obj, left_ctrl, Vector((0, 1, 0))) ctrl_chain.append(left_ctrl) # Right right_ctrl = copy_bone(self.obj, self.org_bone, strip_org(self.params.eye_name) + '.R') right_ctrl_e = eb[right_ctrl] right_ctrl_e.use_connect = False right_ctrl_e.tail = (right_ctrl_e.head + Vector( (0, 0, 1)) * right_ctrl_e.length) align_bone_z_axis(self.obj, right_ctrl, Vector((0, 1, 0))) ctrl_chain.append(right_ctrl) # Main main_ctrl = copy_bone(self.obj, self.org_bone, strip_org(self.org_bone)) main_ctrl_e = eb[main_ctrl] main_ctrl_e.head = (main_ctrl_e.head + main_ctrl_e.tail) / 2 if self.org_parent is not None: main_ctrl_e.parent = eb[self.org_parent] ctrl_chain.append(main_ctrl) # Mechanism bones inter = copy_bone( self.obj, self.org_bone, make_mechanism_name(strip_org(self.org_bone) + '.intermediate')) eb[inter].parent = eb[main_ctrl] eb[left_ctrl].parent = eb[inter] eb[right_ctrl].parent = eb[inter] # # Def bones for i, b in enumerate([left_ctrl, right_ctrl]): def_bone = pantin_utils.create_deformation(self.obj, b, member_Z_index, bone_Z_index + i, 0.0, b) bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Widgets pantin_utils.create_capsule_widget(self.obj, main_ctrl, length=pb[self.org_bone].length, width=pb[self.org_bone].length * 0.7, horizontal=False) for b in [left_ctrl, right_ctrl]: pantin_utils.create_aligned_circle_widget(self.obj, b, radius=pb[b].length / 4) # for ctrl_bone in ctrl_chain: # global_scale = pb[ctrl_bone].length # self.obj.dimensions[2] # # member_factor = 0.06 # widget_size = global_scale * 0.5 # * member_factor # pantin_utils.create_aligned_circle_widget( # self.obj, ctrl_bone, radius=widget_size) # Constraints # for org, ctrl in zip(self.org_bones, mch_chain): con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = inter # # Pelvis follow # if self.params.do_flip: # pantin_utils.create_ik_child_of( # self.obj, ctrl_bone, self.params.pelvis_name) return { 'imports': UI_IMPORTS, 'utilities': PANTIN_UTILS, 'register': PANTIN_REGISTER, 'register_props': REGISTER_PANTIN_PROPS, }