Changeset View
Changeset View
Standalone View
Standalone View
rigify/rigs/experimental/super_chain.py
| import bpy | import bpy | ||||
| from mathutils import Vector | from mathutils import Vector | ||||
| from ...utils import copy_bone, put_bone, org, align_bone_y_axis, align_bone_x_axis, align_bone_z_axis | from ...utils import copy_bone, put_bone, org, align_bone_y_axis, align_bone_x_axis, align_bone_z_axis | ||||
| from ...utils import strip_org, make_deformer_name, connected_children_names | from ...utils import strip_org, make_deformer_name, connected_children_names | ||||
| from ...utils import create_chain_widget | from ...utils import create_chain_widget | ||||
| from ...utils import make_mechanism_name, create_cube_widget | from ...utils import make_mechanism_name | ||||
| from ...utils import ControlLayersOption | from ...utils import ControlLayersOption | ||||
| from ...utils.mechanism import make_property, make_driver | from rna_prop_ui import rna_idprop_ui_prop_get | ||||
| from ..limbs.limb_utils import get_bone_name | from ..limbs.limb_utils import get_bone_name | ||||
| class Rig: | class Rig: | ||||
| def __init__(self, obj, bone_name, params): | def __init__(self, obj, bone_name, params): | ||||
| """ Chain with pivot Rig """ | """ Chain with pivot Rig """ | ||||
| eb = obj.data.edit_bones | eb = obj.data.bones | ||||
| self.obj = obj | self.obj = obj | ||||
| self.org_bones = [bone_name] + connected_children_names(obj, bone_name) | self.org_bones = [bone_name] + connected_children_names(obj, bone_name) | ||||
| self.params = params | self.params = params | ||||
| self.spine_length = sum([eb[b].length for b in self.org_bones]) | self.spine_length = sum([eb[b].length for b in self.org_bones]) | ||||
| self.bbones = params.bbones | self.bbones = params.bbones | ||||
| self.SINGLE_BONE = (len(self.org_bones) == 1) | self.SINGLE_BONE = (len(self.org_bones) == 1) | ||||
| ▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | def create_deform(self): | ||||
| if not self.SINGLE_BONE: | if not self.SINGLE_BONE: | ||||
| self.obj.data.bones[def_bones[0]].bbone_easein = 0.0 | self.obj.data.bones[def_bones[0]].bbone_easein = 0.0 | ||||
| self.obj.data.bones[def_bones[-1]].bbone_easeout = 0.0 | self.obj.data.bones[def_bones[-1]].bbone_easeout = 0.0 | ||||
| else: | else: | ||||
| self.obj.data.bones[def_bones[0]].bbone_easein = 1.0 | self.obj.data.bones[def_bones[0]].bbone_easein = 1.0 | ||||
| self.obj.data.bones[def_bones[-1]].bbone_easeout = 1.0 | self.obj.data.bones[def_bones[-1]].bbone_easeout = 1.0 | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| return def_bones | 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 create_chain(self): | def create_chain(self): | ||||
| org_bones = self.org_bones | org_bones = self.org_bones | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| eb = self.obj.data.edit_bones | eb = self.obj.data.edit_bones | ||||
| twk, mch, mch_ctrl, ctrl = [], [], [], [] | twk, mch, mch_ctrl, ctrl = [], [], [], [] | ||||
| Show All 16 Lines | def create_chain(self): | ||||
| # Intermediary bones | # Intermediary bones | ||||
| for b in org_bones: # All | for b in org_bones: # All | ||||
| if self.SINGLE_BONE: | if self.SINGLE_BONE: | ||||
| mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | ||||
| eb[mch_name].length /= 4 | eb[mch_name].length /= 4 | ||||
| put_bone(self.obj, mch_name, eb[b].head - (eb[mch_name].tail - eb[mch_name].head)) | put_bone(self.obj, mch_name, eb[b].head - (eb[mch_name].tail - eb[mch_name].head)) | ||||
| align_bone_z_axis(self.obj, mch_name, eb[b].z_axis) | align_bone_z_axis(self.obj, mch_name, eb[b].z_axis) | ||||
| if '.' in mch_name: | |||||
| mch_rev_name = mch_name.split('.')[0] + '_reverse.' + mch_name.split('.')[1] | |||||
| else: | |||||
| mch_rev_name = mch_name + '_reverse' | |||||
| mch_rev_name = copy_bone(self.obj, org(b), mch_rev_name) | |||||
| eb[mch_rev_name].length /= 4 | |||||
| eb[mch_rev_name].tail = eb[mch_name].head | |||||
| align_bone_z_axis(self.obj, mch_rev_name, eb[b].z_axis) | |||||
| mch += [mch_name] | mch += [mch_name] | ||||
| mch += [mch_rev_name] | mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | ||||
| eb[mch_name].length /= 4 | |||||
| put_bone(self.obj, mch_name, eb[b].tail) | |||||
| mch += [mch_name] | |||||
| break | break | ||||
| else: | |||||
| mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | ||||
| eb[mch_name].length /= 4 | eb[mch_name].length /= 4 | ||||
| mch += [mch_name] | mch += [mch_name] | ||||
| if b == org_bones[-1]: # Add extra | if b == org_bones[-1]: # Add extra | ||||
| mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b))) | ||||
| eb[mch_name].length /= 4 | eb[mch_name].length /= 4 | ||||
| put_bone(self.obj, mch_name, eb[b].tail) | put_bone(self.obj, mch_name, eb[b].tail) | ||||
| mch += [mch_name] | mch += [mch_name] | ||||
| # Tweak & Ctrl bones | # Tweak & Ctrl bones | ||||
| v = eb[org_bones[-1]].tail - eb[org_bones[0]].head # Create a vector from head of first ORG to tail of last | 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.normalize() | ||||
| v_proj = eb[org_bones[0]].y_axis.dot(v)*v # projection of first ORG to v | 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 | 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.magnitude < eb[org_bones[0]].y_axis.magnitude*1e-03: | ||||
| v_point = eb[org_bones[0]].x_axis | v_point = eb[org_bones[0]].x_axis | ||||
| for b in org_bones: # All | for b in org_bones: # All | ||||
| suffix = '' | suffix = '' | ||||
| if '.L' in b: | if '.L' in b: | ||||
| suffix = '.L' | suffix = '.L' | ||||
| elif '.R' in b: | elif '.R' in b: | ||||
| suffix = '.R' | suffix = '.R' | ||||
| if b == org_bones[0]: | if b == org_bones[0]: | ||||
| name = get_bone_name(b.split('.')[0] + suffix, 'ctrl', 'ctrl') | name = get_bone_name(b.split('.')[0] + suffix, 'ctrl', 'ctrl') | ||||
| name = copy_bone(self.obj, org(b), name) | name = copy_bone(self.obj, org(b), name) | ||||
| align_bone_x_axis(self.obj, name, eb[org(b)].x_axis) | align_bone_x_axis(self.obj, name, eb[org(b)].x_axis) | ||||
| ctrl += [name] | ctrl += [name] | ||||
| else: | else: | ||||
| name = get_bone_name(b, 'ctrl', 'tweak') | name = 'tweak_' + strip_org(b) | ||||
| name = copy_bone(self.obj, org(b), name) | name = copy_bone(self.obj, org(b), name) | ||||
| twk += [name] | twk += [name] | ||||
| self.orient_bone(eb[name], 'y', eb[name].length / 2) | self.orient_bone(eb[name], 'y', eb[name].length / 2) | ||||
| if self.params.tweak_axis == 'auto': | if self.params.tweak_axis == 'auto': | ||||
| align_bone_y_axis(self.obj, name, v) | align_bone_y_axis(self.obj, name, v) | ||||
| align_bone_z_axis(self.obj, name, -v_point) # invert? | align_bone_z_axis(self.obj, name, -v_point) # invert? | ||||
| Show All 28 Lines | def create_chain(self): | ||||
| align_bone_x_axis(self.obj, ctrl_name, eb[lastname].x_axis) | align_bone_x_axis(self.obj, ctrl_name, eb[lastname].x_axis) | ||||
| put_bone(self.obj, ctrl_name, eb[b].tail) | put_bone(self.obj, ctrl_name, eb[b].tail) | ||||
| ctrl += [ctrl_name] | ctrl += [ctrl_name] | ||||
| conv_twk = '' | conv_twk = '' | ||||
| # Convergence tweak | # Convergence tweak | ||||
| if self.params.conv_bone: | if self.params.conv_bone: | ||||
| conv_twk = get_bone_name(self.params.conv_bone, 'ctrl', 'tweak') | conv_twk = 'tweak_' + strip_org(self.params.conv_bone) | ||||
| if not(conv_twk in eb.keys()): | if not(conv_twk in eb.keys()): | ||||
| conv_twk = copy_bone(self.obj, org(self.params.conv_bone), conv_twk) | conv_twk = copy_bone(self.obj, org(self.params.conv_bone), conv_twk) | ||||
| for b in org_bones: | for b in org_bones: | ||||
| if self.SINGLE_BONE: | |||||
| break | |||||
| # Mch controls | # Mch controls | ||||
| suffix = '' | suffix = '' | ||||
| if '.L' in b: | if '.L' in b: | ||||
| suffix = '.L' | suffix = '.L' | ||||
| elif '.R' in b: | elif '.R' in b: | ||||
| suffix = '.R' | suffix = '.R' | ||||
| mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix | mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix | ||||
| mch_ctrl_name = copy_bone(self.obj, twk[0], mch_ctrl_name) | mch_ctrl_name = copy_bone(self.obj, twk[0] if twk else ctrl[0], mch_ctrl_name) | ||||
| eb[mch_ctrl_name].length /= 6 | eb[mch_ctrl_name].length /= 6 | ||||
| put_bone(self.obj, mch_ctrl_name, eb[b].head) | put_bone(self.obj, mch_ctrl_name, eb[b].head) | ||||
| mch_ctrl += [mch_ctrl_name] | mch_ctrl += [mch_ctrl_name] | ||||
| if b == org_bones[-1]: # Add extra | if b == org_bones[-1]: # Add extra | ||||
| mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix | mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix | ||||
| mch_ctrl_name = copy_bone(self.obj, twk[0], mch_ctrl_name) | mch_ctrl_name = copy_bone(self.obj, twk[0] if twk else ctrl[0], mch_ctrl_name) | ||||
| eb[mch_ctrl_name].length /= 6 | eb[mch_ctrl_name].length /= 6 | ||||
| put_bone(self.obj, mch_ctrl_name, eb[b].tail) | put_bone(self.obj, mch_ctrl_name, eb[b].tail) | ||||
| mch_ctrl += [mch_ctrl_name] | mch_ctrl += [mch_ctrl_name] | ||||
| return { | return { | ||||
| Show All 10 Lines | def parent_bones(self, bones): | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| eb = self.obj.data.edit_bones | eb = self.obj.data.edit_bones | ||||
| # Parent deform bones | # Parent deform bones | ||||
| for i, b in enumerate(bones['def']): | for i, b in enumerate(bones['def']): | ||||
| if i > 0: # For all bones but the first (which has no parent) | if i > 0: # For all bones but the first (which has no parent) | ||||
| eb[b].parent = eb[bones['def'][i-1]] # to previous | eb[b].parent = eb[bones['def'][i-1]] # to previous | ||||
| eb[b].use_connect = True | eb[b].use_connect = True | ||||
| elif self.SINGLE_BONE: | |||||
| eb[b].parent = eb[bones['chain']['mch'][0]] | |||||
| eb[b].use_connect = True | |||||
| # Todo check case when sup_chain is in bigger rig | # Todo check case when sup_chain is in bigger rig | ||||
| eb[bones['def'][0]].parent = eb[bones['chain']['mch'][0]] | eb[bones['def'][0]].parent = eb[bones['chain']['mch'][0]] | ||||
| for i, twk in enumerate(bones['chain']['tweak']): | for i, twk in enumerate(bones['chain']['tweak']): | ||||
| eb[twk].parent = eb[bones['chain']['mch_ctrl'][i+1]] | eb[twk].parent = eb[bones['chain']['mch_ctrl'][i+1]] | ||||
| eb[twk].use_inherit_scale = False | eb[twk].use_inherit_scale = False | ||||
| eb[bones['chain']['ctrl'][0]].parent = eb[bones['chain']['mch_ctrl'][0]] | eb[bones['chain']['ctrl'][0]].parent = eb[bones['chain']['mch_ctrl'][0]] if bones['chain']['mch_ctrl'] else None | ||||
| eb[bones['chain']['ctrl'][0]].use_inherit_scale = False | eb[bones['chain']['ctrl'][0]].use_inherit_scale = False | ||||
| eb[bones['chain']['ctrl'][1]].parent = eb[bones['chain']['mch_ctrl'][-1]] | eb[bones['chain']['ctrl'][1]].parent = eb[bones['chain']['mch_ctrl'][-1]] if bones['chain']['mch_ctrl'] else None | ||||
| eb[bones['chain']['ctrl'][1]].use_inherit_scale = False | eb[bones['chain']['ctrl'][1]].use_inherit_scale = False | ||||
| if 'pivot' in bones.keys(): | if 'pivot' in bones.keys(): | ||||
| eb[bones['pivot']['ctrl']].use_inherit_scale = False | eb[bones['pivot']['ctrl']].use_inherit_scale = False | ||||
| for i, mch in enumerate(bones['chain']['mch']): | for i, mch in enumerate(bones['chain']['mch']): | ||||
| if mch == bones['chain']['mch'][0]: | if mch == bones['chain']['mch'][0]: | ||||
| eb[mch].parent = eb[bones['chain']['ctrl'][0]] | eb[mch].parent = eb[bones['chain']['ctrl'][0]] | ||||
| elif mch == bones['chain']['mch'][-1]: | elif mch == bones['chain']['mch'][-1]: | ||||
| eb[mch].parent = eb[bones['chain']['ctrl'][1]] | eb[mch].parent = eb[bones['chain']['ctrl'][1]] | ||||
| else: | else: | ||||
| eb[mch].parent = eb[bones['chain']['tweak'][i-1]] | eb[mch].parent = eb[bones['chain']['tweak'][i-1]] | ||||
| if 'parent' in bones.keys(): | if 'parent' in bones.keys(): | ||||
| if self.SINGLE_BONE: | |||||
| eb[bones['chain']['ctrl'][0]].parent = eb[bones['parent']] | |||||
| eb[bones['chain']['ctrl'][-1]].parent = eb[bones['parent']] | |||||
| else: | |||||
| eb[bones['chain']['mch_auto']].parent = eb[bones['parent']] | eb[bones['chain']['mch_auto']].parent = eb[bones['parent']] | ||||
| eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['parent']] | eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['parent']] | ||||
| eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['parent']] | eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['parent']] | ||||
| for i, mch_ctrl in enumerate(bones['chain']['mch_ctrl'][1:-1]): | for i, mch_ctrl in enumerate(bones['chain']['mch_ctrl'][1:-1]): | ||||
| eb[mch_ctrl].parent = eb[bones['chain']['mch_auto']] | eb[mch_ctrl].parent = eb[bones['chain']['mch_auto']] | ||||
| if 'pivot' in bones.keys(): | if 'pivot' in bones.keys(): | ||||
| eb[bones['pivot']['ctrl']].parent = eb[bones['chain']['mch_auto']] | eb[bones['pivot']['ctrl']].parent = eb[bones['chain']['mch_auto']] | ||||
| if bones['chain']['conv']: | if bones['chain']['conv']: | ||||
| eb[bones['chain']['ctrl'][-1]].parent = eb[bones['chain']['conv']] | eb[bones['chain']['ctrl'][-1]].parent = eb[bones['chain']['conv']] | ||||
| eb[bones['chain']['conv']].parent = eb[bones['chain']['conv']].parent | |||||
| if self.SINGLE_BONE: | if self.SINGLE_BONE: | ||||
| eb[bones['chain']['ctrl'][0]].parent = None | eb[bones['chain']['mch'][0]].parent = eb[bones['chain']['ctrl'][0]] | ||||
| eb[bones['chain']['ctrl'][-1]].parent = None | eb[bones['chain']['mch'][1]].parent = eb[bones['chain']['ctrl'][1]] | ||||
| eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['chain']['ctrl'][0]] | |||||
| eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['chain']['ctrl'][-1]] | |||||
| eb[bones['chain']['mch'][0]].parent = eb[bones['chain']['mch'][1]] | |||||
| eb[bones['chain']['mch'][1]].parent = eb[bones['chain']['mch_ctrl'][0]] | |||||
| return | return | ||||
| def make_constraint(self, bone, constraint): | def make_constraint(self, bone, constraint): | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| pb = self.obj.pose.bones | pb = self.obj.pose.bones | ||||
| owner_pb = pb[bone] | owner_pb = pb[bone] | ||||
| const = owner_pb.constraints.new(constraint['constraint']) | const = owner_pb.constraints.new(constraint['constraint']) | ||||
| const.target = self.obj | const.target = self.obj | ||||
| # filter constraint props to those that actually exist in the current type of constraint, | # filter constraint props to those that actually exist in the current type of constraint, | ||||
| # then assign values to each | # then assign values to each | ||||
| for p in [k for k in constraint.keys() if k in dir(const)]: | for p in [k for k in constraint.keys() if k in dir(const)]: | ||||
| setattr(const, p, constraint[p]) | setattr(const, p, constraint[p]) | ||||
| def constrain_bones(self, bones): | def constrain_bones(self, bones): | ||||
| # DEF bones | |||||
| deform = bones['def'] | deform = bones['def'] | ||||
| mch = bones['chain']['mch'] | mch = bones['chain']['mch'] | ||||
| mch_ctrl = bones['chain']['mch_ctrl'] | mch_ctrl = bones['chain']['mch_ctrl'] | ||||
| ctrls = bones['chain']['ctrl'] | ctrls = bones['chain']['ctrl'] | ||||
| tweaks = [ctrls[0]] + bones['chain']['tweak'] + [ctrls[-1]] | tweaks = [ctrls[0]] + bones['chain']['tweak'] + [ctrls[-1]] | ||||
| # ORG bones | |||||
| for i, org_bone in enumerate(self.org_bones): | |||||
| self.make_constraint(org_bone, { | |||||
| 'constraint': 'COPY_TRANSFORMS', | |||||
| 'subtarget': tweaks[i], | |||||
| 'owner_space': 'WORLD', | |||||
| 'target_space': 'WORLD' | |||||
| }) | |||||
| # DEF bones | |||||
| for i, d in enumerate(deform): | for i, d in enumerate(deform): | ||||
| if len(deform) > 1: | if len(deform) > 1: | ||||
| self.make_constraint(d, { | self.make_constraint(d, { | ||||
| 'constraint': 'COPY_TRANSFORMS', | 'constraint': 'COPY_TRANSFORMS', | ||||
| 'subtarget': mch[i], | 'subtarget': mch[i], | ||||
| 'owner_space': 'POSE', | 'owner_space': 'POSE', | ||||
| 'target_space': 'POSE' | 'target_space': 'POSE' | ||||
| }) | }) | ||||
| self.make_constraint(d, { | self.make_constraint(d, { | ||||
| 'constraint': 'STRETCH_TO', | 'constraint': 'STRETCH_TO', | ||||
| 'subtarget': tweaks[i+1] | 'subtarget': tweaks[i+1] | ||||
| }) | }) | ||||
| if bones['conv_def']: | |||||
| self.make_constraint(bones['conv_def'], { | |||||
| 'constraint': 'COPY_TRANSFORMS', | |||||
| 'subtarget': bones['chain']['conv'], | |||||
| 'owner_space': 'POSE', | |||||
| 'target_space': 'POSE' | |||||
| }) | |||||
| if 'pivot' in bones.keys(): | if 'pivot' in bones.keys(): | ||||
| step = 2/(len(self.org_bones)) | step = 2/(len(self.org_bones)) | ||||
| for i, b in enumerate(mch_ctrl): | for i, b in enumerate(mch_ctrl): | ||||
| xval = i*step | xval = i*step | ||||
| influence = 2*xval - xval**2 # parabolic influence of pivot | influence = 2*xval - xval**2 # parabolic influence of pivot | ||||
| if (i != 0) and (i != len(mch_ctrl)-1): | if (i != 0) and (i != len(mch_ctrl)-1): | ||||
| self.make_constraint(b, { | self.make_constraint(b, { | ||||
| 'constraint': 'COPY_TRANSFORMS', | 'constraint': 'COPY_TRANSFORMS', | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | def stick_to_bendy_bones(self, bones): | ||||
| if len(deform) > 1: # Only for single bone sup chain | if len(deform) > 1: # Only for single bone sup chain | ||||
| return | return | ||||
| def_pb = pb[deform[0]] | def_pb = pb[deform[0]] | ||||
| ctrl_start = pb[bones['chain']['ctrl'][0]] | ctrl_start = pb[bones['chain']['ctrl'][0]] | ||||
| ctrl_end = pb[bones['chain']['ctrl'][-1]] | ctrl_end = pb[bones['chain']['ctrl'][-1]] | ||||
| mch_start = pb[bones['chain']['mch'][0]] | mch_start = pb[bones['chain']['mch'][0]] | ||||
| mch_end = pb[bones['chain']['mch_ctrl'][-1]] | mch_end = pb[bones['chain']['mch_ctrl'][-1]] if bones['chain']['mch_ctrl'] else pb[bones['chain']['mch'][-1]] | ||||
| if 'bbone_custom_handle_start' in dir(def_pb) and 'bbone_custom_handle_end' in dir(def_pb): | if 'bbone_custom_handle_start' in dir(def_pb) and 'bbone_custom_handle_end' in dir(def_pb): | ||||
| if not self.SINGLE_BONE: | if not self.SINGLE_BONE: | ||||
| def_pb.bbone_custom_handle_start = ctrl_start | def_pb.bbone_custom_handle_start = ctrl_start | ||||
| def_pb.bbone_custom_handle_end = ctrl_end | def_pb.bbone_custom_handle_end = ctrl_end | ||||
| else: | else: | ||||
| def_pb.bbone_custom_handle_start = mch_start | def_pb.bbone_custom_handle_start = mch_start | ||||
| def_pb.bbone_custom_handle_end = mch_end | def_pb.bbone_custom_handle_end = mch_end | ||||
| Show All 40 Lines | def locks_and_widgets(self, bones): | ||||
| for b in bones['chain']['ctrl']: | for b in bones['chain']['ctrl']: | ||||
| pb[b].lock_rotation = True, False, True | pb[b].lock_rotation = True, False, True | ||||
| if 'pivot' in bones.keys(): | if 'pivot' in bones.keys(): | ||||
| pb[bones['pivot']['ctrl']].lock_rotation = True, False, True | pb[bones['pivot']['ctrl']].lock_rotation = True, False, True | ||||
| # Assigning a widget to main ctrl bone | # Assigning a widget to main ctrl bone | ||||
| if 'pivot' in bones.keys(): | if 'pivot' in bones.keys(): | ||||
| create_cube_widget( | create_chain_widget( | ||||
| self.obj, | self.obj, | ||||
| bones['pivot']['ctrl'], | bones['pivot']['ctrl'], | ||||
| cube=True, | |||||
| radius=0.15, | radius=0.15, | ||||
| bone_transform_name=None | bone_transform_name=None, | ||||
| axis=self.params.wgt_align_axis, | |||||
| offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length | |||||
| ) | ) | ||||
| for bone in bones['chain']['tweak']: | for bone in bones['chain']['tweak']: | ||||
| create_cube_widget( | create_chain_widget( | ||||
| self.obj, | self.obj, | ||||
| bone, | bone, | ||||
| cube=True, | |||||
| radius=0.2, | radius=0.2, | ||||
| bone_transform_name=None | bone_transform_name=None, | ||||
| axis=self.params.wgt_align_axis, | |||||
| offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length | |||||
| ) | ) | ||||
| create_chain_widget( | create_chain_widget( | ||||
| self.obj, | self.obj, | ||||
| bones['chain']['ctrl'][0], | bones['chain']['ctrl'][0], | ||||
| invert=False, | invert=False, | ||||
| radius=0.3, | radius=0.3, | ||||
| bone_transform_name=None | bone_transform_name=None, | ||||
| axis=self.params.wgt_align_axis, | |||||
| offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length | |||||
| ) | ) | ||||
| invert_last = True | |||||
| if self.params.wgt_align_axis is not 'y' or '-y': | |||||
| invert_last = False | |||||
| create_chain_widget( | create_chain_widget( | ||||
| self.obj, | self.obj, | ||||
| bones['chain']['ctrl'][-1], | bones['chain']['ctrl'][-1], | ||||
| invert=True, | invert=invert_last, | ||||
| radius=0.3, | radius=0.3, | ||||
| bone_transform_name=None | bone_transform_name=None, | ||||
| axis=self.params.wgt_align_axis, | |||||
| offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length | |||||
| ) | ) | ||||
| if bones['chain']['conv']: | if bones['chain']['conv']: | ||||
| create_cube_widget( | create_chain_widget( | ||||
| self.obj, | self.obj, | ||||
| bones['chain']['conv'], | bones['chain']['conv'], | ||||
| cube=True, | |||||
| radius=0.5, | radius=0.5, | ||||
| bone_transform_name=None | bone_transform_name=None, | ||||
| axis=self.params.wgt_align_axis, | |||||
| offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length | |||||
| ) | ) | ||||
| # Assigning layers to tweaks and ctrls | # Assigning layers to tweaks and ctrls | ||||
| ControlLayersOption.TWEAK.assign(self.params, pb, bones['chain']['tweak']) | ControlLayersOption.TWEAK.assign(self.params, pb, bones['chain']['tweak']) | ||||
| return | return | ||||
| def aggregate_ctrls(self, bones): | |||||
| if not self.params.cluster_ctrls: | |||||
| return | |||||
| other_ctrls = [] | |||||
| all_ctrls = [] | |||||
| eb = self.obj.data.edit_bones | |||||
| head_start = eb[bones['chain']['ctrl'][0]].head | |||||
| head_tip = eb[bones['chain']['ctrl'][-1]].head | |||||
| all_ctrls.extend(bones['chain']['ctrl']) | |||||
| all_ctrls.extend(bones['chain']['tweak']) | |||||
| all_ctrls.extend(bones['chain']['conv']) | |||||
| for bname in eb.keys(): | |||||
| if bname not in all_ctrls and (bname.startswith('tweak') or 'ctrl' in bname): | |||||
| other_ctrls.append(bname) | |||||
| for bname in other_ctrls: | |||||
| if eb[bname].head == head_start: | |||||
| for child in eb[bones['chain']['ctrl'][0]].children: | |||||
| child.parent = eb[bname] | |||||
| eb.remove(eb[bones['chain']['ctrl'][0]]) | |||||
| bones['chain']['ctrl'][0] = bname | |||||
| break | |||||
| for bname in other_ctrls: | |||||
| if eb[bname].head == head_tip: | |||||
| eb.remove(eb[bones['chain']['ctrl'][-1]]) | |||||
| bones['chain']['ctrl'][-1] = bname | |||||
| break | |||||
| def generate(self): | def generate(self): | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| eb = self.obj.data.edit_bones | eb = self.obj.data.edit_bones | ||||
| bones = {} | bones = {} | ||||
| if eb[self.org_bones[0]].parent: | 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 | bones['parent'] = eb[self.org_bones[0]].parent.name | ||||
| # Clear parents for org bones | # Clear parents for org bones | ||||
| for bone in self.org_bones[0:]: | for bone in self.org_bones[0:]: | ||||
| eb[bone].use_connect = False | eb[bone].use_connect = False | ||||
| eb[bone].parent = None | eb[bone].parent = None | ||||
| bones['def'] = self.create_deform() | bones['def'], bones['conv_def'] = self.create_deform() | ||||
| if len(self.org_bones) > 2: | if len(self.org_bones) > 2: | ||||
| bones['pivot'] = self.create_pivot() | bones['pivot'] = self.create_pivot() | ||||
| bones['chain'] = self.create_chain() | bones['chain'] = self.create_chain() | ||||
| self.parent_bones(bones) | self.parent_bones(bones) | ||||
| # ctrls snapping pass | |||||
| self.aggregate_ctrls(bones) | |||||
| self.constrain_bones(bones) | self.constrain_bones(bones) | ||||
| self.stick_to_bendy_bones(bones) | self.stick_to_bendy_bones(bones) | ||||
| self.locks_and_widgets(bones) | self.locks_and_widgets(bones) | ||||
| return | return | ||||
| def add_parameters(params): | def add_parameters(params): | ||||
| """ Add the parameters of this rig type to the | """ Add the parameters of this rig type to the | ||||
| RigifyParameters PropertyGroup | RigifyParameters PropertyGroup | ||||
| """ | """ | ||||
| items = [ | items = [ | ||||
| ('auto', 'Auto', ''), | ('auto', 'Auto', ''), | ||||
| ('x', 'X', ''), | ('x', 'X-Global', ''), | ||||
| ('y', 'Y', ''), | ('y', 'Y-Global', ''), | ||||
| ('z', 'Z', '') | ('z', 'Z-Global', '') | ||||
| ] | ] | ||||
| params.tweak_axis = bpy.props.EnumProperty( | params.tweak_axis = bpy.props.EnumProperty( | ||||
| items=items, | items=items, | ||||
| name="Tweak Axis", | name="Orient y-axis to", | ||||
| description="Targets all ctrls y-axis to defined axis (global space)", | |||||
| default='auto' | default='auto' | ||||
| ) | ) | ||||
| axes = [ | |||||
| ('x', 'X', ''), | |||||
| ('y', 'Y', ''), | |||||
| ('z', 'Z', ''), | |||||
| ('-x', '-X', ''), | |||||
| ('-y', '-Y', ''), | |||||
| ('-z', '-Z', '') | |||||
| ] | |||||
| params.wgt_align_axis = bpy.props.EnumProperty( | |||||
| items=axes, | |||||
| name="Custom Widget orient", | |||||
| description="Targets custom WGTs to defined axis (global space)", | |||||
| default='y' | |||||
| ) | |||||
| params.conv_bone = bpy.props.StringProperty( | params.conv_bone = bpy.props.StringProperty( | ||||
| name='Convergence bone', | name='Convergence bone', | ||||
| default='' | default='' | ||||
| ) | ) | ||||
| params.conv_def = bpy.props.BoolProperty( | |||||
| name="Add DEF on convergence", | |||||
| default=False, | |||||
| description="" | |||||
| ) | |||||
| params.def_parenting = bpy.props.BoolProperty( | |||||
| name="Prefer DEF parenting", | |||||
| default=False, | |||||
| description="" | |||||
| ) | |||||
| params.cluster_ctrls = bpy.props.BoolProperty( | |||||
| name="Cluster controls", | |||||
| default=False, | |||||
| description="Clusterize controls in the same position" | |||||
| ) | |||||
| params.bbones = bpy.props.IntProperty( | params.bbones = bpy.props.IntProperty( | ||||
| name='bbone segments', | name='bbone segments', | ||||
| default=10, | default=10, | ||||
| min=1, | min=1, | ||||
| description='Number of segments' | description='Number of segments' | ||||
| ) | ) | ||||
| params.wgt_offset = bpy.props.FloatProperty( | |||||
| name='Widget Offset', | |||||
| default=0.0, | |||||
| min=-10.0, | |||||
| max=10.0 | |||||
| ) | |||||
| ControlLayersOption.TWEAK.add_parameters(params) | ControlLayersOption.TWEAK.add_parameters(params) | ||||
| def parameters_ui(layout, params): | def parameters_ui(layout, params): | ||||
| """ Create the ui for the rig parameters.""" | """ Create the ui for the rig parameters.""" | ||||
| pb = bpy.context.object.pose | pb = bpy.context.object.pose | ||||
| r = layout.row() | r = layout.row() | ||||
| col = r.column(align=True) | col = r.column(align=True) | ||||
| row = col.row(align=True) | row = col.row(align=True) | ||||
| row.prop(params, "tweak_axis") | row.prop(params, "tweak_axis") | ||||
| r = layout.row() | r = layout.row() | ||||
| r.prop(params, "wgt_align_axis") | |||||
| r = layout.row() | |||||
| r.prop(params, "wgt_offset") | |||||
| r = layout.row() | |||||
| r.prop(params, "bbones") | r.prop(params, "bbones") | ||||
| r = layout.row() | r = layout.row() | ||||
| r.prop_search(params, 'conv_bone', pb, "bones", text="Convergence Bone") | r.prop_search(params, 'conv_bone', pb, "bones", text="Convergence Bone") | ||||
| r = layout.row() | |||||
| r.prop(params, 'conv_def') | |||||
| r = layout.row() | |||||
| r.prop(params, 'def_parenting') | |||||
| r = layout.row() | |||||
| r.prop(params, 'cluster_ctrls') | |||||
| ControlLayersOption.TWEAK.parameters_ui(layout, params) | ControlLayersOption.TWEAK.parameters_ui(layout, params) | ||||
| def create_sample(obj): | def create_sample(obj): | ||||
| # generated by rigify.utils.write_metarig | # generated by rigify.utils.write_metarig | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| arm = obj.data | arm = obj.data | ||||
| ▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines | |||||