[Bf-extensions-cvs] [7120e9c9] master: Rigify: allow aligning IK control location channels to world space.

Alexander Gavrilov noreply at git.blender.org
Fri Feb 11 21:50:17 CET 2022


Commit: 7120e9c9e08720c20833a334fee197ed9a11dc64
Author: Alexander Gavrilov
Date:   Fri Feb 11 23:27:26 2022 +0300
Branches: master
https://developer.blender.org/rBA7120e9c9e08720c20833a334fee197ed9a11dc64

Rigify: allow aligning IK control location channels to world space.

For IK controls that move freely in space without being tied to
a parent it makes sense to align the location channels to world
(or root), while keeping rotation channels aligned to the limb
end orientation.

Blender already has a Local Location parenting option for this
very use case, but Rigify wasn't using it. This adjusts the
switchable parent mechanism so that the option works as intended,
and provides a Rigify option that controls its value for IK controls.

Note that now it is possible to enable the Local Location option
directly on the control bones after generation and it will work
correctly - it is not required to enable IK Local Location.

===================================================================

M	rigify/rigs/face/skin_eye.py
M	rigify/rigs/limbs/limb_rigs.py
M	rigify/rigs/limbs/super_finger.py
M	rigify/utils/bones.py
M	rigify/utils/switch_parent.py

===================================================================

diff --git a/rigify/rigs/face/skin_eye.py b/rigify/rigs/face/skin_eye.py
index 2d1f6c2f..4955df6b 100644
--- a/rigify/rigs/face/skin_eye.py
+++ b/rigify/rigs/face/skin_eye.py
@@ -593,6 +593,8 @@ class EyeClusterControl(RigComponent):
 
     def parent_bones(self):
         if self.rig_count > 1:
+            self.get_bone(self.master_bone).use_local_location = False
+
             for child in self.child_bones:
                 self.set_bone_parent(child, self.master_bone)
 
diff --git a/rigify/rigs/limbs/limb_rigs.py b/rigify/rigs/limbs/limb_rigs.py
index 2b4723a4..b72e9d40 100644
--- a/rigify/rigs/limbs/limb_rigs.py
+++ b/rigify/rigs/limbs/limb_rigs.py
@@ -432,6 +432,12 @@ class BaseLimbRig(BaseRig):
         else:
             self.set_bone_parent(self.bones.ctrl.ik_base, self.bones.mch.ik_swing)
 
+        self.set_ik_local_location(self.bones.ctrl.ik)
+        self.set_ik_local_location(self.bones.ctrl.ik_pole)
+
+    def set_ik_local_location(self, ctrl):
+        self.get_bone(ctrl).use_local_location = self.params.ik_local_location
+
     @stage.configure_bones
     def configure_ik_controls(self):
         base = self.get_bone(self.bones.ctrl.ik_base)
@@ -927,6 +933,12 @@ class BaseLimbRig(BaseRig):
             description = "Create a rotation pivot control that can be repositioned arbitrarily"
         )
 
+        params.ik_local_location = bpy.props.BoolProperty(
+            name        = "IK Local Location",
+            default     = True,
+            description = "Specifies the value of the Local Location option for IK controls, which decides if the location channels are aligned to the local control orientation or world",
+        )
+
         # Setting up extra layers for the FK and tweak
         ControlLayersOption.FK.add_parameters(params)
         ControlLayersOption.TWEAK.add_parameters(params)
@@ -949,6 +961,7 @@ class BaseLimbRig(BaseRig):
         r.prop(params, "bbones")
 
         layout.prop(params, 'make_custom_pivot', text="Custom IK Pivot")
+        layout.prop(params, 'ik_local_location')
 
         ControlLayersOption.FK.parameters_ui(layout, params)
         ControlLayersOption.TWEAK.parameters_ui(layout, params)
diff --git a/rigify/rigs/limbs/super_finger.py b/rigify/rigs/limbs/super_finger.py
index 9eed5415..2229c0c0 100644
--- a/rigify/rigs/limbs/super_finger.py
+++ b/rigify/rigs/limbs/super_finger.py
@@ -152,6 +152,12 @@ class Rig(SimpleChainRig):
             no_fix_rotation=True, no_fix_scale=True,
         )
 
