def get_cluster_data(self): """ Returns the center position and common direction of an eye-cluster :return: [position, direction] :rtype: list(Vector) """ edit_bones = self.obj.data.edit_bones positions = [] sum_position = Vector((0, 0, 0)) y_direction = None z_direction = Vector((0, 0, 0)) for name in self.get_cluster_names(): did_generate_ctrl = strip_org(name) in edit_bones if not did_generate_ctrl: # this is not the last eye in the cluster, delay return [None, None, None] else: positions.append(edit_bones[strip_org(name)].head) sum_position += edit_bones[strip_org(name)].head y_direction = edit_bones[strip_org(name)].y_axis z_direction += edit_bones[strip_org(name)].z_axis if positions and y_direction and z_direction: position = sum_position / len(positions) z_direction = z_direction / len(positions) else: return [None, None, None] return [position, y_direction, z_direction]
def create_deform(self): org_bones = self.org_bones bpy.ops.object.mode_set(mode='EDIT') def_bones = [] for o in org_bones: def_name = make_deformer_name(strip_org(o)) def_name = copy_bone(self.obj, o, def_name) def_bones.append(def_name) bpy.ops.object.mode_set(mode='POSE') # Create bbone segments for bone in def_bones: self.obj.data.bones[bone].bbone_segments = self.bbones if not self.SINGLE_BONE: self.obj.data.bones[def_bones[0]].bbone_easein = 0.0 self.obj.data.bones[def_bones[-1]].bbone_easeout = 0.0 else: self.obj.data.bones[def_bones[0]].bbone_easein = 1.0 self.obj.data.bones[def_bones[-1]].bbone_easeout = 1.0 bpy.ops.object.mode_set(mode='EDIT') conv_def = "" if self.params.conv_bone and self.params.conv_def: b = org(self.params.conv_bone) conv_def = make_deformer_name(strip_org(b)) conv_def = copy_bone(self.obj, b, conv_def) return def_bones, conv_def
def parent_bones(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones super().parent_bones() ctrl_chain = self.bones['ctrl'][strip_org(self.base_bone)] tweak_chain = self.bones['tweaks'][strip_org(self.base_bone)] def_chain = self.bones['def'][strip_org(self.base_bone)] edit_bones[tweak_chain[0]].parent = None for ctrl, tweak in zip(ctrl_chain[1:-1], tweak_chain[1:-1]): edit_bones[tweak].use_connect = False edit_bones[tweak].parent = edit_bones[ctrl] edit_bones[tweak_chain[-1]].use_connect = False edit_bones[tweak_chain[-1]].parent = edit_bones[ctrl_chain[-2]] for i, def_bone in enumerate(def_chain[1:]): edit_bones[def_bone].use_connect = True edit_bones[def_bone].parent = edit_bones[def_chain[i]] for i, ctrl in enumerate(ctrl_chain[1:-1]): edit_bones[ctrl].parent = edit_bones[ctrl_chain[i]] edit_bones[ctrl_chain[0]].parent = edit_bones[self.bones['tail_mch'] ['rot_tail_mch']] edit_bones[self.bones['tail_mch']['rot_tail_mch']].parent = edit_bones[ tweak_chain[0]]
def make_constraints(self): bpy.ops.object.mode_set(mode='OBJECT') pose_bones = self.obj.pose.bones super().make_constraints() def_chain = self.bones['def'][strip_org(self.base_bone)] tweak_chain = self.bones['tweaks'][strip_org(self.base_bone)] ctrl_chain = self.bones['ctrl'][strip_org(self.base_bone)] for i, def_bone in enumerate(def_chain): pose_bones[def_bone].constraints[0].subtarget = tweak_chain[-i - 1] pose_bones[def_bone].constraints[1].subtarget = tweak_chain[-i - 2] pose_bones[def_bone].constraints[2].subtarget = tweak_chain[-i - 2] for i, ctrl in enumerate(ctrl_chain): if ctrl != ctrl_chain[-1]: owner = pose_bones[ctrl] if i == 0: subtarget = ctrl_chain[-1] else: subtarget = ctrl_chain[i - 1] make_constraints_from_string(owner, self.obj, subtarget, "CR1.0LLO") owner.constraints[-1].use_y = False first_org = self.get_chain_bones(self.base_bone)[0] if pose_bones[first_org].parent: owner = pose_bones[self.bones['tail_mch']['rot_tail_mch']] subtarget = pose_bones[first_org].parent.name make_constraints_from_string(owner, self.obj, subtarget, "CR1.0WW")
def parent_bones(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones super().parent_bones() edit_bones[self.bones['tongue_ctrl']['tongue_master']].parent = edit_bones[self.orientation_bone] def_chain = self.bones['def'][strip_org(self.base_bone)] ctrl_chain = self.bones['ctrl'][strip_org(self.base_bone)] mch_chain = self.bones['mch'][strip_org(self.base_bone)] org_chain = self.bones['org'] for ctrl, def_bone in zip(ctrl_chain, def_chain): edit_bones[def_bone].parent = edit_bones[ctrl] for ctrl, mch in zip(ctrl_chain[1:-1], mch_chain): edit_bones[ctrl].parent = edit_bones[mch] edit_bones[mch].parent = edit_bones[self.orientation_bone] edit_bones[ctrl_chain[0]].parent = edit_bones[self.bones['tongue_ctrl']['tongue_master']] edit_bones[ctrl_chain[-1]].parent = edit_bones[self.orientation_bone] for ctrl, org_bone in zip(ctrl_chain, org_chain): edit_bones[org_bone].use_connect = False edit_bones[org_bone].parent = edit_bones[ctrl]
def create_mch(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones self.bones['eye_mch'] = dict() self.bones['eye_mch']['eyelid_top'] = [] self.bones['eye_mch']['eyelid_bottom'] = [] self.bones['eye_mch']['eye_master'] = '' self.bones['eye_mch']['eye_master_tip'] = '' main_bone_name = strip_org(self.bones['org'][0]) eye_mch_name = make_mechanism_name(main_bone_name) eye_mch_name = copy_bone(self.obj, self.bones['org'][0], eye_mch_name) self.bones['eye_mch']['eye_master'] = eye_mch_name eye_tip_mch_name = copy_bone(self.obj, self.orientation_bone, eye_mch_name) self.bones['eye_mch']['eye_master_tip'] = eye_tip_mch_name put_bone(self.obj, eye_tip_mch_name, edit_bones[eye_mch_name].tail) if self.orientation_bone == self.base_bone: align_bone_y_axis(self.obj, eye_tip_mch_name, Vector((0, 0, 1))) edit_bones[ eye_tip_mch_name].length = 0.25 * edit_bones[eye_mch_name].length # top lid top_lid_chain = self.get_chain_bones(self.lid_bones['top'][0]) for l_b in top_lid_chain: lid_m_name = copy_bone(self.obj, self.bones['org'][0], eye_mch_name) edit_bones[lid_m_name].tail = edit_bones[l_b].tail self.bones['eye_mch']['eyelid_top'].append(lid_m_name) # bottom lid bottom_lid_chain = self.get_chain_bones(self.lid_bones['bottom'][0]) for l_b in bottom_lid_chain: lid_m_name = copy_bone(self.obj, self.bones['org'][0], eye_mch_name) edit_bones[lid_m_name].tail = edit_bones[l_b].tail self.bones['eye_mch']['eyelid_bottom'].append(lid_m_name) # create mch for eye_follow driver if self.needs_driver: if self.paired_eye or self.is_clustered(): eye_follow_mch = self.get_common_name() else: eye_follow_mch = strip_org(self.base_bone) eye_follow_mch = make_mechanism_name(eye_follow_mch) eye_follow_mch += "_parent" if eye_follow_mch not in edit_bones: parent = edit_bones[self.base_bone].parent.name eye_follow_mch = copy_bone(self.obj, parent, eye_follow_mch) edit_bones[ eye_follow_mch].length = 0.25 * edit_bones[parent].length self.bones['eye_mch']['eyefollow'] = eye_follow_mch super().create_mch()
def create_pivot(self, pivot=None): """ Create the pivot control and mechanism bones """ org_bones = self.org_bones bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones if not pivot: pivot = int(len(org_bones) / 2) pivot_name = org_bones[pivot] if '.L' in pivot_name: prefix = strip_org(org_bones[pivot]).split('.')[0] + '.L' elif '.R' in pivot_name: prefix = strip_org(org_bones[pivot]).split('.')[0] + '.R' else: prefix = strip_org(org_bones[pivot]).split('.')[0] ctrl_name = get_bone_name(prefix, 'ctrl', 'pivot') ctrl_name = copy_bone(self.obj, pivot_name, ctrl_name) ctrl_eb = eb[ctrl_name] self.orient_bone(ctrl_eb, 'y', self.spine_length / 2.5) pivot_loc = eb[pivot_name].head + ( (eb[pivot_name].tail - eb[pivot_name].head) / 2) * (len(org_bones) % 2) put_bone(self.obj, ctrl_name, pivot_loc) v = eb[org_bones[-1]].tail - eb[org_bones[ 0]].head # Create a vector from head of first ORG to tail of last v.normalize() v_proj = eb[org_bones[0]].y_axis.dot( v) * v # projection of first ORG to v v_point = eb[org_bones[ 0]].y_axis - v_proj # a vector co-planar to first ORG and v directed out of the chain if v_point.magnitude < eb[org_bones[ 0]].y_axis.magnitude * 1e-03: # if v_point is too small it's not usable v_point = eb[org_bones[0]].x_axis if self.params.tweak_axis == 'auto': align_bone_y_axis(self.obj, ctrl_name, v) align_bone_z_axis(self.obj, ctrl_name, -v_point) elif self.params.tweak_axis == 'x': align_bone_y_axis(self.obj, ctrl_name, Vector((1, 0, 0))) align_bone_x_axis(self.obj, ctrl_name, Vector((0, 0, 1))) elif self.params.tweak_axis == 'y': align_bone_y_axis(self.obj, ctrl_name, Vector((0, 1, 0))) align_bone_x_axis(self.obj, ctrl_name, Vector((1, 0, 0))) elif self.params.tweak_axis == 'z': align_bone_y_axis(self.obj, ctrl_name, Vector((0, 0, 1))) align_bone_x_axis(self.obj, ctrl_name, Vector((1, 0, 0))) return {'ctrl': ctrl_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 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 == 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(shin)) ) 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 childrenconnected) attached to bone '%s'" % (strip_org(bone), strip_org(shin)) ) # 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 -- toe is None" % (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 cleanup(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones # cleanup for mch in self.bones['mch'][strip_org(self.lid_bones['top'][0])]: edit_bones.remove(edit_bones[mch]) for mch in self.bones['mch'][strip_org(self.lid_bones['bottom'][0])]: edit_bones.remove(edit_bones[mch])
def create_mch(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones main_bone_name = strip_org(self.bones['org'][0]) mouth_lock_name = make_mechanism_name(main_bone_name + "_lock") mouth_lock = copy_bone(self.obj, self.main_mch, mouth_lock_name) self.bones['jaw_mch'] = dict() self.bones['jaw_mch']['mouth_lock'] = mouth_lock self.bones['jaw_mch']['jaw_masters'] = [] jaw_masters_number = 3 for i in range(0, jaw_masters_number): jaw_m_name = make_mechanism_name("jaw_master") jaw_m = copy_bone(self.obj, self.main_mch, jaw_m_name) div_len = (edit_bones[mouth_lock].length/(jaw_masters_number + 1)) edit_bones[jaw_m].length = (jaw_masters_number - i) * div_len edit_bones[jaw_m].use_connect = False self.bones['jaw_mch']['jaw_masters'].append(jaw_m) self.bones['mouth_mch'] = dict() org_top = self.mouth_bones['top'][0] top_mch_name = make_mechanism_name(strip_org(org_top)) top_mch = copy_bone(self.obj, org_top, top_mch_name) self.bones['mouth_mch']['top'] = [top_mch] edit_bones[top_mch].use_connect = False self.bones['mouth_mch']['corners'] = [] for org_name in self.mouth_bones['corners']: mch_name = make_mechanism_name(strip_org(org_name)) mch = copy_bone(self.obj, org_name, mch_name) self.bones['mouth_mch']['corners'].append(mch) edit_bones[mch].use_connect = False org_bottom = self.mouth_bones['bottom'][0] bottom_mch_name = make_mechanism_name(strip_org(org_bottom)) bottom_mch = copy_bone(self.obj, org_bottom, bottom_mch_name) self.bones['mouth_mch']['bottom'] = [bottom_mch] edit_bones[bottom_mch].use_connect = False mbs = self.flatten(self.bones['mouth_mch']) mouth_center = edit_bones[mbs[0]].head for b in mbs[1:]: mouth_center = mouth_center + edit_bones[b].head mouth_center = mouth_center / len(mbs) for b in self.flatten(self.bones['mouth_mch']): put_bone(self.obj, b, mouth_center) # create remaining subchain mch-s super().create_mch()
def parent_bones(self): """ Parent jaw bones :return: """ bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones # Parenting to jaw MCHs jaw_masters = self.bones['jaw_mch']['jaw_masters'] b_lip_1 = strip_org( self.mouth_bones['bottom'][0]) # 1st bottom lip quarter b_lip_2 = strip_org(self.mouth_bones['bottom'][1]) for i, lip_def in enumerate(self.bones['def'][b_lip_1]): lip_def_eb = edit_bones[lip_def] lip_ctrl = self.get_ctrl_by_index(b_lip_1, i) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i]] if lip_def == self.bones['def'][b_lip_1][-1]: lip_ctrl = self.get_ctrl_by_index(b_lip_1, i + 1) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i + 1]] for i, lip_def in enumerate(self.bones['def'][b_lip_2]): lip_def_eb = edit_bones[lip_def] lip_ctrl = self.get_ctrl_by_index(b_lip_2, i) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i]] if lip_def == self.bones['def'][b_lip_2][-1]: lip_ctrl = self.get_ctrl_by_index(b_lip_2, i + 1) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i + 1]] t_lip_1 = strip_org(self.mouth_bones['top'][0]) # 1st top lip quarter t_lip_2 = strip_org(self.mouth_bones['top'][1]) for i, lip_def in enumerate(self.bones['def'][t_lip_1]): lip_def_eb = edit_bones[lip_def] lip_ctrl = self.get_ctrl_by_index(t_lip_1, i) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[-2]] if lip_def == self.bones['def'][t_lip_1][-1]: lip_ctrl = self.get_ctrl_by_index(t_lip_1, i + 1) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i + 1]] for i, lip_def in enumerate(self.bones['def'][t_lip_2]): lip_def_eb = edit_bones[lip_def] lip_ctrl = self.get_ctrl_by_index(t_lip_2, i) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[-2]] if lip_def == self.bones['def'][t_lip_2][-1]: lip_ctrl = self.get_ctrl_by_index(t_lip_2, i + 1) edit_bones[lip_ctrl].parent = edit_bones[jaw_masters[i + 1]] # parenting what's connected to main jaw mch to jaw ctrl for child in edit_bones[self.main_mch].children: child.parent = edit_bones[self.bones['jaw_ctrl']['jaw']] super().parent_bones()
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 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 rig parameters self.use_thigh_twist = params.use_thigh_twist self.use_shin_twist = params.use_shin_twist
def gen_deform(self): """ Generate the deformation rig. """ for name in self.org_bones: bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones # Create deform bone bone_e = eb[copy_bone(self.obj, name)] # Change its name bone_e.name = make_deformer_name(strip_org(name)) bone_name = bone_e.name # Leave edit mode bpy.ops.object.mode_set(mode='OBJECT') # Get the pose bone bone = self.obj.pose.bones[bone_name] # Constrain to the original bone con = bone.constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = name
def cleanup(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones for mch in self.bones['mch'][strip_org(self.base_bone)]: if mch not in self.bones['tongue_mch']['tongue_tip']: edit_bones.remove(edit_bones[mch])
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): """ 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 __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 generate(self): bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones bones = {} if eb[self.org_bones[0]].parent: def_name = make_deformer_name( strip_org(eb[self.org_bones[0]].parent.name)) if self.params.def_parenting and def_name in eb.keys(): bones['parent'] = def_name else: bones['parent'] = eb[self.org_bones[0]].parent.name # Clear parents for org bones for bone in self.org_bones[0:]: eb[bone].use_connect = False eb[bone].parent = None bones['def'], bones['conv_def'] = self.create_deform() if len(self.org_bones) > 2: bones['pivot'] = self.create_pivot() bones['chain'] = self.create_chain() self.parent_bones(bones) # ctrls snapping pass self.aggregate_ctrls(bones) self.constrain_bones(bones) self.stick_to_bendy_bones(bones) self.locks_and_widgets(bones) return
def create_mch(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones super().create_mch() self.bones['tail_mch'] = {} org_chain = self.get_chain_bones(self.base_bone) if edit_bones[org_chain[0]].parent: bone_to_copy = edit_bones[org_chain[0]].parent.name else: bone_to_copy = self.orientation_bone mch_rot_tail = make_mechanism_name('ROT-' + strip_org(self.base_bone)) mch_rot_tail = copy_bone(self.obj, bone_to_copy, assign_name=mch_rot_tail) self.bones['tail_mch']['rot_tail_mch'] = mch_rot_tail main_chain = self.get_chain_bones(self.base_bone) flip_bone(self.obj, mch_rot_tail) edit_bones[mch_rot_tail].parent = None put_bone(self.obj, mch_rot_tail, edit_bones[main_chain[0]].head)
def make_mch_chain(self): """ Create all MCHs needed on a single chain :return: :rtype: list """ if not self.active: return [] bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones chain = self._bones['org'] self._bones['mch'] = [] if self.chain_type == ChainType.TYPE_MCH_BASED: for chain_bone in chain: mch = make_mechanism_name(strip_org(chain_bone)) mch = copy_bone(self.obj, chain_bone, assign_name=mch) edit_bones[mch].parent = None edit_bones[mch].use_connect = False edit_bones[mch].length *= self.MCH_SCALE self._bones['mch'].append(mch) return self._bones['mch']
def __init__(self, obj, base_bone, orientation_bone=None, chain_type=None, parent=None): """ :param obj: :param base_bone: :param orientation_bone: :param chain_type: :type chain_type: ChainType :param parent: :type parent: Chain """ self.chain_type = chain_type or ChainType.TYPE_MCH_BASED self.obj = obj self._base_bone = base_bone self.base_name = strip_org(self._base_bone) self.orientation_bone = orientation_bone or self._base_bone self.parent = parent self._bones = dict() self._bones['org'] = self._get_chain_org_bones() self.active = True
def make_def_chain(self): """ Creates all DEFs in chain :return: :rtype:list """ if not self.active: return [] bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones chain = self._bones['org'] self._bones['def'] = [] if self.chain_type == ChainType.TYPE_MCH_BASED: for chain_bone in chain: def_bone = make_deformer_name(strip_org(chain_bone)) def_bone = copy_bone(self.obj, chain_bone, assign_name=def_bone) edit_bones[def_bone].parent = None edit_bones[def_bone].use_connect = False self._bones['def'].append(def_bone) return self._bones['def']
def __init__(self, obj, bone, params): """ Gather and validate data about the rig. """ self.obj = obj self.org_bone = bone self.org_name = strip_org(bone) self.params = params
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, 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 create_mch(self): bpy.ops.object.mode_set(mode='EDIT') edit_bones = self.obj.data.edit_bones main_bone_name = strip_org(self.bones['org'][0]) mouth_lock_name = make_mechanism_name(main_bone_name + "_lock") mouth_lock = copy_bone(self.obj, self.main_mch, mouth_lock_name) self.bones['jaw_mch'] = dict() self.bones['jaw_mch']['mouth_lock'] = mouth_lock self.bones['jaw_mch']['jaw_masters'] = [] jaw_masters_number = self.lip_len + 3 for i in range(0, jaw_masters_number): jaw_m_name = make_mechanism_name("jaw_master") jaw_m = copy_bone(self.obj, self.main_mch, jaw_m_name) div_len = (edit_bones[mouth_lock].length / (jaw_masters_number + 1)) edit_bones[jaw_m].length = (jaw_masters_number - i) * div_len edit_bones[jaw_m].use_connect = False self.bones['jaw_mch']['jaw_masters'].append(jaw_m) # create remaining subchain mch-s super().create_mch()
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 make_constraints(self): """ Make constraints :return: """ bpy.ops.object.mode_set(mode='OBJECT') pose_bones = self.obj.pose.bones owner = pose_bones[self.bones['jaw_mch']['mouth_lock']] subtarget = self.bones['jaw_ctrl']['jaw'] make_constraints_from_string(owner, self.obj, subtarget, "CT0.2WW0.0") influence_div = 1 / len(self.bones['jaw_mch']['jaw_masters']) for i, j_m in enumerate(self.bones['jaw_mch']['jaw_masters']): owner = pose_bones[j_m] subtarget = self.bones['jaw_ctrl']['jaw'] influence = 1 - i * influence_div make_constraints_from_string(owner, self.obj, subtarget, "CT%sWW0.0" % influence) if j_m != self.bones['jaw_mch']['jaw_masters'][-1]: owner = pose_bones[j_m] subtarget = self.bones['jaw_mch']['mouth_lock'] make_constraints_from_string(owner, self.obj, subtarget, "CT0.0WW0.0") # add limits on upper_lip jaw_master if j_m == self.bones['jaw_mch']['jaw_masters'][-2]: make_constraints_from_string(owner, self.obj, "", "LLmY0mZ0#LRmX0MX%f" % (3.14 / 2)) lip_bones = [] lip_bones.extend(self.mouth_bones['top']) lip_bones.extend(self.mouth_bones['bottom']) for lip_bone in lip_bones: lip_bone = strip_org(lip_bone) total_len = 0 influence_share = [] for def_b in self.bones['def'][lip_bone]: total_len += pose_bones[def_b].length influence_share.append(total_len) influence_share = [val / total_len for val in influence_share] for i, ctrl in enumerate(self.bones['ctrl'][lip_bone][1:-1]): owner = pose_bones[self.bones['ctrl'][lip_bone][i + 1]] subtarget = self.bones['ctrl'][lip_bone][-1] infl = influence_share[i] make_constraints_from_string(owner, self.obj, subtarget, "CL%sLLO0.0" % infl) subtarget = self.bones['ctrl'][lip_bone][0] infl = 1 - influence_share[i] make_constraints_from_string(owner, self.obj, subtarget, "CL%sLLO0.0" % infl) make_constraints_from_string(owner, self.obj, subtarget, "CR1.0LLO0.0") make_constraints_from_string(owner, self.obj, subtarget, "CS1.0LLO0.0") # make the standard bendy rig constraints super().make_constraints()
def remove_chains(self, remove_list): for bone in remove_list: base_name = strip_org(bone) if base_name in self.chain_objects: del self.chain_objects[base_name] if bone in self.chains: del self.chains[bone]
def get_common_name(self): """ Returns an aggregate name for an eyes pair :return: :rtype: str """ cluster = [] if self.is_clustered(): cluster = self.get_cluster_names() else: base = strip_org(self.base_bone) pair = strip_org(self.paired_eye) cluster = [base, pair] return self.control_snapper.get_aggregate_name(cluster)
def get_chain_object_by_name(self, name): """ returns a chain object by the name of the first org w/o ORG prefix :return: :rtype: Chain """ name = strip_org(name) return self.chain_objects[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 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 generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') make_rocker = False if self.org_bones[5] is not None: make_rocker = True # Create the bones thigh = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik")))) shin = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik")))) foot = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik"))) foot_ik_target = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[2], "_ik_target")))) pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole"))) toe = copy_bone(self.obj, self.org_bones[3], strip_org(self.org_bones[3])) toe_parent = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".parent"))) toe_parent_socket1 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket1"))) toe_parent_socket2 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket2"))) foot_roll = copy_bone(self.obj, self.org_bones[4], strip_org(insert_before_lr(self.org_bones[2], "_roll"))) roll1 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.01"))) roll2 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.02"))) if make_rocker: rocker1 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.01"))) rocker2 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.02"))) visfoot = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik"))) vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole"))) # Get edit bones eb = self.obj.data.edit_bones org_foot_e = eb[self.org_bones[2]] thigh_e = eb[thigh] shin_e = eb[shin] foot_e = eb[foot] foot_ik_target_e = eb[foot_ik_target] pole_e = eb[pole] toe_e = eb[toe] toe_parent_e = eb[toe_parent] toe_parent_socket1_e = eb[toe_parent_socket1] toe_parent_socket2_e = eb[toe_parent_socket2] foot_roll_e = eb[foot_roll] roll1_e = eb[roll1] roll2_e = eb[roll2] if make_rocker: rocker1_e = eb[rocker1] rocker2_e = eb[rocker2] visfoot_e = eb[visfoot] vispole_e = eb[vispole] # Parenting shin_e.parent = thigh_e foot_e.use_connect = False foot_e.parent = None foot_ik_target_e.use_connect = False foot_ik_target_e.parent = roll2_e pole_e.use_connect = False pole_e.parent = foot_e toe_e.parent = toe_parent_e toe_parent_e.use_connect = False toe_parent_e.parent = toe_parent_socket1_e toe_parent_socket1_e.use_connect = False toe_parent_socket1_e.parent = roll1_e toe_parent_socket2_e.use_connect = False toe_parent_socket2_e.parent = eb[self.org_bones[2]] foot_roll_e.use_connect = False foot_roll_e.parent = foot_e roll1_e.use_connect = False roll1_e.parent = foot_e roll2_e.use_connect = False roll2_e.parent = roll1_e visfoot_e.use_connect = False visfoot_e.parent = None vispole_e.use_connect = False vispole_e.parent = None if make_rocker: rocker1_e.use_connect = False rocker2_e.use_connect = False roll1_e.parent = rocker2_e rocker2_e.parent = rocker1_e rocker1_e.parent = foot_e # Misc foot_e.use_local_location = False visfoot_e.hide_select = True vispole_e.hide_select = True # Positioning vec = Vector(toe_e.vector) vec.normalize() foot_e.tail = foot_e.head + (vec * foot_e.length) foot_e.roll = toe_e.roll v1 = shin_e.tail - thigh_e.head if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis: v2 = v1.cross(shin_e.x_axis) if (v2 * shin_e.z_axis) > 0.0: v2 *= -1.0 else: v2 = v1.cross(shin_e.z_axis) if (v2 * shin_e.x_axis) < 0.0: v2 *= -1.0 v2.normalize() v2 *= v1.length if '-' in self.primary_rotation_axis: v2 *= -1 pole_e.head = shin_e.head + v2 pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8)) pole_e.roll = 0.0 flip_bone(self.obj, toe_parent_socket1) flip_bone(self.obj, toe_parent_socket2) toe_parent_socket1_e.head = Vector(org_foot_e.tail) toe_parent_socket2_e.head = Vector(org_foot_e.tail) toe_parent_socket1_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 2) toe_parent_socket2_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 3) toe_parent_socket2_e.roll = toe_parent_socket1_e.roll tail = Vector(roll1_e.tail) roll1_e.tail = Vector(org_foot_e.tail) roll1_e.tail = Vector(org_foot_e.tail) roll1_e.head = tail roll2_e.head = Vector(org_foot_e.tail) foot_roll_e.head = Vector(org_foot_e.tail) put_bone(self.obj, foot_roll, roll1_e.head) foot_roll_e.length /= 2 roll_axis = roll1_e.vector.cross(org_foot_e.vector) align_x_axis(self.obj, roll1, roll_axis) align_x_axis(self.obj, roll2, roll_axis) foot_roll_e.roll = roll2_e.roll visfoot_e.tail = visfoot_e.head + Vector((0, 0, v1.length / 32)) vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32)) if make_rocker: d = toe_e.y_axis.dot(rocker1_e.x_axis) if d >= 0.0: flip_bone(self.obj, rocker2) else: flip_bone(self.obj, rocker1) # Weird alignment issues. Fix. toe_parent_e.head = Vector(org_foot_e.head) toe_parent_e.tail = Vector(org_foot_e.tail) toe_parent_e.roll = org_foot_e.roll foot_e.head = Vector(org_foot_e.head) foot_ik_target_e.head = Vector(org_foot_e.head) foot_ik_target_e.tail = Vector(org_foot_e.tail) # Determine the pole offset value plane = (shin_e.tail - thigh_e.head).normalized() vec1 = thigh_e.x_axis.normalized() vec2 = (pole_e.head - thigh_e.head).normalized() pole_offset = angle_on_plane(plane, vec1, vec2) # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # thigh_p = pb[thigh] # UNUSED shin_p = pb[shin] foot_p = pb[foot] pole_p = pb[pole] foot_roll_p = pb[foot_roll] roll1_p = pb[roll1] roll2_p = pb[roll2] if make_rocker: rocker1_p = pb[rocker1] rocker2_p = pb[rocker2] toe_p = pb[toe] toe_parent_p = pb[toe_parent] toe_parent_socket1_p = pb[toe_parent_socket1] visfoot_p = pb[visfoot] vispole_p = pb[vispole] # Set the knee to only bend on the primary axis. if 'X' in self.primary_rotation_axis: shin_p.lock_ik_y = True shin_p.lock_ik_z = True elif 'Y' in self.primary_rotation_axis: shin_p.lock_ik_x = True shin_p.lock_ik_z = True else: shin_p.lock_ik_x = True shin_p.lock_ik_y = True # Foot roll control only rotates on x-axis, or x and y if rocker. foot_roll_p.rotation_mode = 'XYZ' if make_rocker: foot_roll_p.lock_rotation = False, False, True else: foot_roll_p.lock_rotation = False, True, True foot_roll_p.lock_location = True, True, True foot_roll_p.lock_scale = True, True, True # roll and rocker bones set to euler rotation roll1_p.rotation_mode = 'XYZ' roll2_p.rotation_mode = 'XYZ' if make_rocker: rocker1_p.rotation_mode = 'XYZ' rocker2_p.rotation_mode = 'XYZ' # Pole target only translates pole_p.lock_location = False, False, False pole_p.lock_rotation = True, True, True pole_p.lock_rotation_w = True pole_p.lock_scale = True, True, True # Set up custom properties if self.switch == True: prop = rna_idprop_ui_prop_get(foot_p, "ikfk_switch", create=True) foot_p["ikfk_switch"] = 0.0 prop["soft_min"] = prop["min"] = 0.0 prop["soft_max"] = prop["max"] = 1.0 # Bend direction hint if self.bend_hint: con = shin_p.constraints.new('LIMIT_ROTATION') con.name = "bend_hint" con.owner_space = 'LOCAL' if self.primary_rotation_axis == 'X': con.use_limit_x = True con.min_x = pi / 10 con.max_x = pi / 10 elif self.primary_rotation_axis == '-X': con.use_limit_x = True con.min_x = -pi / 10 con.max_x = -pi / 10 elif self.primary_rotation_axis == 'Y': con.use_limit_y = True con.min_y = pi / 10 con.max_y = pi / 10 elif self.primary_rotation_axis == '-Y': con.use_limit_y = True con.min_y = -pi / 10 con.max_y = -pi / 10 elif self.primary_rotation_axis == 'Z': con.use_limit_z = True con.min_z = pi / 10 con.max_z = pi / 10 elif self.primary_rotation_axis == '-Z': con.use_limit_z = True con.min_z = -pi / 10 con.max_z = -pi / 10 # IK Constraint con = shin_p.constraints.new('IK') con.name = "ik" con.target = self.obj con.subtarget = foot_ik_target con.pole_target = self.obj con.pole_subtarget = pole con.pole_angle = pole_offset con.chain_count = 2 # toe_parent constraint con = toe_parent_socket1_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = toe_parent_socket2 con = toe_parent_socket1_p.constraints.new('COPY_SCALE') con.name = "copy_scale" con.target = self.obj con.subtarget = toe_parent_socket2 con = toe_parent_socket1_p.constraints.new('COPY_TRANSFORMS') # drive with IK switch con.name = "fk" con.target = self.obj con.subtarget = toe_parent_socket2 fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]' mod = fcurve.modifiers[0] mod.poly_order = 1 mod.coefficients[0] = 1.0 mod.coefficients[1] = -1.0 # Foot roll drivers fcurve = roll1_p.driver_add("rotation_euler", 0) driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' driver.expression = "min(0,var)" var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]' fcurve = roll2_p.driver_add("rotation_euler", 0) driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' driver.expression = "max(0,var)" var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]' if make_rocker: fcurve = rocker1_p.driver_add("rotation_euler", 0) driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' driver.expression = "max(0,-var)" var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]' fcurve = rocker2_p.driver_add("rotation_euler", 0) driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' driver.expression = "max(0,var)" var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]' # Constrain org bones to controls con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = thigh if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]' con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = shin if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]' con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = foot_ik_target if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]' con = pb[self.org_bones[3]].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = toe # VIS foot constraints con = visfoot_p.constraints.new('COPY_LOCATION') con.name = "copy_loc" con.target = self.obj con.subtarget = self.org_bones[2] con = visfoot_p.constraints.new('STRETCH_TO') con.name = "stretch_to" con.target = self.obj con.subtarget = foot con.volume = 'NO_VOLUME' con.rest_length = visfoot_p.length # VIS pole constraints con = vispole_p.constraints.new('COPY_LOCATION') con.name = "copy_loc" con.target = self.obj con.subtarget = self.org_bones[1] con = vispole_p.constraints.new('STRETCH_TO') con.name = "stretch_to" con.target = self.obj con.subtarget = pole con.volume = 'NO_VOLUME' con.rest_length = vispole_p.length # Set layers if specified if self.layers: foot_p.bone.layers = self.layers pole_p.bone.layers = self.layers foot_roll_p.bone.layers = self.layers visfoot_p.bone.layers = self.layers vispole_p.bone.layers = self.layers toe_p.bone.layers = [(i[0] or i[1]) for i in zip(toe_p.bone.layers, self.layers)] # Both FK and IK layers # Create widgets create_line_widget(self.obj, vispole) create_line_widget(self.obj, visfoot) create_sphere_widget(self.obj, pole) create_circle_widget(self.obj, toe, radius=0.7, head_tail=0.5) ob = create_widget(self.obj, foot) if ob != None: verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 ob = create_widget(self.obj, foot_roll) if ob != None: verts = [(0.3999999761581421, 0.766044557094574, 0.6427875757217407), (0.17668449878692627, 3.823702598992895e-08, 3.2084670920085046e-08), (-0.17668461799621582, 9.874240447516058e-08, 8.285470443070153e-08), (-0.39999961853027344, 0.7660449147224426, 0.6427879333496094), (0.3562471270561218, 0.6159579753875732, 0.5168500542640686), (-0.35624682903289795, 0.6159582138061523, 0.5168502926826477), (0.20492683351039886, 0.09688037633895874, 0.0812922865152359), (-0.20492687821388245, 0.0968804731965065, 0.08129236847162247)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (1, 6), (4, 6), (2, 7), (5, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 return [thigh, shin, foot, pole, foot_roll, foot_ik_target]
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 __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 generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create the control bones uarm = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0])) farm = copy_bone(self.obj, self.org_bones[1], strip_org(self.org_bones[1])) hand = copy_bone(self.obj, self.org_bones[2], strip_org(self.org_bones[2])) # Create the hinge bones if self.org_parent != None: hinge = copy_bone(self.obj, self.org_parent, make_mechanism_name(uarm + ".hinge")) socket1 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket1")) socket2 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket2")) # Get edit bones eb = self.obj.data.edit_bones uarm_e = eb[uarm] farm_e = eb[farm] hand_e = eb[hand] if self.org_parent != None: hinge_e = eb[hinge] socket1_e = eb[socket1] socket2_e = eb[socket2] # Parenting farm_e.parent = uarm_e hand_e.parent = farm_e if self.org_parent != None: hinge_e.use_connect = False socket1_e.use_connect = False socket2_e.use_connect = False uarm_e.parent = hinge_e hinge_e.parent = socket2_e socket2_e.parent = None # Positioning if self.org_parent != None: center = (hinge_e.head + hinge_e.tail) / 2 hinge_e.head = center socket1_e.length /= 4 socket2_e.length /= 3 # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones uarm_p = pb[uarm] farm_p = pb[farm] hand_p = pb[hand] if self.org_parent != None: hinge_p = pb[hinge] if self.org_parent != None: # socket1_p = pb[socket1] # UNUSED socket2_p = pb[socket2] # Set the elbow to only bend on the x-axis. farm_p.rotation_mode = 'XYZ' if 'X' in self.primary_rotation_axis: farm_p.lock_rotation = (False, True, True) elif 'Y' in self.primary_rotation_axis: farm_p.lock_rotation = (True, False, True) else: farm_p.lock_rotation = (True, True, False) # Hinge transforms are locked, for auto-ik if self.org_parent != None: hinge_p.lock_location = True, True, True hinge_p.lock_rotation = True, True, True hinge_p.lock_rotation_w = True hinge_p.lock_scale = True, True, True # Set up custom properties if self.org_parent != None: prop = rna_idprop_ui_prop_get(uarm_p, "isolate", create=True) uarm_p["isolate"] = 0.0 prop["soft_min"] = prop["min"] = 0.0 prop["soft_max"] = prop["max"] = 1.0 # Hinge constraints / drivers if self.org_parent != None: con = socket2_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = socket1 con = socket2_p.constraints.new('COPY_TRANSFORMS') con.name = "isolate_off" con.target = self.obj con.subtarget = socket1 # Driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = uarm_p.path_from_id() + '["isolate"]' mod = fcurve.modifiers[0] mod.poly_order = 1 mod.coefficients[0] = 1.0 mod.coefficients[1] = -1.0 # Constrain org bones to controls con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = uarm con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = farm con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS') con.name = "fk" con.target = self.obj con.subtarget = hand # Set layers if specified if self.layers: uarm_p.bone.layers = self.layers farm_p.bone.layers = self.layers hand_p.bone.layers = self.layers # Create control widgets create_limb_widget(self.obj, uarm) create_limb_widget(self.obj, farm) ob = create_widget(self.obj, hand) if ob != None: verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 return [uarm, farm, hand]
def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create upper arm bones if self.use_thigh_twist: thigh1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01"))) thigh2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02"))) utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip"))) else: thigh = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0]))) # Create forearm bones if self.use_shin_twist: shin1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01"))) shin2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02"))) stip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip"))) else: shin = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1]))) # Create foot bone foot = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2]))) # Create toe bone toe = copy_bone(self.obj, self.org_bones[3], make_deformer_name(strip_org(self.org_bones[3]))) # Get edit bones eb = self.obj.data.edit_bones org_thigh_e = eb[self.org_bones[0]] if self.use_thigh_twist: thigh1_e = eb[thigh1] thigh2_e = eb[thigh2] utip_e = eb[utip] else: thigh_e = eb[thigh] org_shin_e = eb[self.org_bones[1]] if self.use_shin_twist: shin1_e = eb[shin1] shin2_e = eb[shin2] stip_e = eb[stip] else: shin_e = eb[shin] org_foot_e = eb[self.org_bones[2]] foot_e = eb[foot] org_toe_e = eb[self.org_bones[3]] toe_e = eb[toe] # Parent and position thigh bones if self.use_thigh_twist: thigh1_e.use_connect = False thigh2_e.use_connect = False utip_e.use_connect = False thigh1_e.parent = org_thigh_e.parent thigh2_e.parent = org_thigh_e utip_e.parent = org_thigh_e center = Vector((org_thigh_e.head + org_thigh_e.tail) / 2) thigh1_e.tail = center thigh2_e.head = center put_bone(self.obj, utip, org_thigh_e.tail) utip_e.length = org_thigh_e.length / 8 else: thigh_e.use_connect = False thigh_e.parent = org_thigh_e # Parent and position shin bones if self.use_shin_twist: shin1_e.use_connect = False shin2_e.use_connect = False stip_e.use_connect = False shin1_e.parent = org_shin_e shin2_e.parent = org_shin_e stip_e.parent = org_shin_e center = Vector((org_shin_e.head + org_shin_e.tail) / 2) shin1_e.tail = center shin2_e.head = center put_bone(self.obj, stip, org_shin_e.tail) stip_e.length = org_shin_e.length / 8 # Align roll of shin2 with foot align_roll(self.obj, shin2, foot) else: shin_e.use_connect = False shin_e.parent = org_shin_e # Parent foot foot_e.use_connect = False foot_e.parent = org_foot_e # Parent toe toe_e.use_connect = False toe_e.parent = org_toe_e # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones if self.use_thigh_twist: thigh1_p = pb[thigh1] if self.use_shin_twist: shin2_p = pb[shin2] # foot_p = pb[foot] # UNUSED # Thigh constraints if self.use_thigh_twist: con = thigh1_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = self.org_bones[0] con = thigh1_p.constraints.new('COPY_SCALE') con.name = "copy_scale" con.target = self.obj con.subtarget = self.org_bones[0] con = thigh1_p.constraints.new('DAMPED_TRACK') con.name = "track_to" con.target = self.obj con.subtarget = utip # Shin constraints if self.use_shin_twist: con = shin2_p.constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = foot con = shin2_p.constraints.new('DAMPED_TRACK') con.name = "track_to" con.target = self.obj con.subtarget = stip
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 generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Figure out the name for the control bone (remove the last .##) last_bone = self.org_bones[-1:][0] ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1] # Make control bone ctrl = copy_bone(self.obj, last_bone, ctrl_name) # Make deformation bones def_bones = [] for bone in self.org_bones: b = copy_bone(self.obj, bone, deformer(strip_org(bone))) def_bones += [b] # Parenting eb = self.obj.data.edit_bones for d, b in zip(def_bones, self.org_bones): eb[d].use_connect = False eb[d].parent = eb[b] # Constraints bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones i = 0 div = len(self.org_bones) - 1 for b in self.org_bones: con = pb[b].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = ctrl con.target_space = 'LOCAL' con.owner_space = 'LOCAL' con.influence = i / div con = pb[b].constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = ctrl con.target_space = 'LOCAL' con.owner_space = 'LOCAL' if 'X' in self.palm_rotation_axis: con.invert_x = True con.use_x = True con.use_z = False else: con.invert_z = True con.use_x = False con.use_z = True con.use_y = False con.influence = (i / div) - (1 - cos((i * pi / 2) / div)) i += 1 # Create control widget w = create_widget(self.obj, ctrl) if w != None: mesh = w.data verts = [(0.15780271589756012, 2.086162567138672e-07, -0.30000004172325134), (0.15780259668827057, 1.0, -0.2000001072883606), (-0.15780280530452728, 0.9999999403953552, -0.20000004768371582), (-0.15780259668827057, -2.086162567138672e-07, -0.29999998211860657), (-0.15780256688594818, -2.7089754439657554e-07, 0.30000004172325134), (-0.1578027755022049, 0.9999998807907104, 0.19999995827674866), (0.15780262649059296, 0.9999999403953552, 0.19999989867210388), (0.1578027456998825, 1.4633496903115883e-07, 0.29999998211860657), (0.15780268609523773, 0.2500001788139343, -0.27500003576278687), (-0.15780264139175415, 0.24999985098838806, -0.2749999761581421), (0.15780262649059296, 0.7500000596046448, -0.22500008344650269), (-0.1578027606010437, 0.7499998807907104, -0.2250000238418579), (0.15780265629291534, 0.75, 0.22499991953372955), (0.15780271589756012, 0.2500000596046448, 0.2749999761581421), (-0.15780261158943176, 0.2499997615814209, 0.27500003576278687), (-0.1578027307987213, 0.7499998807907104, 0.22499997913837433)] if 'Z' in self.palm_rotation_axis: # Flip x/z coordinates temp = [] for v in verts: temp += [(v[2], v[1], v[0])] verts = temp edges = [(1, 2), (0, 3), (4, 7), (5, 6), (8, 0), (9, 3), (10, 1), (11, 2), (12, 6), (13, 7), (4, 14), (15, 5), (10, 8), (11, 9), (15, 14), (12, 13)] mesh.from_pydata(verts, edges, []) mesh.update() mod = w.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2
def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create the bones uarm = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik")))) farm = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik")))) hand = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik"))) pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole"))) vishand = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik"))) vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole"))) # Get edit bones eb = self.obj.data.edit_bones uarm_e = eb[uarm] farm_e = eb[farm] hand_e = eb[hand] pole_e = eb[pole] vishand_e = eb[vishand] vispole_e = eb[vispole] # Parenting farm_e.parent = uarm_e hand_e.use_connect = False hand_e.parent = None pole_e.use_connect = False vishand_e.use_connect = False vishand_e.parent = None vispole_e.use_connect = False vispole_e.parent = None # Misc hand_e.use_local_location = False vishand_e.hide_select = True vispole_e.hide_select = True # Positioning v1 = farm_e.tail - uarm_e.head if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis: v2 = v1.cross(farm_e.x_axis) if (v2 * farm_e.z_axis) > 0.0: v2 *= -1.0 else: v2 = v1.cross(farm_e.z_axis) if (v2 * farm_e.x_axis) < 0.0: v2 *= -1.0 v2.normalize() v2 *= v1.length if '-' in self.primary_rotation_axis: v2 *= -1 pole_e.head = farm_e.head + v2 pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8)) pole_e.roll = 0.0 vishand_e.tail = vishand_e.head + Vector((0, 0, v1.length / 32)) vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32)) # Determine the pole offset value plane = (farm_e.tail - uarm_e.head).normalized() vec1 = uarm_e.x_axis.normalized() vec2 = (pole_e.head - uarm_e.head).normalized() pole_offset = angle_on_plane(plane, vec1, vec2) # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # uarm_p = pb[uarm] # UNUSED farm_p = pb[farm] hand_p = pb[hand] pole_p = pb[pole] vishand_p = pb[vishand] vispole_p = pb[vispole] # Set the elbow to only bend on the primary axis if 'X' in self.primary_rotation_axis: farm_p.lock_ik_y = True farm_p.lock_ik_z = True elif 'Y' in self.primary_rotation_axis: farm_p.lock_ik_x = True farm_p.lock_ik_z = True else: farm_p.lock_ik_x = True farm_p.lock_ik_y = True # Pole target only translates pole_p.lock_location = False, False, False pole_p.lock_rotation = True, True, True pole_p.lock_rotation_w = True pole_p.lock_scale = True, True, True # Set up custom properties if self.switch == True: prop = rna_idprop_ui_prop_get(hand_p, "ikfk_switch", create=True) hand_p["ikfk_switch"] = 0.0 prop["soft_min"] = prop["min"] = 0.0 prop["soft_max"] = prop["max"] = 1.0 # Bend direction hint if self.bend_hint: con = farm_p.constraints.new('LIMIT_ROTATION') con.name = "bend_hint" con.owner_space = 'LOCAL' if self.primary_rotation_axis == 'X': con.use_limit_x = True con.min_x = pi / 10 con.max_x = pi / 10 elif self.primary_rotation_axis == '-X': con.use_limit_x = True con.min_x = -pi / 10 con.max_x = -pi / 10 elif self.primary_rotation_axis == 'Y': con.use_limit_y = True con.min_y = pi / 10 con.max_y = pi / 10 elif self.primary_rotation_axis == '-Y': con.use_limit_y = True con.min_y = -pi / 10 con.max_y = -pi / 10 elif self.primary_rotation_axis == 'Z': con.use_limit_z = True con.min_z = pi / 10 con.max_z = pi / 10 elif self.primary_rotation_axis == '-Z': con.use_limit_z = True con.min_z = -pi / 10 con.max_z = -pi / 10 # IK Constraint con = farm_p.constraints.new('IK') con.name = "ik" con.target = self.obj con.subtarget = hand con.pole_target = self.obj con.pole_subtarget = pole con.pole_angle = pole_offset con.chain_count = 2 # Constrain org bones to controls con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = uarm if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]' con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = farm if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]' con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS') con.name = "ik" con.target = self.obj con.subtarget = hand if self.switch == True: # IK/FK switch driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "var" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]' # VIS hand constraints con = vishand_p.constraints.new('COPY_LOCATION') con.name = "copy_loc" con.target = self.obj con.subtarget = self.org_bones[2] con = vishand_p.constraints.new('STRETCH_TO') con.name = "stretch_to" con.target = self.obj con.subtarget = hand con.volume = 'NO_VOLUME' con.rest_length = vishand_p.length # VIS pole constraints con = vispole_p.constraints.new('COPY_LOCATION') con.name = "copy_loc" con.target = self.obj con.subtarget = self.org_bones[1] con = vispole_p.constraints.new('STRETCH_TO') con.name = "stretch_to" con.target = self.obj con.subtarget = pole con.volume = 'NO_VOLUME' con.rest_length = vispole_p.length # Set layers if specified if self.layers: hand_p.bone.layers = self.layers pole_p.bone.layers = self.layers vishand_p.bone.layers = self.layers vispole_p.bone.layers = self.layers # Create widgets create_line_widget(self.obj, vispole) create_line_widget(self.obj, vishand) create_sphere_widget(self.obj, pole) ob = create_widget(self.obj, hand) if ob != None: verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 return [uarm, farm, hand, pole]
def gen_control(self): """ Generate the control rig. """ #--------------------------------- # Create the neck and head controls bpy.ops.object.mode_set(mode='EDIT') # Create bones neck_ctrl = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0])) neck_follow = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[0] + ".follow"))) neck_child = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[0] + ".child"))) head_ctrl = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1])) head_mch = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[-1]))) if self.isolate: head_socket1 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket1"))) head_socket2 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket2"))) # Create neck chain bones neck = [] helpers = [] for name in self.org_bones: neck += [copy_bone(self.obj, name, make_mechanism_name(strip_org(name)))] helpers += [copy_bone(self.obj, neck_child, make_mechanism_name(strip_org(name + ".02")))] # Fetch edit bones eb = self.obj.data.edit_bones neck_ctrl_e = eb[neck_ctrl] neck_follow_e = eb[neck_follow] neck_child_e = eb[neck_child] head_ctrl_e = eb[head_ctrl] head_mch_e = eb[head_mch] if self.isolate: head_socket1_e = eb[head_socket1] head_socket2_e = eb[head_socket2] # Parenting head_ctrl_e.use_connect = False head_ctrl_e.parent = neck_ctrl_e.parent head_mch_e.use_connect = False head_mch_e.parent = head_ctrl_e if self.isolate: head_socket1_e.use_connect = False head_socket1_e.parent = neck_ctrl_e.parent head_socket2_e.use_connect = False head_socket2_e.parent = None head_ctrl_e.parent = head_socket2_e for (name1, name2) in zip(neck, helpers): eb[name1].use_connect = False eb[name1].parent = eb[name2] eb[name2].use_connect = False eb[name2].parent = neck_ctrl_e.parent neck_follow_e.use_connect = False neck_follow_e.parent = neck_ctrl_e.parent neck_child_e.use_connect = False neck_child_e.parent = neck_ctrl_e neck_ctrl_e.parent = neck_follow_e # Position put_bone(self.obj, neck_follow, neck_ctrl_e.head) put_bone(self.obj, neck_child, neck_ctrl_e.head) put_bone(self.obj, head_ctrl, neck_ctrl_e.head) put_bone(self.obj, head_mch, neck_ctrl_e.head) head_mch_e.length = head_ctrl_e.length / 2 neck_child_e.length = neck_ctrl_e.length / 2 if self.isolate: put_bone(self.obj, head_socket1, neck_ctrl_e.head) head_mch_e.length /= 2 put_bone(self.obj, head_socket2, neck_ctrl_e.head) head_mch_e.length /= 3 for (name1, name2) in zip(neck, helpers): put_bone(self.obj, name2, eb[name1].head) eb[name2].length = eb[name1].length / 2 # Switch to object mode bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones neck_ctrl_p = pb[neck_ctrl] neck_follow_p = pb[neck_follow] # neck_child_p = pb[neck_child] # UNUSED head_ctrl_p = pb[head_ctrl] if self.isolate: # head_socket1_p = pb[head_socket1] # UNUSED head_socket2_p = pb[head_socket2] # Custom bone appearance neck_ctrl_p.custom_shape_transform = pb[self.org_bones[(len(self.org_bones) - 1) // 2]] head_ctrl_p.custom_shape_transform = pb[self.org_bones[-1]] # Custom properties prop = rna_idprop_ui_prop_get(head_ctrl_p, "inf_extent", create=True) head_ctrl_p["inf_extent"] = 0.5 prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 prop = rna_idprop_ui_prop_get(head_ctrl_p, "neck_follow", create=True) head_ctrl_p["neck_follow"] = 1.0 prop["min"] = 0.0 prop["max"] = 2.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 if self.isolate: prop = rna_idprop_ui_prop_get(head_ctrl_p, "isolate", create=True) head_ctrl_p["isolate"] = 0.0 prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 # Constraints # Neck follow con = neck_follow_p.constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = head_ctrl fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' var.name = "follow" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = head_ctrl_p.path_from_id() + '["neck_follow"]' driver.expression = "follow / 2" # Isolate if self.isolate: con = head_socket2_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = head_socket1 con = head_socket2_p.constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = head_socket1 fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' var.name = "isolate" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = head_ctrl_p.path_from_id() + '["isolate"]' driver.expression = "1.0 - isolate" # Neck chain first = True prev = None i = 0 l = len(neck) for (name1, name2, org_name) in zip(neck, helpers, self.org_bones): con = pb[org_name].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = name1 n_con = pb[name2].constraints.new('COPY_TRANSFORMS') n_con.name = "neck" n_con.target = self.obj n_con.subtarget = neck_child h_con = pb[name2].constraints.new('COPY_TRANSFORMS') h_con.name = "head" h_con.target = self.obj h_con.subtarget = head_mch con = pb[name2].constraints.new('COPY_LOCATION') con.name = "anchor" con.target = self.obj if first: con.subtarget = neck_ctrl else: con.subtarget = prev con.head_tail = 1.0 # Drivers n = (i + 1) / l # Neck influence fcurve = n_con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' var.name = "ext" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]' driver.expression = "1.0 if (%.4f > (1.0-ext) or (1.0-ext) == 0.0) else (%.4f / (1.0-ext))" % (n, n) # Head influence if (i + 1) == l: h_con.influence = 1.0 else: fcurve = h_con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'SCRIPTED' var.name = "ext" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]' driver.expression = "0.0 if (%.4f <= (1.0-ext)) else ((%.4f - (1.0-ext)) / ext)" % (n, n) first = False prev = name1 i += 1 # Create control widgets w1 = create_circle_widget(self.obj, neck_ctrl, radius=1.0, head_tail=0.5) w2 = create_circle_widget(self.obj, head_ctrl, radius=1.0, head_tail=0.5) if w1 != None: obj_to_bone(w1, self.obj, self.org_bones[(len(self.org_bones) - 1) // 2]) if w2 != None: obj_to_bone(w2, self.obj, self.org_bones[-1]) # Return control bones return (head_ctrl, neck_ctrl)
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. """ 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_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 __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 gen_control(self): """ Generate the control rig. """ bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones #------------------------- # Get rest slide position a = self.pivot_rest * len(self.org_bones) i = floor(a) a -= i if i == len(self.org_bones): i -= 1 a = 1.0 pivot_rest_pos = eb[self.org_bones[i]].head.copy() pivot_rest_pos += eb[self.org_bones[i]].vector * a #---------------------- # Create controls # Create control bones controls = [] for i in self.control_indices: name = copy_bone(self.obj, self.org_bones[i], strip_org(self.org_bones[i])) controls += [name] # Create control parents control_parents = [] for i in self.control_indices[1:-1]: name = new_bone(self.obj, make_mechanism_name("par_" + strip_org(self.org_bones[i]))) control_parents += [name] # Create sub-control bones subcontrols = [] for i in self.control_indices: name = new_bone(self.obj, make_mechanism_name("sub_" + strip_org(self.org_bones[i]))) subcontrols += [name] # Create main control bone main_control = new_bone(self.obj, self.params.spine_main_control_name) # Create main control WGT bones main_wgt1 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".01")) main_wgt2 = new_bone(self.obj, make_mechanism_name(self.params.spine_main_control_name + ".02")) eb = self.obj.data.edit_bones # Parent the main control eb[main_control].use_connect = False eb[main_control].parent = eb[self.org_bones[0]].parent # Parent the main WGTs eb[main_wgt1].use_connect = False eb[main_wgt1].parent = eb[main_control] eb[main_wgt2].use_connect = False eb[main_wgt2].parent = eb[main_wgt1] # Parent the controls and sub-controls for name, subname in zip(controls, subcontrols): eb[name].use_connect = False eb[name].parent = eb[main_control] eb[subname].use_connect = False eb[subname].parent = eb[name] # Parent the control parents for name, par_name in zip(controls[1:-1], control_parents): eb[par_name].use_connect = False eb[par_name].parent = eb[main_control] eb[name].parent = eb[par_name] # Position the main bone put_bone(self.obj, main_control, pivot_rest_pos) eb[main_control].length = sum([eb[b].length for b in self.org_bones]) / 2 # Position the main WGTs eb[main_wgt1].tail = (0.0, 0.0, sum([eb[b].length for b in self.org_bones]) / 4) eb[main_wgt2].length = sum([eb[b].length for b in self.org_bones]) / 4 put_bone(self.obj, main_wgt1, pivot_rest_pos) put_bone(self.obj, main_wgt2, pivot_rest_pos) # Position the controls and sub-controls pos = eb[controls[0]].head.copy() for name, subname in zip(controls, subcontrols): put_bone(self.obj, name, pivot_rest_pos) put_bone(self.obj, subname, pivot_rest_pos) eb[subname].length = eb[name].length / 3 # Position the control parents for name, par_name in zip(controls[1:-1], control_parents): put_bone(self.obj, par_name, pivot_rest_pos) eb[par_name].length = eb[name].length / 2 #----------------------------------------- # Control bone constraints and properties bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Lock control locations for name in controls: bone = pb[name] bone.lock_location = True, True, True # Main control doesn't use local location pb[main_control].bone.use_local_location = False # Intermediate controls follow hips and spine for name, par_name, i in zip(controls[1:-1], control_parents, self.control_indices[1:-1]): bone = pb[par_name] # Custom bend_alpha property prop = rna_idprop_ui_prop_get(pb[name], "bend_alpha", create=True) pb[name]["bend_alpha"] = i / (len(self.org_bones) - 1) # set bend alpha prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 # Custom auto_rotate prop = rna_idprop_ui_prop_get(pb[name], "auto_rotate", create=True) pb[name]["auto_rotate"] = 1.0 prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 # Constraints con1 = bone.constraints.new('COPY_TRANSFORMS') con1.name = "copy_transforms" con1.target = self.obj con1.subtarget = subcontrols[0] con2 = bone.constraints.new('COPY_TRANSFORMS') con2.name = "copy_transforms" con2.target = self.obj con2.subtarget = subcontrols[-1] # Drivers fcurve = con1.driver_add("influence") driver = fcurve.driver driver.type = 'AVERAGE' var = driver.variables.new() var.name = "auto" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]' fcurve = con2.driver_add("influence") driver = fcurve.driver driver.type = 'SCRIPTED' driver.expression = "alpha * auto" var = driver.variables.new() var.name = "alpha" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = pb[name].path_from_id() + '["bend_alpha"]' var = driver.variables.new() var.name = "auto" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]' #------------------------- # Create flex spine chain bpy.ops.object.mode_set(mode='EDIT') flex_bones = [] flex_subs = [] prev_bone = None for b in self.org_bones: # Create bones bone = copy_bone(self.obj, b, make_mechanism_name(strip_org(b) + ".flex")) sub = new_bone(self.obj, make_mechanism_name(strip_org(b) + ".flex_s")) flex_bones += [bone] flex_subs += [sub] eb = self.obj.data.edit_bones bone_e = eb[bone] sub_e = eb[sub] # Parenting bone_e.use_connect = False sub_e.use_connect = False if prev_bone is None: sub_e.parent = eb[controls[0]] else: sub_e.parent = eb[prev_bone] bone_e.parent = sub_e # Position put_bone(self.obj, sub, bone_e.head) sub_e.length = bone_e.length / 4 if prev_bone is not None: sub_e.use_connect = True prev_bone = bone #---------------------------- # Create reverse spine chain # Create bones/parenting/positioning bpy.ops.object.mode_set(mode='EDIT') rev_bones = [] prev_bone = None for b in zip(flex_bones, self.org_bones): # Create bones bone = copy_bone(self.obj, b[1], make_mechanism_name(strip_org(b[1]) + ".reverse")) rev_bones += [bone] eb = self.obj.data.edit_bones bone_e = eb[bone] # Parenting bone_e.use_connect = False bone_e.parent = eb[b[0]] # Position flip_bone(self.obj, bone) bone_e.tail = Vector(eb[b[0]].head) #bone_e.head = Vector(eb[b[0]].tail) if prev_bone is None: put_bone(self.obj, bone, pivot_rest_pos) else: put_bone(self.obj, bone, eb[prev_bone].tail) prev_bone = bone # Constraints bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones prev_bone = None for bone in rev_bones: bone_p = pb[bone] con = bone_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj if prev_bone is None: con.subtarget = main_control else: con.subtarget = prev_bone con.head_tail = 1.0 prev_bone = bone #---------------------------------------- # Constrain original bones to flex spine bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones for obone, fbone in zip(self.org_bones, flex_bones): con = pb[obone].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = fbone #--------------------------- # Create pivot slide system pb = self.obj.pose.bones bone_p = pb[self.org_bones[0]] main_control_p = pb[main_control] # Custom pivot_slide property prop = rna_idprop_ui_prop_get(main_control_p, "pivot_slide", create=True) main_control_p["pivot_slide"] = self.pivot_rest prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 1.0 / len(self.org_bones) prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones)) # Anchor constraints con = bone_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = rev_bones[0] con = pb[main_wgt1].constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = rev_bones[0] # Slide constraints i = 1 tot = len(rev_bones) for rb in rev_bones: con = bone_p.constraints.new('COPY_LOCATION') con.name = "slide." + str(i) con.target = self.obj con.subtarget = rb con.head_tail = 1.0 # Driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "slide" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = main_control_p.path_from_id() + '["pivot_slide"]' mod = fcurve.modifiers[0] mod.poly_order = 1 mod.coefficients[0] = 1 - i mod.coefficients[1] = tot # Main WGT con = pb[main_wgt1].constraints.new('COPY_ROTATION') con.name = "slide." + str(i) con.target = self.obj con.subtarget = rb # Driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "slide" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = main_control_p.path_from_id() + '["pivot_slide"]' mod = fcurve.modifiers[0] mod.poly_order = 1 mod.coefficients[0] = 1.5 - i mod.coefficients[1] = tot i += 1 #---------------------------------- # Constrain flex spine to controls bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Constrain the bones that correspond exactly to the controls for i, name in zip(self.control_indices, subcontrols): con = pb[flex_subs[i]].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = name # Constrain the bones in-between the controls for i, j, name1, name2 in zip(self.control_indices, self.control_indices[1:], subcontrols, subcontrols[1:]): if (i + 1) < j: for n in range(i + 1, j): bone = pb[flex_subs[n]] # Custom bend_alpha property prop = rna_idprop_ui_prop_get(bone, "bend_alpha", create=True) bone["bend_alpha"] = (n - i) / (j - i) # set bend alpha prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 con = bone.constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = name1 con = bone.constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = name2 # Driver fcurve = con.driver_add("influence") driver = fcurve.driver var = driver.variables.new() driver.type = 'AVERAGE' var.name = "alpha" var.targets[0].id_type = 'OBJECT' var.targets[0].id = self.obj var.targets[0].data_path = bone.path_from_id() + '["bend_alpha"]' #------------- # Final stuff bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Control appearance # Main pb[main_control].custom_shape_transform = pb[main_wgt2] w = create_compass_widget(self.obj, main_control) if w != None: obj_to_bone(w, self.obj, main_wgt2) # Spines for name, i in zip(controls[1:-1], self.control_indices[1:-1]): pb[name].custom_shape_transform = pb[self.org_bones[i]] # Create control widgets w = create_circle_widget(self.obj, name, radius=1.0, head_tail=0.5, with_line=True) if w != None: obj_to_bone(w, self.obj, self.org_bones[i]) # Hips pb[controls[0]].custom_shape_transform = pb[self.org_bones[0]] # Create control widgets w = create_circle_widget(self.obj, controls[0], radius=1.0, head_tail=0.5, with_line=True) if w != None: obj_to_bone(w, self.obj, self.org_bones[0]) # Ribs pb[controls[-1]].custom_shape_transform = pb[self.org_bones[-1]] # Create control widgets w = create_circle_widget(self.obj, controls[-1], radius=1.0, head_tail=0.5, with_line=True) if w != None: obj_to_bone(w, self.obj, self.org_bones[-1]) # Layers pb[main_control].bone.layers = pb[self.org_bones[0]].bone.layers return [main_control] + controls
def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create the deformation and control bone chains. # Just copies of the original chain. def_chain = [] ctrl_chain = [] for i in range(len(self.org_bones)): name = self.org_bones[i] # Control bone if self.make_controls: # Copy ctrl_bone = copy_bone(self.obj, name) eb = self.obj.data.edit_bones ctrl_bone_e = eb[ctrl_bone] # Name ctrl_bone_e.name = strip_org(name) # Parenting if i == 0: # First bone ctrl_bone_e.parent = eb[self.org_bones[0]].parent else: # The rest ctrl_bone_e.parent = eb[ctrl_chain[-1]] # Add to list ctrl_chain += [ctrl_bone_e.name] else: ctrl_chain += [None] # Deformation bone if self.make_deforms: # Copy def_bone = copy_bone(self.obj, name) eb = self.obj.data.edit_bones def_bone_e = eb[def_bone] # Name def_bone_e.name = make_deformer_name(strip_org(name)) # Parenting if i == 0: # First bone def_bone_e.parent = eb[self.org_bones[0]].parent else: # The rest def_bone_e.parent = eb[def_chain[-1]] # Add to list def_chain += [def_bone_e.name] else: def_chain += [None] bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones # Constraints for org and def for org, ctrl, defrm in zip(self.org_bones, ctrl_chain, def_chain): if self.make_controls: con = pb[org].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = ctrl if self.make_deforms: con = pb[defrm].constraints.new('COPY_TRANSFORMS') con.name = "copy_transforms" con.target = self.obj con.subtarget = org # Create control widgets if self.make_controls: for bone in ctrl_chain: create_bone_widget(self.obj, bone)
def deform(self): """ Generate the deformation rig. Just a copy of the original bones, except the first digit which is a twist bone. """ bpy.ops.object.mode_set(mode="EDIT") # Create the bones # First bone is a twist bone if self.use_digit_twist: b1a = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01"))) b1b = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02"))) b1tip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip"))) else: b1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0]))) # The rest are normal bones = [] for bone in self.org_bones[1:]: bones += [copy_bone(self.obj, bone, make_deformer_name(strip_org(bone)))] # Position bones eb = self.obj.data.edit_bones if self.use_digit_twist: b1a_e = eb[b1a] b1b_e = eb[b1b] b1tip_e = eb[b1tip] b1tip_e.use_connect = False b1tip_e.tail += Vector((0.1, 0, 0)) b1tip_e.head = b1b_e.tail b1tip_e.length = b1a_e.length / 4 center = (b1a_e.head + b1a_e.tail) / 2 b1a_e.tail = center b1b_e.use_connect = False b1b_e.head = center # Parenting if self.use_digit_twist: b1b_e.parent = eb[self.org_bones[0]] b1tip_e.parent = eb[self.org_bones[0]] else: eb[b1].use_connect = False eb[b1].parent = eb[self.org_bones[0]] for (ba, bb) in zip(bones, self.org_bones[1:]): eb[ba].use_connect = False eb[ba].parent = eb[bb] # Constraints if self.use_digit_twist: bpy.ops.object.mode_set(mode="OBJECT") pb = self.obj.pose.bones b1a_p = pb[b1a] con = b1a_p.constraints.new("COPY_LOCATION") con.name = "copy_location" con.target = self.obj con.subtarget = self.org_bones[0] con = b1a_p.constraints.new("COPY_SCALE") con.name = "copy_scale" con.target = self.obj con.subtarget = self.org_bones[0] con = b1a_p.constraints.new("DAMPED_TRACK") con.name = "track_to" con.target = self.obj con.subtarget = b1tip
def control(self): """ Generate the control rig. """ bpy.ops.object.mode_set(mode="EDIT") # Figure out the name for the control bone (remove the last .##) ctrl_name = re.sub("([0-9]+\.)", "", strip_org(self.org_bones[0])[::-1], count=1)[::-1] # Create the bones ctrl = copy_bone(self.obj, self.org_bones[0], ctrl_name) helpers = [] bones = [] for bone in self.org_bones: bones += [copy_bone(self.obj, bone, strip_org(bone))] helpers += [copy_bone(self.obj, bone, make_mechanism_name(strip_org(bone)))] # Position bones eb = self.obj.data.edit_bones length = 0.0 for bone in helpers: length += eb[bone].length eb[bone].length /= 2 eb[ctrl].length = length * 1.5 # Parent bones prev = eb[self.org_bones[0]].parent for (b, h) in zip(bones, helpers): b_e = eb[b] h_e = eb[h] b_e.use_connect = False h_e.use_connect = False b_e.parent = h_e h_e.parent = prev prev = b_e # Transform locks and rotation mode bpy.ops.object.mode_set(mode="OBJECT") pb = self.obj.pose.bones for bone in bones[1:]: pb[bone].lock_location = True, True, True if pb[self.org_bones[0]].bone.use_connect == True: pb[bones[0]].lock_location = True, True, True pb[ctrl].lock_scale = True, False, True for bone in helpers: pb[bone].rotation_mode = "XYZ" # Drivers i = 1 val = 1.2 / (len(self.org_bones) - 1) for bone in helpers: # Add custom prop prop_name = "bend_%02d" % i prop = rna_idprop_ui_prop_get(pb[ctrl], prop_name, create=True) prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 prop["soft_max"] = 1.0 if i == 1: pb[ctrl][prop_name] = 0.0 else: pb[ctrl][prop_name] = val # Add driver if "X" in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 0) elif "Y" in self.primary_rotation_axis: fcurve = pb[bone].driver_add("rotation_euler", 1) else: fcurve = pb[bone].driver_add("rotation_euler", 2) driver = fcurve.driver driver.type = "SCRIPTED" var = driver.variables.new() var.name = "ctrl_y" var.targets[0].id_type = "OBJECT" var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id() + ".scale[1]" var = driver.variables.new() var.name = "bend" var.targets[0].id_type = "OBJECT" var.targets[0].id = self.obj var.targets[0].data_path = pb[ctrl].path_from_id() + '["' + prop_name + '"]' if "-" in self.primary_rotation_axis: driver.expression = "-(1.0-ctrl_y) * bend * 3.14159 * 2" else: driver.expression = "(1.0-ctrl_y) * bend * 3.14159 * 2" i += 1 # Constraints con = pb[helpers[0]].constraints.new("COPY_LOCATION") con.name = "copy_location" con.target = self.obj con.subtarget = ctrl con = pb[helpers[0]].constraints.new("COPY_ROTATION") con.name = "copy_rotation" con.target = self.obj con.subtarget = ctrl # Constrain org bones to the control bones for (bone, org) in zip(bones, self.org_bones): con = pb[org].constraints.new("COPY_TRANSFORMS") con.name = "copy_transforms" con.target = self.obj con.subtarget = bone # Set layers for extra control bones if self.ex_layers: for bone in bones: pb[bone].bone.layers = self.ex_layers # Create control widgets w = create_widget(self.obj, ctrl) if w != None: mesh = w.data verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)] if "Z" in self.primary_rotation_axis: # Flip x/z coordinates temp = [] for v in verts: temp += [(v[2], v[1], v[0])] verts = temp edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)] mesh.from_pydata(verts, edges, []) mesh.update() for bone in bones: create_limb_widget(self.obj, bone)
def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ bpy.ops.object.mode_set(mode='EDIT') # Create upper arm bones if self.use_upper_arm_twist: uarm1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01"))) uarm2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02"))) utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip"))) else: uarm = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0]))) # Create forearm bones if self.use_forearm_twist: farm1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01"))) farm2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02"))) ftip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip"))) else: farm = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1]))) # Create hand bone hand = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2]))) # Get edit bones eb = self.obj.data.edit_bones org_uarm_e = eb[self.org_bones[0]] if self.use_upper_arm_twist: uarm1_e = eb[uarm1] uarm2_e = eb[uarm2] utip_e = eb[utip] else: uarm_e = eb[uarm] org_farm_e = eb[self.org_bones[1]] if self.use_forearm_twist: farm1_e = eb[farm1] farm2_e = eb[farm2] ftip_e = eb[ftip] else: farm_e = eb[farm] org_hand_e = eb[self.org_bones[2]] hand_e = eb[hand] # Parent and position upper arm bones if self.use_upper_arm_twist: uarm1_e.use_connect = False uarm2_e.use_connect = False utip_e.use_connect = False uarm1_e.parent = org_uarm_e.parent uarm2_e.parent = org_uarm_e utip_e.parent = org_uarm_e center = Vector((org_uarm_e.head + org_uarm_e.tail) / 2) uarm1_e.tail = center uarm2_e.head = center put_bone(self.obj, utip, org_uarm_e.tail) utip_e.length = org_uarm_e.length / 8 else: uarm_e.use_connect = False uarm_e.parent = org_uarm_e # Parent and position forearm bones if self.use_forearm_twist: farm1_e.use_connect = False farm2_e.use_connect = False ftip_e.use_connect = False farm1_e.parent = org_farm_e farm2_e.parent = org_farm_e ftip_e.parent = org_farm_e center = Vector((org_farm_e.head + org_farm_e.tail) / 2) farm1_e.tail = center farm2_e.head = center put_bone(self.obj, ftip, org_farm_e.tail) ftip_e.length = org_farm_e.length / 8 # Align roll of farm2 with hand align_roll(self.obj, farm2, hand) else: farm_e.use_connect = False farm_e.parent = org_farm_e # Parent hand hand_e.use_connect = False hand_e.parent = org_hand_e # Object mode, get pose bones bpy.ops.object.mode_set(mode='OBJECT') pb = self.obj.pose.bones if self.use_upper_arm_twist: uarm1_p = pb[uarm1] if self.use_forearm_twist: farm2_p = pb[farm2] # hand_p = pb[hand] # UNUSED # Upper arm constraints if self.use_upper_arm_twist: con = uarm1_p.constraints.new('COPY_LOCATION') con.name = "copy_location" con.target = self.obj con.subtarget = self.org_bones[0] con = uarm1_p.constraints.new('COPY_SCALE') con.name = "copy_scale" con.target = self.obj con.subtarget = self.org_bones[0] con = uarm1_p.constraints.new('DAMPED_TRACK') con.name = "track_to" con.target = self.obj con.subtarget = utip # Forearm constraints if self.use_forearm_twist: con = farm2_p.constraints.new('COPY_ROTATION') con.name = "copy_rotation" con.target = self.obj con.subtarget = hand con = farm2_p.constraints.new('DAMPED_TRACK') con.name = "track_to" con.target = self.obj con.subtarget = ftip
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 is 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 is True: toe = b.name # Get the 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] # 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 rig parameters if "layers" in params: self.layers = get_layers(params["layers"]) else: self.layers = None self.primary_rotation_axis = params.primary_rotation_axis