Rigify: add more parent switching and 2.81 inherit scale features.
- Add a parent switch to the main spine control, to allow using the key baking operator to convert between moving and fixed root bone. - Add hips, chest and head as parents for children of the spine. - Use 'Fix Shear' Inherit Scale and 'Make Uniform' Copy Scale in limbs. - Switch code to use the new inherit_scale parameter of set_bone_parent. - Allow local matrices in adjust_widget_transform_mesh.
This commit is contained in:
parent
e57714f3a2
commit
50c493fb22
|
@ -218,7 +218,7 @@ class BaseLimbRig(BaseRig):
|
|||
def parent_mch_follow_bone(self):
|
||||
mch = self.bones.mch.follow
|
||||
align_bone_orientation(self.obj, mch, 'root')
|
||||
self.set_bone_parent(mch, self.rig_parent_bone)
|
||||
self.set_bone_parent(mch, self.rig_parent_bone, inherit_scale='FIX_SHEAR')
|
||||
|
||||
@stage.configure_bones
|
||||
def configure_mch_follow_bone(self):
|
||||
|
@ -232,8 +232,9 @@ class BaseLimbRig(BaseRig):
|
|||
def rig_mch_follow_bone(self):
|
||||
mch = self.bones.mch.follow
|
||||
|
||||
self.make_constraint(mch, 'COPY_SCALE', 'root', use_make_uniform=True)
|
||||
|
||||
con = self.make_constraint(mch, 'COPY_ROTATION', 'root')
|
||||
self.make_constraint(mch, 'COPY_SCALE', 'root')
|
||||
|
||||
self.make_driver(con, 'influence', variables=[(self.prop_bone, 'FK_limb_follow')])
|
||||
|
||||
|
@ -311,7 +312,7 @@ class BaseLimbRig(BaseRig):
|
|||
|
||||
def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
|
||||
if i == 2:
|
||||
self.set_bone_parent(parent_mch, prev_ctrl, use_connect=True)
|
||||
self.set_bone_parent(parent_mch, prev_ctrl, use_connect=True, inherit_scale='NONE')
|
||||
|
||||
@stage.rig_bones
|
||||
def rig_fk_parent_chain(self):
|
||||
|
@ -320,7 +321,7 @@ class BaseLimbRig(BaseRig):
|
|||
|
||||
def rig_fk_parent_bone(self, i, parent_mch, org):
|
||||
if i == 2:
|
||||
self.make_constraint(parent_mch, 'COPY_SCALE', 'root')
|
||||
self.make_constraint(parent_mch, 'COPY_SCALE', 'root', use_make_uniform=True)
|
||||
|
||||
|
||||
####################################################
|
||||
|
@ -691,7 +692,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')
|
||||
self.make_constraint(tweak, 'COPY_SCALE', 'root', use_make_uniform=True)
|
||||
|
||||
|
||||
####################################################
|
||||
|
|
|
@ -115,17 +115,21 @@ class Rig(BaseRig):
|
|||
|
||||
@stage.parent_bones
|
||||
def parent_master_control(self):
|
||||
self.set_bone_parent(self.bones.ctrl.master, self.rig_parent_bone)
|
||||
self.set_bone_parent(self.bones.ctrl.master, self.rig_parent_bone, inherit_scale='AVERAGE')
|
||||
|
||||
if self.make_secondary:
|
||||
self.set_bone_parent(self.bones.ctrl.secondary, self.rig_parent_bone)
|
||||
self.set_bone_parent(self.bones.ctrl.secondary, self.rig_parent_bone, inherit_scale='AVERAGE')
|
||||
|
||||
@stage.configure_bones
|
||||
def configure_master_control(self):
|
||||
self.copy_bone_properties(self.bones.org[-1], self.bones.ctrl.master)
|
||||
self.configure_control_bone(self.bones.ctrl.master, self.bones.org[-1])
|
||||
|
||||
if self.make_secondary:
|
||||
self.copy_bone_properties(self.bones.org[0], self.bones.ctrl.secondary)
|
||||
self.configure_control_bone(self.bones.ctrl.secondary, self.bones.org[0])
|
||||
|
||||
def configure_control_bone(self, ctrl, org):
|
||||
self.copy_bone_properties(org, ctrl)
|
||||
self.get_bone(ctrl).lock_scale = (True, True, True)
|
||||
|
||||
@stage.generate_widgets
|
||||
def make_master_control_widgets(self):
|
||||
|
@ -179,8 +183,7 @@ class Rig(BaseRig):
|
|||
@stage.parent_bones
|
||||
def parent_org_chain(self):
|
||||
for org in self.bones.org:
|
||||
self.set_bone_parent(org, self.rig_parent_bone)
|
||||
self.get_bone(org).inherit_scale = 'NONE'
|
||||
self.set_bone_parent(org, self.rig_parent_bone, inherit_scale='NONE')
|
||||
|
||||
@stage.rig_bones
|
||||
def rig_org_chain(self):
|
||||
|
|
|
@ -64,11 +64,26 @@ class BaseSpineRig(TweakChainRig):
|
|||
|
||||
align_bone_to_axis(self.obj, name, 'y', length=self.length * 0.6)
|
||||
|
||||
SwitchParentBuilder(self.generator).register_parent(self, name)
|
||||
self.build_parent_switch(name)
|
||||
|
||||
def build_parent_switch(self, master_name):
|
||||
pbuilder = SwitchParentBuilder(self.generator)
|
||||
pbuilder.register_parent(self, master_name, name='Torso')
|
||||
pbuilder.build_child(
|
||||
self, master_name, exclude_self=True,
|
||||
prop_id='torso_parent', prop_name='Torso Parent',
|
||||
controls=lambda: self.bones.flatten('ctrl'),
|
||||
)
|
||||
|
||||
self.register_parent_bones(pbuilder)
|
||||
|
||||
def register_parent_bones(self, pbuilder):
|
||||
pbuilder.register_parent(self, self.bones.org[0], name='Hips', exclude_self=True)
|
||||
pbuilder.register_parent(self, self.bones.org[-1], name='Chest', exclude_self=True)
|
||||
|
||||
@stage.parent_bones
|
||||
def parent_master_control(self):
|
||||
self.set_bone_parent(self.bones.ctrl.master, self.rig_parent_bone)
|
||||
pass
|
||||
|
||||
@stage.configure_bones
|
||||
def configure_master_control(self):
|
||||
|
|
|
@ -26,6 +26,7 @@ from ...utils.naming import make_derived_name
|
|||
from ...utils.bones import align_bone_orientation
|
||||
from ...utils.widgets_basic import create_circle_widget, create_cube_widget
|
||||
from ...utils.widgets_special import create_neck_bend_widget, create_neck_tweak_widget
|
||||
from ...utils.switch_parent import SwitchParentBuilder
|
||||
from ...utils.misc import map_list
|
||||
|
||||
from ...base_rig import stage
|
||||
|
@ -253,8 +254,7 @@ class Rig(BaseHeadTailRig):
|
|||
def parent_mch_chain(self):
|
||||
mch = self.bones.mch
|
||||
for bone in mch.chain:
|
||||
self.set_bone_parent(bone, mch.stretch)
|
||||
self.get_bone(bone).inherit_scale = 'NONE'
|
||||
self.set_bone_parent(bone, mch.stretch, inherit_scale='NONE')
|
||||
|
||||
@stage.rig_bones
|
||||
def rig_mch_chain(self):
|
||||
|
@ -318,6 +318,12 @@ class Rig(BaseHeadTailRig):
|
|||
####################################################
|
||||
# ORG and DEF bones
|
||||
|
||||
@stage.generate_bones
|
||||
def register_parent_bones(self):
|
||||
rig = self.rigify_parent or self
|
||||
builder = SwitchParentBuilder(self.generator)
|
||||
builder.register_parent(rig, self.bones.org[-1], name='Head', exclude_self=True)
|
||||
|
||||
@stage.configure_bones
|
||||
def configure_bbone_chain(self):
|
||||
self.get_bone(self.bones.deform[-1]).bone.bbone_segments = 1
|
||||
|
|
|
@ -96,6 +96,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
|
|||
use_parent_mch Create an intermediate MCH bone for the constraints and parent the child to it.
|
||||
select_parent Select the specified bone instead of the last one.
|
||||
ignore_global Ignore the is_global flag of potential parents.
|
||||
exclude_self Ignore parents registered by the rig itself.
|
||||
context_rig Rig to use for selecting parents.
|
||||
|
||||
prop_bone Name of the bone to add the property to.
|
||||
|
@ -158,7 +159,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
|
|||
child_option_table = {
|
||||
'extra_parents': None,
|
||||
'prop_bone': None, 'prop_id': None, 'prop_name': None, 'controls': None,
|
||||
'select_parent': None, 'ignore_global': False, 'context_rig': None,
|
||||
'select_parent': None, 'ignore_global': False, 'exclude_self': False, 'context_rig': None,
|
||||
'ctrl_bone': None,
|
||||
'no_fix_location': False, 'no_fix_rotation': False, 'no_fix_scale': False,
|
||||
'copy_location': None, 'copy_rotation': None, 'copy_scale': None,
|
||||
|
@ -186,7 +187,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
|
|||
|
||||
for parent in self.parent_list:
|
||||
if parent['rig'] is child_rig:
|
||||
if parent['exclude_self']:
|
||||
if parent['exclude_self'] or child['exclude_self']:
|
||||
continue
|
||||
elif parent['is_global'] and not child['ignore_global']:
|
||||
# Can't use parents from own children, even if global (cycle risk)
|
||||
|
@ -218,8 +219,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
|
|||
|
||||
# Parent child to the MCH proxy
|
||||
if mch != child['bone']:
|
||||
rig.set_bone_parent(child['bone'], mch)
|
||||
rig.get_bone(child['bone']).inherit_scale = child['inherit_scale']
|
||||
rig.set_bone_parent(child['bone'], mch, inherit_scale=child['inherit_scale'])
|
||||
|
||||
def configure_bones(self):
|
||||
for child in self.child_list:
|
||||
|
|
|
@ -50,16 +50,8 @@ def obj_to_bone(obj, rig, bone_name, bone_transform_name=None):
|
|||
elif bone.custom_shape_transform:
|
||||
bone = bone.custom_shape_transform
|
||||
|
||||
mat = rig.matrix_world @ bone.bone.matrix_local
|
||||
|
||||
obj.location = mat.to_translation()
|
||||
|
||||
obj.rotation_mode = 'XYZ'
|
||||
obj.rotation_euler = mat.to_euler()
|
||||
|
||||
scl = mat.to_scale()
|
||||
scl_avg = (scl[0] + scl[1] + scl[2]) / 3
|
||||
obj.scale = (scale * scl_avg), (scale * scl_avg), (scale * scl_avg)
|
||||
obj.matrix_basis = rig.matrix_world @ bone.bone.matrix_local @ Matrix.Scale(scale, 4)
|
||||
|
||||
|
||||
def create_widget(rig, bone_name, bone_transform_name=None):
|
||||
|
@ -159,11 +151,22 @@ def adjust_widget_axis(obj, axis='y', offset=0.0):
|
|||
vert.co = matrix @ vert.co
|
||||
|
||||
|
||||
def adjust_widget_transform(obj, matrix):
|
||||
"""Adjust the generated widget by applying a world space correction matrix to the mesh."""
|
||||
def adjust_widget_transform_mesh(obj, matrix, local=None):
|
||||
"""Adjust the generated widget by applying a correction matrix to the mesh.
|
||||
If local is false, the matrix is in world space.
|
||||
If local is True, it's in the local space of the widget.
|
||||
If local is a bone, it's in the local space of the bone.
|
||||
"""
|
||||
if obj:
|
||||
obmat = obj.matrix_basis
|
||||
matrix = obmat.inverted() @ matrix @ obmat
|
||||
if local is not True:
|
||||
if local:
|
||||
assert isinstance(local, bpy.types.PoseBone)
|
||||
bonemat = local.id_data.matrix_world @ local.bone.matrix_local
|
||||
matrix = bonemat @ matrix @ bonemat.inverted()
|
||||
|
||||
obmat = obj.matrix_basis
|
||||
matrix = obmat.inverted() @ matrix @ obmat
|
||||
|
||||
obj.data.transform(matrix)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue