diff options
Diffstat (limited to 'rigify/rigs/limbs/arm.py')
-rw-r--r-- | rigify/rigs/limbs/arm.py | 150 |
1 files changed, 105 insertions, 45 deletions
diff --git a/rigify/rigs/limbs/arm.py b/rigify/rigs/limbs/arm.py index 1a560c46..e7e08c41 100644 --- a/rigify/rigs/limbs/arm.py +++ b/rigify/rigs/limbs/arm.py @@ -1,17 +1,17 @@ import bpy, re from ..widgets import create_hand_widget, create_gear_widget -from .ui import create_script -from .limb_utils import * -from mathutils import Vector -from ...utils import copy_bone, flip_bone, put_bone, create_cube_widget -from ...utils import strip_org, make_deformer_name, create_widget -from ...utils import create_circle_widget, create_sphere_widget, create_line_widget -from ...utils import MetarigError, make_mechanism_name, org -from ...utils import create_limb_widget, connected_children_names -from ...utils import align_bone_y_axis -from rna_prop_ui import rna_idprop_ui_prop_get -from ..widgets import create_ikarrow_widget -from math import trunc, pi +from .ui import create_script +from .limb_utils import * +from mathutils import Vector +from ...utils import copy_bone, flip_bone, put_bone, create_cube_widget +from ...utils import strip_org, make_deformer_name, create_widget +from ...utils import create_circle_widget, create_sphere_widget, create_line_widget +from ...utils import MetarigError, make_mechanism_name, org +from ...utils import create_limb_widget, connected_children_names +from ...utils import align_bone_y_axis, align_bone_x_axis, align_bone_z_axis +from rna_prop_ui import rna_idprop_ui_prop_get +from ..widgets import create_ikarrow_widget +from math import trunc, pi extra_script = """ controls = [%s] @@ -19,13 +19,14 @@ ctrl = '%s' if is_selected( controls ): layout.prop( pose_bones[ ctrl ], '["%s"]') - layout.prop( pose_bones[ ctrl ], '["%s"]') + if '%s' in pose_bones[ctrl].keys(): + layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True ) if '%s' in pose_bones[ctrl].keys(): layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True ) """ -IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class - # add_parameters and parameters_ui are unused for implementation classes +IMPLEMENTATION = True # Include and set True if Rig is just an implementation for a wrapper class + # add_parameters and parameters_ui are unused for implementation classes class Rig: @@ -43,6 +44,7 @@ class Rig: self.bbones = params.bbones self.limb_type = params.limb_type self.rot_axis = params.rotation_axis + self.auto_align_extremity = params.auto_align_extremity # Assign values to tweak/FK layers props if opted by user if params.tweak_extra_layers: @@ -55,6 +57,36 @@ class Rig: else: self.fk_layers = None + def orient_org_bones(self): + + bpy.ops.object.mode_set(mode='EDIT') + eb = self.obj.data.edit_bones + + thigh = self.org_bones[0] + org_bones = list( + [thigh] + connected_children_names(self.obj, thigh) + ) # All the provided orgs + + org_uarm = eb[org_bones[0]] + org_farm = eb[org_bones[1]] + org_hand = eb[org_bones[2]] + + if self.rot_axis != 'automatic': + if self.auto_align_extremity: + z_ground_projection = Vector((org_hand.z_axis[0], org_hand.z_axis[1], 0)) + align_bone_z_axis(self.obj, org_hand.name, z_ground_projection.normalized()) + return + + # Orient uarm farm bones + chain_y_axis = org_uarm.y_axis + org_farm.y_axis + chain_rot_axis = org_uarm.y_axis.cross(chain_y_axis).normalized() # ik-plane normal axis (rotation) + + align_bone_x_axis(self.obj, org_uarm.name, chain_rot_axis) + align_bone_x_axis(self.obj, org_farm.name, chain_rot_axis) + + # Orient hand + align_bone_x_axis(self.obj, org_hand.name, chain_rot_axis) + def create_parent(self): org_bones = self.org_bones @@ -350,9 +382,9 @@ class Rig: bpy.ops.object.mode_set(mode ='EDIT') eb = self.obj.data.edit_bones - ctrl = get_bone_name( org_bones[0], 'ctrl', 'ik' ) - mch_ik = get_bone_name( org_bones[0], 'mch', 'ik' ) - mch_target = get_bone_name( org_bones[0], 'mch', 'ik_target' ) + ctrl = get_bone_name(org_bones[0], 'ctrl', 'ik') + mch_ik = get_bone_name(org_bones[0], 'mch', 'ik') + mch_target = get_bone_name(org_bones[0], 'mch', 'ik_target') for o, ik in zip( org_bones, [ ctrl, mch_ik, mch_target ] ): bone = copy_bone( self.obj, o, ik ) @@ -370,9 +402,9 @@ class Rig: eb[ mch_str ].tail = eb[ org_bones[-1] ].head # Parenting - eb[ ctrl ].parent = eb[ parent ] - eb[ mch_str ].parent = eb[ parent ] - eb[ mch_ik ].parent = eb[ ctrl ] + eb[ctrl].parent = eb[parent] + eb[mch_str].parent = eb[parent] + eb[mch_ik].parent = eb[ctrl] # Make standard pole target bone pole_name = get_bone_name(org_bones[0], 'ctrl', 'ik_target') @@ -381,17 +413,25 @@ class Rig: lo_vector = eb[org_bones[1]].tail - eb[org_bones[1]].head tot_vector = eb[org_bones[0]].head - eb[org_bones[1]].tail tot_vector.normalize() - elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as regression of lo on tot + elbow_vector = lo_vector.dot(tot_vector)*tot_vector - lo_vector # elbow_vec as rejection of lo on tot elbow_vector.normalize() elbow_vector *= (eb[org_bones[1]].tail - eb[org_bones[0]].head).length - z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis - alfa = elbow_vector.angle(z_vector) + + if self.rot_axis == 'x' or self.rot_axis == 'automatic': + z_vector = eb[org_bones[0]].z_axis + eb[org_bones[1]].z_axis + alfa = elbow_vector.angle(z_vector) + elif self.rot_axis == 'z': + x_vector = eb[org_bones[0]].x_axis + eb[org_bones[1]].x_axis + alfa = elbow_vector.angle(x_vector) if alfa > pi/2: pole_angle = -pi/2 else: pole_angle = pi/2 + if self.rot_axis == 'z': + pole_angle = 0 + eb[pole_target].head = eb[org_bones[0]].tail + elbow_vector eb[pole_target].tail = eb[pole_target].head - elbow_vector/8 eb[pole_target].roll = 0.0 @@ -441,21 +481,28 @@ class Rig: pb[ ctrl ].ik_stretch = 0.1 # IK constraint Rotation locks - for axis in ['x','y','z']: - if axis != self.rot_axis: - setattr( pb[ mch_ik ], 'lock_ik_' + axis, True ) + if self.rot_axis == 'z': + pb[mch_ik].lock_ik_x = True + pb[mch_ik].lock_ik_y = True + else: + pb[mch_ik].lock_ik_y = True + pb[mch_ik].lock_ik_z = True # Locks and Widget - pb[ ctrl ].lock_rotation = True, False, True - create_ikarrow_widget( self.obj, ctrl, bone_transform_name=None ) + pb[ctrl].lock_rotation = True, False, True + if self.rot_axis == 'x' or self.rot_axis == 'automatic': + roll = 0 + else: + roll = pi/2 + create_ikarrow_widget(self.obj, ctrl, bone_transform_name=None, roll=roll) create_sphere_widget(self.obj, pole_target, bone_transform_name=None) create_line_widget(self.obj, vispole) return {'ctrl': {'limb': ctrl, 'ik_target': pole_target}, - 'mch_ik': mch_ik, - 'mch_target': mch_target, - 'mch_str': mch_str, - 'visuals': {'vispole': vispole} + 'mch_ik': mch_ik, + 'mch_target': mch_target, + 'mch_str': mch_str, + 'visuals': {'vispole': vispole} } def create_fk(self, parent): @@ -521,8 +568,8 @@ class Rig: pb_parent = pb[parent] # Create ik/fk switch property - pb_parent['IK/FK'] = 0.0 - prop = rna_idprop_ui_prop_get(pb_parent, 'IK/FK', create=True) + pb_parent['IK_FK'] = 0.0 + prop = rna_idprop_ui_prop_get(pb_parent, 'IK_FK', create=True) prop["min"] = 0.0 prop["max"] = 1.0 prop["soft_min"] = 0.0 @@ -567,8 +614,8 @@ class Rig: ctrl = copy_bone(self.obj, org_bones[2], ctrl) # clear parent (so that rigify will parent to root) - eb[ ctrl ].parent = None - eb[ ctrl ].use_connect = False + eb[ctrl].parent = None + eb[ctrl].use_connect = False # Parent eb[ bones['ik']['mch_target'] ].parent = eb[ ctrl ] @@ -939,6 +986,9 @@ class Rig: bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones + # Adjust org-bones rotation + self.orient_org_bones() + # Clear parents for org bones for bone in self.org_bones[1:]: eb[bone].use_connect = False @@ -968,7 +1018,8 @@ class Rig: controls_string = ", ".join(["'" + x + "'" for x in controls]) script = create_script(bones, 'arm') - script += extra_script % (controls_string, bones['main_parent'], 'IK_follow', 'pole_follow', 'root/parent', 'root/parent') + script += extra_script % (controls_string, bones['main_parent'], 'IK_follow', + 'pole_follow', 'pole_follow', 'root/parent', 'root/parent') return [script] @@ -979,14 +1030,21 @@ def add_parameters(params): """ items = [ - ('x', 'X', ''), - ('y', 'Y', ''), - ('z', 'Z', '') + ('x', 'X manual', ''), + ('z', 'Z manual', ''), + ('automatic', 'Automatic', '') ] + params.rotation_axis = bpy.props.EnumProperty( items = items, name = "Rotation Axis", - default = 'x' + default = 'automatic' + ) + + params.auto_align_extremity = bpy.BoolProperty( + name='auto_align_extremity', + default=False, + description="Auto Align Extremity Bone" ) params.segments = bpy.props.IntProperty( @@ -1033,12 +1091,14 @@ def add_parameters(params): def parameters_ui(layout, params): """ Create the ui for the rig parameters.""" - # r = layout.row() - # r.prop(params, "limb_type") - r = layout.row() r.prop(params, "rotation_axis") + if 'auto' not in params.rotation_axis.lower(): + r = layout.row() + text = "Auto align Hand" + r.prop(params, "auto_align_extremity", text=text) + r = layout.row() r.prop(params, "segments") |