From 2f1c38fd507ecfd9c23cc7205da6b426507fa07f Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov <angavrilov@gmail.com> Date: Sun, 2 Jan 2022 19:48:39 +0300 Subject: [PATCH] Rigify: support uniform scaling of limbs via the master control. Existing IK & FK controls only allowed squash and stretch scaling. --- rigify/rigs/limbs/limb_rigs.py | 36 +++++++++++++++++++++++++--------- rigify/utils/animation.py | 27 +++++++++++++++++++------ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/rigify/rigs/limbs/limb_rigs.py b/rigify/rigs/limbs/limb_rigs.py index 8a9657958..4841fd425 100644 --- a/rigify/rigs/limbs/limb_rigs.py +++ b/rigify/rigs/limbs/limb_rigs.py @@ -181,31 +181,35 @@ class BaseLimbRig(BaseRig): @stage.generate_bones def make_master_control(self): org = self.bones.org.main[0] - self.bones.mch.master = name = self.copy_bone(org, make_derived_name(org, 'mch', '_parent_socket'), scale=1/12) + self.bones.mch.master = name = self.copy_bone(org, make_derived_name(org, 'mch', '_parent_widget'), scale=1/12) self.bones.ctrl.master = name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_parent'), scale=1/4) self.get_bone(name).roll = 0 self.prop_bone = self.bones.ctrl.master @stage.parent_bones def parent_master_control(self): - self.set_bone_parent(self.bones.ctrl.master, self.bones.mch.master) - self.set_bone_parent(self.bones.mch.master, self.bones.mch.follow) + self.set_bone_parent(self.bones.ctrl.master, self.rig_parent_bone, inherit_scale='NONE') + self.set_bone_parent(self.bones.mch.master, self.bones.org.main[0], inherit_scale='NONE') @stage.configure_bones def configure_master_control(self): bone = self.get_bone(self.bones.ctrl.master) bone.lock_location = (True, True, True) bone.lock_rotation = (True, True, True) - bone.lock_scale = (True, True, True) + bone.lock_scale = (False, False, False) bone.lock_rotation_w = True @stage.rig_bones def rig_master_control(self): - self.make_constraint(self.bones.mch.master, 'COPY_ROTATION', self.bones.org.main[0]) + mch = self.bones.mch + self.make_constraint(mch.master, 'COPY_SCALE', 'root', use_make_uniform=True) + self.make_constraint(mch.master, 'COPY_SCALE', self.bones.ctrl.master, use_offset=True, space='LOCAL') @stage.generate_widgets def make_master_control_widget(self): - create_gear_widget(self.obj, self.bones.ctrl.master, radius=1) + master = self.bones.ctrl.master + set_bone_widget_transform(self.obj, master, self.bones.mch.master) + create_gear_widget(self.obj, master, radius=1) #################################################### @@ -235,6 +239,10 @@ class BaseLimbRig(BaseRig): mch = self.bones.mch.follow self.make_constraint(mch, 'COPY_SCALE', 'root', use_make_uniform=True) + self.make_constraint( + mch, 'COPY_SCALE', self.bones.ctrl.master, + use_make_uniform=True, use_offset=True, space='LOCAL' + ) con = self.make_constraint(mch, 'COPY_ROTATION', 'root') @@ -325,7 +333,9 @@ class BaseLimbRig(BaseRig): def rig_fk_parent_bone(self, i, parent_mch, org): if i >= 2: - self.make_constraint(parent_mch, 'COPY_SCALE', 'root', use_make_uniform=True) + self.make_constraint( + parent_mch, 'COPY_SCALE', self.bones.mch.follow, use_make_uniform=True + ) #################################################### @@ -435,6 +445,13 @@ class BaseLimbRig(BaseRig): @stage.rig_bones def rig_ik_controls(self): self.rig_hide_pole_control(self.bones.ctrl.ik_pole) + self.rig_ik_control_scale(self.bones.ctrl.ik) + + def rig_ik_control_scale(self, ctrl): + self.make_constraint( + ctrl, 'COPY_SCALE', self.bones.ctrl.master, + use_make_uniform=True, use_offset=True, space='LOCAL', + ) @stage.generate_widgets def make_ik_control_widgets(self): @@ -801,7 +818,7 @@ class BaseLimbRig(BaseRig): self.make_constraint(tweak, 'DAMPED_TRACK', next_tweak) elif entry.seg_idx is not None: - self.make_constraint(tweak, 'COPY_SCALE', 'root', use_make_uniform=True) + self.make_constraint(tweak, 'COPY_SCALE', self.bones.mch.follow, use_make_uniform=True) if i == 0: self.make_constraint(tweak, 'COPY_LOCATION', entry.org) @@ -1007,7 +1024,8 @@ class RigifyLimbIk2FkBase: endmat = convert_pose_matrix_via_rest_delta(matrices[-1], ik_bones[-1], ctrl_bones[-1]) set_transform_from_matrix( - obj, self.ctrl_bone_list[-1], endmat, keyflags=self.keyflags + obj, self.ctrl_bone_list[-1], endmat, keyflags=self.keyflags, + undo_copy_scale=True, ) # Remove foot heel transform, if present diff --git a/rigify/utils/animation.py b/rigify/utils/animation.py index 1355a0b65..8710e74da 100644 --- a/rigify/utils/animation.py +++ b/rigify/utils/animation.py @@ -182,18 +182,33 @@ def undo_copy_scale_with_offset(obj, bone, con, old_matrix): "Undo the effects of Copy Scale with Offset constraint on a bone matrix." inf = con.influence - if con.mute or inf == 0 or not con.is_valid or not con.use_offset or con.use_add or con.use_make_uniform: + if con.mute or inf == 0 or not con.is_valid or not con.use_offset or con.use_add: return old_matrix + tgt_matrix = get_constraint_target_matrix(con) + tgt_scale = tgt_matrix.to_scale() + use = [con.use_x, con.use_y, con.use_z] + + if con.use_make_uniform: + if con.use_x and con.use_y and con.use_z: + total = tgt_matrix.determinant() + else: + total = 1 + for i, use in enumerate(use): + if use: + total *= tgt_scale[i] + + tgt_scale = [abs(total)**(1./3.)]*3 + else: + for i, use in enumerate(use): + if not use: + tgt_scale[i] = 1 + scale_delta = [ 1 / (1 + (math.pow(x, con.power) - 1) * inf) - for x in get_constraint_target_matrix(con).to_scale() + for x in tgt_scale ] - for i, use in enumerate([con.use_x, con.use_y, con.use_z]): - if not use: - scale_delta[i] = 1 - return old_matrix @ Matrix.Diagonal([*scale_delta, 1]) def undo_copy_scale_constraints(obj, bone, matrix): -- GitLab