+    @stage.parent_bones
+    def parent_ik_control(self):
+        if self.make_ik:
+            bone = self.get_bone(self.bones.ctrl.ik)
+            bone.use_local_location = self.params.ik_local_location
+
     @stage.configure_bones
     def configure_ik_control(self):
         if self.make_ik:
@@ -366,6 +372,12 @@ class Rig(SimpleChainRig):
             description = "Create an optional IK control"
         )
 
+        params.ik_local_location = bpy.props.BoolProperty(
+            name        = 'IK Local Location',
+            default     = True,
+            description = "Specifies the value of the Local Location option for IK controls, which decides if the location channels are aligned to the local control orientation or world",
+        )
+
         ControlLayersOption.TWEAK.add_parameters(params)
         ControlLayersOption.EXTRA_IK.add_parameters(params)
 
@@ -380,6 +392,9 @@ class Rig(SimpleChainRig):
         layout.prop(params, 'bbones')
         layout.prop(params, 'make_extra_ik_control', text='IK Control')
 
+        if params.make_extra_ik_control:
+            layout.prop(params, 'ik_local_location')
+
         ControlLayersOption.TWEAK.parameters_ui(layout, params)
 
         if params.make_extra_ik_control:
diff --git a/rigify/utils/bones.py b/rigify/utils/bones.py
index 16cf62de..10a8926d 100644
--- a/rigify/utils/bones.py
+++ b/rigify/utils/bones.py
@@ -482,6 +482,20 @@ def align_bone_orientation(obj, bone_name, target_bone_name):
     bone1_e.roll = bone2_e.roll
 
 
+def set_bone_orientation(obj, bone_name, orientation):
+    """ Aligns the orientation of bone to target bone or matrix. """
+    if isinstance(orientation, str):
+        align_bone_orientation(obj, bone_name, orientation)
+
+    else:
+        bone_e = obj.data.edit_bones[bone_name]
+
+        matrix = Matrix(orientation).to_4x4()
+        matrix.translation = bone_e.head
+
+        bone_e.matrix = matrix
+
+
 def align_bone_roll(obj, bone1, bone2):
     """ Aligns the roll of two bones.
     """
diff --git a/rigify/utils/switch_parent.py b/rigify/utils/switch_parent.py
index 405008b9..ff5217b4 100644
--- a/rigify/utils/switch_parent.py
+++ b/rigify/utils/switch_parent.py
@@ -7,6 +7,7 @@ import json
 
 from .errors import MetarigError
 from .naming import strip_prefix, make_derived_name
+from .bones import set_bone_orientation
 from .mechanism import MechanismUtilityMixin
 from .rig import rig_is_child
 from .misc import map_list, map_apply, force_lazy
@@ -16,6 +17,7 @@ from ..base_generate import GeneratorPlugin
 
 from collections import defaultdict
 from itertools import count, repeat, chain
+from mathutils import Matrix
 
 
 class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
@@ -80,7 +82,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
             self.local_parents[id(rig)].append(entry)
 
 
-    def build_child(self, rig, bone, *, use_parent_mch=True, **options):
+    def build_child(self, rig, bone, *, use_parent_mch=True, mch_orientation=None, **options):
         """
         Build a switchable parent mechanism for the specified bone.
 
@@ -89,6 +91,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
           bone              Name of the child bone.
           extra_parents     List of bone names or (name, user_name) pairs to use as additional parents.
           use_parent_mch    Create an intermediate MCH bone for the constraints and parent the child to it.
+          mch_orientation   Orientation matrix or bone name to align the MCH bone to; defaults to world.
           select_parent     Select the specified bone instead of the last one.
           select_tags       List of parent tags to try for default selection.
           ignore_global     Ignore the is_global flag of potential parents.
@@ -120,6 +123,9 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
         # Create MCH proxy
         if use_parent_mch:
             mch_bone = rig.copy_bone(bone, make_derived_name(bone, 'mch', '.parent'), scale=1/3)
+
+            set_bone_orientation(rig.obj, mch_bone, mch_orientation or Matrix.Identity(4))
+
         else:
             mch_bone = bone



More information about the Bf-extensions-cvs mailing list