Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rigify/rigs/limbs')
-rw-r--r--rigify/rigs/limbs/arm.py69
-rw-r--r--rigify/rigs/limbs/leg.py190
-rw-r--r--rigify/rigs/limbs/limb_rigs.py97
-rw-r--r--rigify/rigs/limbs/paw.py8
-rw-r--r--rigify/rigs/limbs/simple_tentacle.py2
-rw-r--r--rigify/rigs/limbs/super_finger.py42
-rw-r--r--rigify/rigs/limbs/super_palm.py3
7 files changed, 299 insertions, 112 deletions
diff --git a/rigify/rigs/limbs/arm.py b/rigify/rigs/limbs/arm.py
index 98a3c50f..e79edc5c 100644
--- a/rigify/rigs/limbs/arm.py
+++ b/rigify/rigs/limbs/arm.py
@@ -21,12 +21,15 @@
import bpy
from itertools import count
+from mathutils import Matrix
-from ...utils.bones import BoneDict, compute_chain_x_axis, align_bone_x_axis, align_bone_z_axis
+from ...utils.bones import put_bone, compute_chain_x_axis, align_bone_x_axis, align_bone_z_axis
from ...utils.naming import make_derived_name
from ...utils.misc import map_list
+from ...utils.widgets import adjust_widget_transform_mesh
from ..widgets import create_hand_widget
+from ...utils.widgets_basic import create_circle_widget
from ...base_rig import stage
@@ -42,6 +45,8 @@ class Rig(BaseLimbRig):
super().initialize()
+ self.make_wrist_pivot = self.params.make_ik_wrist_pivot
+
def prepare_bones(self):
orgs = self.bones.org.main
@@ -62,16 +67,76 @@ class Rig(BaseLimbRig):
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
create_hand_widget(self.obj, ctrl)
####################################################
+ # Palm Pivot
+
+ def get_ik_input_bone(self):
+ if self.make_wrist_pivot:
+ return self.bones.mch.ik_wrist
+ else:
+ return self.get_ik_control_output()
+
+ def get_extra_ik_controls(self):
+ controls = super().get_extra_ik_controls()
+ if self.make_wrist_pivot:
+ controls += [self.bones.ctrl.ik_wrist]
+ return controls
+
+ @stage.generate_bones
+ def make_wrist_pivot_control(self):
+ if self.make_wrist_pivot:
+ org = self.bones.org.main[2]
+ self.bones.ctrl.ik_wrist = self.make_wrist_pivot_bone(org)
+ self.bones.mch.ik_wrist = self.copy_bone(org, make_derived_name(org, 'mch', '_ik_wrist'), scale=0.25)
+
+ def make_wrist_pivot_bone(self, org):
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_ik_wrist'), scale=0.5)
+ put_bone(self.obj, name, self.get_bone(org).tail)
+ return name
+
+ @stage.parent_bones
+ def parent_wrist_pivot_control(self):
+ if self.make_wrist_pivot:
+ ctrl = self.bones.ctrl.ik_wrist
+ self.set_bone_parent(ctrl, self.get_ik_control_output())
+ self.set_bone_parent(self.bones.mch.ik_wrist, ctrl)
+
+ @stage.generate_widgets
+ def make_wrist_pivot_widget(self):
+ if self.make_wrist_pivot:
+ ctrl = self.bones.ctrl.ik_wrist
+
+ if self.main_axis == 'x':
+ obj = create_circle_widget(self.obj, ctrl, head_tail=-0.3, head_tail_x=0.5)
+ else:
+ obj = create_circle_widget(self.obj, ctrl, head_tail=0.5, head_tail_x=-0.3)
+
+ if obj:
+ org_bone = self.get_bone(self.bones.org.main[2])
+ offset = org_bone.head - self.get_bone(ctrl).head
+ adjust_widget_transform_mesh(obj, Matrix.Translation(offset))
+
+ ####################################################
# Settings
@classmethod
+ def add_parameters(self, params):
+ super().add_parameters(params)
+
+ params.make_ik_wrist_pivot = bpy.props.BoolProperty(
+ name="IK Wrist Pivot", default=False,
+ description="Make an extra IK hand control pivoting around the tip of the hand"
+ )
+
+ @classmethod
def parameters_ui(self, layout, params):
+ layout.prop(params, "make_ik_wrist_pivot")
+
super().parameters_ui(layout, params, 'Hand')
diff --git a/rigify/rigs/limbs/leg.py b/rigify/rigs/limbs/leg.py
index dbdd20cb..b409d009 100644
--- a/rigify/rigs/limbs/leg.py
+++ b/rigify/rigs/limbs/leg.py
@@ -22,13 +22,14 @@ import bpy
import math
from itertools import count
-from mathutils import Vector
+from mathutils import Vector, Matrix
from ...utils.rig import is_rig_base_bone
from ...utils.bones import align_chain_x_axis, align_bone_x_axis, align_bone_y_axis, align_bone_z_axis
from ...utils.bones import align_bone_to_axis, flip_bone, put_bone, align_bone_orientation
from ...utils.naming import make_derived_name
-from ...utils.misc import map_list
+from ...utils.misc import map_list, matrix_from_axis_roll, matrix_from_axis_pair
+from ...utils.widgets import adjust_widget_transform_mesh
from ..widgets import create_foot_widget, create_ballsocket_widget
@@ -62,10 +63,18 @@ class Rig(BaseLimbRig):
super().initialize()
+ self.pivot_type = self.params.foot_pivot_type
+ self.heel_euler_order = 'ZXY' if self.main_axis == 'x' else 'XZY'
+
+ assert self.pivot_type in {'ANKLE', 'TOE', 'ANKLE_TOE'}
+
def prepare_bones(self):
orgs = self.bones.org.main
+ foot = self.get_bone(orgs[2])
- foot_x = self.vector_without_z(self.get_bone(orgs[2]).y_axis).cross((0, 0, -1))
+ ik_y_axis = (0, 1, 0)
+ foot_y_axis = -self.vector_without_z(foot.y_axis)
+ foot_x = foot_y_axis.cross((0, 0, 1))
if self.params.rotation_axis == 'automatic':
align_chain_x_axis(self.obj, orgs[0:2])
@@ -84,6 +93,12 @@ class Rig(BaseLimbRig):
align_bone_z_axis(self.obj, orgs[2], foot_x)
align_bone_z_axis(self.obj, orgs[3], -foot_x)
+ else:
+ ik_y_axis = foot_y_axis
+
+ # Orientation of the IK main and roll control bones
+ self.ik_matrix = matrix_from_axis_roll(ik_y_axis, 0)
+ self.roll_matrix = matrix_from_axis_pair(ik_y_axis, foot_x, self.main_axis)
####################################################
# EXTRA BONES
@@ -92,6 +107,8 @@ class Rig(BaseLimbRig):
# heel:
# Heel location marker bone
# ctrl:
+ # ik_spin:
+ # Toe spin control.
# heel:
# Foot roll control
# mch:
@@ -104,31 +121,71 @@ class Rig(BaseLimbRig):
# IK controls
def get_extra_ik_controls(self):
- return [self.bones.ctrl.heel]
+ controls = super().get_extra_ik_controls() + [self.bones.ctrl.heel]
+ if self.pivot_type == 'ANKLE_TOE':
+ controls += [self.bones.ctrl.ik_spin]
+ return controls
def make_ik_control_bone(self, orgs):
name = self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
-
- if self.params.rotation_axis == 'automatic' or self.params.auto_align_extremity:
- align_bone_to_axis(self.obj, name, 'y', flip=True)
-
+ if self.pivot_type == 'TOE':
+ put_bone(self.obj, name, self.get_bone(name).tail, matrix=self.ik_matrix)
else:
- flip_bone(self.obj, name)
-
- bone = self.get_bone(name)
- bone.tail[2] = bone.head[2]
- bone.roll = 0
-
+ put_bone(self.obj, name, None, matrix=self.ik_matrix)
return name
+ def build_ik_pivot(self, ik_name, **args):
+ heel_bone = self.get_bone(self.bones.org.heel)
+ args = {
+ 'position': (heel_bone.head + heel_bone.tail)/2,
+ **args
+ }
+ return super().build_ik_pivot(ik_name, **args)
+
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
- create_foot_widget(self.obj, ctrl)
+ obj = create_foot_widget(self.obj, ctrl)
+ if self.pivot_type != 'TOE':
+ ctrl = self.get_bone(ctrl)
+ org = self.get_bone(self.bones.org.main[2])
+ offset = org.tail - (ctrl.custom_shape_transform or ctrl).head
+ adjust_widget_transform_mesh(obj, Matrix.Translation(offset))
+
+ ####################################################
+ # IK pivot controls
+
+ def get_ik_pivot_output(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ return self.bones.ctrl.ik_spin
+ else:
+ return self.get_ik_control_output()
+
+ @stage.generate_bones
+ def make_ik_pivot_controls(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ self.bones.ctrl.ik_spin = self.make_ik_spin_bone(self.bones.org.main)
+
+ def make_ik_spin_bone(self, orgs):
+ name = self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_spin_ik'))
+ put_bone(self.obj, name, self.get_bone(orgs[3]).head, matrix=self.ik_matrix, scale=0.5)
+ return name
+
+ @stage.parent_bones
+ def parent_ik_pivot_controls(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ self.set_bone_parent(self.bones.ctrl.ik_spin, self.get_ik_control_output())
+
+ @stage.generate_widgets
+ def make_ik_spin_control_widget(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ obj = create_ballsocket_widget(self.obj, self.bones.ctrl.ik_spin, size=0.75)
+ rotfix = Matrix.Rotation(math.pi/2, 4, self.main_axis.upper())
+ adjust_widget_transform_mesh(obj, rotfix, local=True)
####################################################
# Heel control
@@ -136,25 +193,19 @@ class Rig(BaseLimbRig):
@stage.generate_bones
def make_heel_control_bone(self):
org = self.bones.org.main[2]
- name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_heel_ik'), scale=1/2)
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_heel_ik'))
+ put_bone(self.obj, name, None, matrix=self.roll_matrix, scale=0.5)
self.bones.ctrl.heel = name
- self.align_roll_bone(org, name, -self.vector_without_z(self.get_bone(org).vector))
-
@stage.parent_bones
def parent_heel_control_bone(self):
- self.set_bone_parent(self.bones.ctrl.heel, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.ctrl.heel, self.get_ik_pivot_output(), inherit_scale='AVERAGE')
@stage.configure_bones
def configure_heel_control_bone(self):
bone = self.get_bone(self.bones.ctrl.heel)
bone.lock_location = True, True, True
-
- if self.main_axis == 'x':
- bone.lock_rotation = False, False, True
- else:
- bone.lock_rotation = True, False, False
-
+ bone.rotation_mode = self.heel_euler_order
bone.lock_scale = True, True, True
@stage.generate_widgets
@@ -173,34 +224,27 @@ class Rig(BaseLimbRig):
def make_roll_mch_bones(self, foot, toe, heel):
foot_bone = self.get_bone(foot)
heel_bone = self.get_bone(heel)
- axis = -self.vector_without_z(foot_bone.vector)
-
- roll1 = self.copy_bone(foot, make_derived_name(heel, 'mch', '_roll1'))
- flip_bone(self.obj, roll1)
- self.align_roll_bone(foot, roll1, -foot_bone.vector)
+ heel_middle = (heel_bone.head + heel_bone.tail) / 2
- roll2 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll2'), scale=1/4)
-
- put_bone(self.obj, roll2, (heel_bone.head + heel_bone.tail) / 2)
- self.align_roll_bone(foot, roll2, -axis)
+ result = self.copy_bone(foot, make_derived_name(foot, 'mch', '_roll'), scale=0.25)
+ roll1 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll1'), scale=0.3)
+ roll2 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll2'), scale=0.3)
rock1 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock1'))
-
- align_bone_to_axis(self.obj, rock1, 'y', roll=0, length=heel_bone.length/2, flip=True)
- align_bone_y_axis(self.obj, rock1, axis)
-
rock2 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock2'))
- align_bone_to_axis(self.obj, rock2, 'y', roll=0, length=heel_bone.length/2)
- align_bone_y_axis(self.obj, rock2, axis)
+ put_bone(self.obj, roll1, None, matrix=self.roll_matrix)
+ put_bone(self.obj, roll2, heel_middle, matrix=self.roll_matrix)
+ put_bone(self.obj, rock1, heel_bone.tail, matrix=self.roll_matrix, scale=0.5)
+ put_bone(self.obj, rock2, heel_bone.head, matrix=self.roll_matrix, scale=0.5)
- return [ rock2, rock1, roll2, roll1 ]
+ return [ rock2, rock1, roll2, roll1, result ]
@stage.parent_bones
def parent_roll_mch_chain(self):
chain = self.bones.mch.heel
- self.set_bone_parent(chain[0], self.bones.ctrl.ik)
+ self.set_bone_parent(chain[0], self.get_ik_pivot_output())
self.parent_bone_chain(chain)
@stage.rig_bones
@@ -208,28 +252,37 @@ class Rig(BaseLimbRig):
self.rig_roll_mch_bones(self.bones.mch.heel, self.bones.ctrl.heel, self.bones.org.heel)
def rig_roll_mch_bones(self, chain, heel, org_heel):
- rock2, rock1, roll2, roll1 = chain
+ rock2, rock1, roll2, roll1, result = chain
+
+ # This order is required for correct working of the constraints
+ for bone in chain:
+ self.get_bone(bone).rotation_mode = self.heel_euler_order
- self.make_constraint(roll1, 'COPY_ROTATION', heel, space='LOCAL')
- self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(roll1, 'COPY_ROTATION', heel, space='POSE')
if self.main_axis == 'x':
- self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_x=True, max_x=DEG_360, space='LOCAL')
- self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_x=-DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL', use_xyz=(True, False, False))
+ self.make_constraint(roll2, 'LIMIT_ROTATION', min_x=-DEG_360, space='LOCAL')
else:
- self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_z=True, max_z=DEG_360, space='LOCAL')
- self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_z=-DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL', use_xyz=(False, False, True))
+ self.make_constraint(roll2, 'LIMIT_ROTATION', min_z=-DEG_360, space='LOCAL')
direction = self.get_main_axis(self.get_bone(heel)).dot(self.get_bone(org_heel).vector)
if direction < 0:
rock2, rock1 = rock1, rock2
- self.make_constraint(rock1, 'COPY_ROTATION', heel, space='LOCAL')
- self.make_constraint(rock2, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(
+ rock1, 'COPY_ROTATION', heel, space='LOCAL',
+ use_xyz=(False, True, False),
+ )
+ self.make_constraint(
+ rock2, 'COPY_ROTATION', heel, space='LOCAL',
+ use_xyz=(False, True, False),
+ )
- self.make_constraint(rock1, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, max_y=DEG_360, space='LOCAL')
- self.make_constraint(rock2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_y=-DEG_360, space='LOCAL')
+ self.make_constraint(rock1, 'LIMIT_ROTATION', max_y=DEG_360, space='LOCAL')
+ self.make_constraint(rock2, 'LIMIT_ROTATION', min_y=-DEG_360, space='LOCAL')
####################################################
@@ -237,7 +290,7 @@ class Rig(BaseLimbRig):
def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
if i == 3:
- align_bone_orientation(self.obj, parent_mch, self.bones.mch.heel[-2])
+ align_bone_orientation(self.obj, parent_mch, self.bones.mch.heel[2])
self.set_bone_parent(parent_mch, prev_org, use_connect=True)
@@ -246,7 +299,7 @@ class Rig(BaseLimbRig):
def rig_fk_parent_bone(self, i, parent_mch, org):
if i == 3:
- con = self.make_constraint(parent_mch, 'COPY_TRANSFORMS', self.bones.mch.heel[-2])
+ con = self.make_constraint(parent_mch, 'COPY_TRANSFORMS', self.bones.mch.heel[2])
self.make_driver(con, 'influence', variables=[(self.prop_bone, 'IK_FK')], polynomial=[1.0, -1.0])
@@ -257,8 +310,6 @@ class Rig(BaseLimbRig):
####################################################
# IK system MCH
- ik_input_head_tail = 1.0
-
def get_ik_input_bone(self):
return self.bones.mch.heel[-1]
@@ -266,14 +317,35 @@ class Rig(BaseLimbRig):
def parent_ik_mch_chain(self):
super().parent_ik_mch_chain()
- self.set_bone_parent(self.bones.mch.ik_target, self.bones.ctrl.heel)
+ self.set_bone_parent(self.bones.mch.ik_target, self.bones.mch.heel[-1])
####################################################
# Settings
@classmethod
+ def add_parameters(self, params):
+ super().add_parameters(params)
+
+ items = [
+ ('ANKLE', 'Ankle',
+ 'The foots pivots at the ankle'),
+ ('TOE', 'Toe',
+ 'The foot pivots around the base of the toe'),
+ ('ANKLE_TOE', 'Ankle and Toe',
+ 'The foots pivots at the ankle, with extra toe pivot'),
+ ]
+
+ params.foot_pivot_type = bpy.props.EnumProperty(
+ items = items,
+ name = "Foot Pivot",
+ default = 'ANKLE_TOE'
+ )
+
+ @classmethod
def parameters_ui(self, layout, params):
+ layout.prop(params, 'foot_pivot_type')
+
super().parameters_ui(layout, params, 'Foot')
diff --git a/rigify/rigs/limbs/limb_rigs.py b/rigify/rigs/limbs/limb_rigs.py
index 81079c05..f1eb8639 100644
--- a/rigify/rigs/limbs/limb_rigs.py
+++ b/rigify/rigs/limbs/limb_rigs.py
@@ -23,12 +23,12 @@ import json
from ...utils.animation import add_generic_snap_fk_to_ik, add_fk_ik_snap_buttons
from ...utils.rig import connected_children_names
-from ...utils.bones import BoneDict, put_bone, compute_chain_x_axis, align_bone_orientation
-from ...utils.bones import align_bone_x_axis, align_bone_y_axis, align_bone_z_axis
+from ...utils.bones import BoneDict, put_bone, compute_chain_x_axis, align_bone_orientation, set_bone_widget_transform
from ...utils.naming import strip_org, make_derived_name
from ...utils.layers import ControlLayersOption
from ...utils.misc import pairwise_nozip, padnone, map_list
from ...utils.switch_parent import SwitchParentBuilder
+from ...utils.components import CustomPivotControl
from ...base_rig import stage, BaseRig
@@ -64,6 +64,7 @@ class BaseLimbRig(BaseRig):
self.segments = self.params.segments
self.bbone_segments = self.params.bbones
+ self.use_ik_pivot = self.params.make_custom_pivot
rot_axis = self.params.rotation_axis
@@ -124,15 +125,6 @@ class BaseLimbRig(BaseRig):
bone = self.get_bone(org)
return bone.head + bone.vector * (seg / self.segments)
- def align_roll_bone(self, org, name, y_axis):
- if y_axis:
- align_bone_y_axis(self.obj, name, y_axis)
-
- if self.main_axis == 'x':
- align_bone_x_axis(self.obj, name, self.get_bone(org).x_axis)
- else:
- align_bone_z_axis(self.obj, name, self.get_bone(org).z_axis)
-
@staticmethod
def vector_without_z(vector):
return Vector((vector[0], vector[1], 0))
@@ -154,6 +146,8 @@ class BaseLimbRig(BaseRig):
# IK controls
# ik_vispole
# IK pole visualization.
+ # ik_pivot
+ # Custom IK pivot (optional).
# mch:
# master:
# Parent of the master control.
@@ -161,6 +155,8 @@ class BaseLimbRig(BaseRig):
# FK follow behavior.
# fk[]:
# FK chain parents (or None)
+ # ik_pivot
+ # Custom IK pivot result (optional).
# ik_stretch
# IK stretch switch implementation.
# ik_target
@@ -328,22 +324,30 @@ class BaseLimbRig(BaseRig):
# IK controls
def get_extra_ik_controls(self):
- return []
+ if self.component_ik_pivot:
+ return [self.component_ik_pivot.control]
+ else:
+ return []
def get_all_ik_controls(self):
ctrl = self.bones.ctrl
- return [ctrl.ik_base, ctrl.ik_pole, ctrl.ik] + self.get_extra_ik_controls()
+ controls = [ctrl.ik_base, ctrl.ik_pole, ctrl.ik]
+ return controls + self.get_extra_ik_controls()
@stage.generate_bones
def make_ik_controls(self):
orgs = self.bones.org.main
- self.bones.ctrl.ik_base = self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik'))
+ self.bones.ctrl.ik_base = self.make_ik_base_bone(orgs)
self.bones.ctrl.ik_pole = self.make_ik_pole_bone(orgs)
- self.bones.ctrl.ik = self.make_ik_control_bone(orgs)
+ self.bones.ctrl.ik = ik_name = self.make_ik_control_bone(orgs)
+ self.component_ik_pivot = self.build_ik_pivot(ik_name)
self.build_ik_parent_switch(SwitchParentBuilder(self.generator))
+ def make_ik_base_bone(self, orgs):
+ return self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik'))
+
def make_ik_pole_bone(self, orgs):
name = self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik_target'))
@@ -357,10 +361,25 @@ class BaseLimbRig(BaseRig):
def make_ik_control_bone(self, orgs):
return self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
+ def build_ik_pivot(self, ik_name, **args):
+ if self.use_ik_pivot:
+ return CustomPivotControl(self, 'ik_pivot', ik_name, parent=ik_name, **args)
+
+ def get_ik_control_output(self):
+ if self.component_ik_pivot:
+ return self.component_ik_pivot.output
+ else:
+ return self.bones.ctrl.ik
+
def register_switch_parents(self, pbuilder):
if self.rig_parent_bone:
pbuilder.register_parent(self, self.rig_parent_bone)
+ pbuilder.register_parent(
+ self, self.get_ik_control_output, name=self.bones.ctrl.ik,
+ exclude_self=True, tags={'limb_ik', 'child'},
+ )
+
def build_ik_parent_switch(self, pbuilder):
ctrl = self.bones.ctrl
@@ -398,9 +417,13 @@ class BaseLimbRig(BaseRig):
@stage.generate_widgets
def make_ik_control_widgets(self):
- self.make_ik_base_widget(self.bones.ctrl.ik_base)
- self.make_ik_pole_widget(self.bones.ctrl.ik_pole)
- self.make_ik_ctrl_widget(self.bones.ctrl.ik)
+ ctrl = self.bones.ctrl
+
+ set_bone_widget_transform(self.obj, ctrl.ik, self.get_ik_control_output())
+
+ self.make_ik_base_widget(ctrl.ik_base)
+ self.make_ik_pole_widget(ctrl.ik_pole)
+ self.make_ik_ctrl_widget(ctrl.ik)
def make_ik_base_widget(self, ctrl):
if self.main_axis == 'x':
@@ -453,7 +476,7 @@ class BaseLimbRig(BaseRig):
ik_input_head_tail = 0.0
def get_ik_input_bone(self):
- return self.bones.ctrl.ik
+ return self.get_ik_control_output()
def get_ik_output_chain(self):
return [self.bones.ctrl.ik_base, self.bones.mch.ik_end, self.bones.mch.ik_target]
@@ -670,7 +693,13 @@ class BaseLimbRig(BaseRig):
@stage.parent_bones
def parent_tweak_mch_chain(self):
- for mch, entry in zip(self.bones.mch.tweak, self.segment_table_tweak):
+ for args in zip(count(0), self.bones.mch.tweak, self.segment_table_tweak):
+ self.parent_tweak_mch_bone(*args)
+
+ def parent_tweak_mch_bone(self, i, mch, entry):
+ if i == 0:
+ self.set_bone_parent(mch, self.rig_parent_bone, inherit_scale='FIX_SHEAR')
+ else:
self.set_bone_parent(mch, entry.org)
@stage.rig_bones
@@ -694,6 +723,10 @@ class BaseLimbRig(BaseRig):
elif entry.seg_idx is not None:
self.make_constraint(tweak, 'COPY_SCALE', 'root', use_make_uniform=True)
+ if i == 0:
+ self.make_constraint(tweak, 'COPY_LOCATION', entry.org)
+ self.make_constraint(tweak, 'DAMPED_TRACK', entry.org, head_tail=1)
+
####################################################
# Deform chain
@@ -786,17 +819,23 @@ class BaseLimbRig(BaseRig):
)
params.segments = bpy.props.IntProperty(
- name = 'limb segments',
+ name = 'Limb Segments',
default = 2,
min = 1,
- description = 'Number of segments'
+ description = 'Number of limb segments'
)
params.bbones = bpy.props.IntProperty(
- name = 'bbone segments',
+ name = 'B-Bone Segments',
default = 10,
min = 1,
- description = 'Number of segments'
+ description = 'Number of B-Bone segments'
+ )
+
+ params.make_custom_pivot = bpy.props.BoolProperty(
+ name = "Custom Pivot Control",
+ default = False,
+ description = "Create a rotation pivot control that can be repositioned arbitrarily"
)
# Setting up extra layers for the FK and tweak
@@ -820,6 +859,8 @@ class BaseLimbRig(BaseRig):
r = layout.row()
r.prop(params, "bbones")
+ layout.prop(params, 'make_custom_pivot', text="Custom IK Pivot")
+
ControlLayersOption.FK.parameters_ui(layout, params)
ControlLayersOption.TWEAK.parameters_ui(layout, params)
@@ -843,8 +884,6 @@ class RigifyLimbIk2FkBase:
ctrl_bones: StringProperty(name="IK Controls")
extra_ctrls: StringProperty(name="Extra IK Controls")
- keyflags = None
-
def init_execute(self, context):
if self.fk_bones:
self.fk_bone_list = json.loads(self.fk_bones)
@@ -921,13 +960,11 @@ class RigifyLimbIk2FkBase:
class POSE_OT_rigify_limb_ik2fk(RigifyLimbIk2FkBase, RigifySingleUpdateMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_ik2fk_" + rig_id
bl_label = "Snap IK->FK"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Snap the IK chain to FK result"
class POSE_OT_rigify_limb_ik2fk_bake(RigifyLimbIk2FkBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_ik2fk_bake_" + rig_id
bl_label = "Apply Snap IK->FK To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Snap the IK chain keyframes to FK result"
def execute_scan_curves(self, context, obj):
@@ -968,8 +1005,6 @@ SCRIPT_UTILITIES_OP_TOGGLE_POLE = SCRIPT_UTILITIES_OP_SNAP_IK_FK + ['''
class RigifyLimbTogglePoleBase(RigifyLimbIk2FkBase):
use_pole: bpy.props.BoolProperty(name="Use Pole Vector")
- keyflags_switch = None
-
def save_frame_state(self, context, obj):
return get_chain_transform_matrices(obj, self.ik_bone_list)
@@ -1007,13 +1042,11 @@ class RigifyLimbTogglePoleBase(RigifyLimbIk2FkBase):
class POSE_OT_rigify_limb_toggle_pole(RigifyLimbTogglePoleBase, RigifySingleUpdateMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_toggle_pole_" + rig_id
bl_label = "Toggle Pole"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Switch the IK chain between pole and rotation"
class POSE_OT_rigify_limb_toggle_pole_bake(RigifyLimbTogglePoleBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_toggle_pole_bake_" + rig_id
bl_label = "Apply Toggle Pole To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Switch the IK chain between pole and rotation over a frame range"
def execute_scan_curves(self, context, obj):
diff --git a/rigify/rigs/limbs/paw.py b/rigify/rigs/limbs/paw.py
index f8cb1f9f..28374eec 100644
--- a/rigify/rigs/limbs/paw.py
+++ b/rigify/rigs/limbs/paw.py
@@ -84,7 +84,7 @@ class Rig(BaseLimbRig):
# IK controls
def get_extra_ik_controls(self):
- return [self.bones.ctrl.heel]
+ return super().get_extra_ik_controls() + [self.bones.ctrl.heel]
def make_ik_control_bone(self, orgs):
name = self.copy_bone(orgs[3], make_derived_name(orgs[2], 'ctrl', '_ik'))
@@ -107,7 +107,7 @@ class Rig(BaseLimbRig):
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[3], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[3], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
create_foot_widget(self.obj, ctrl)
@@ -126,7 +126,7 @@ class Rig(BaseLimbRig):
@stage.parent_bones
def parent_heel_control_bone(self):
- self.set_bone_parent(self.bones.ctrl.heel, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.ctrl.heel, self.get_ik_control_output())
@stage.configure_bones
def configure_heel_control_bone(self):
@@ -150,7 +150,7 @@ class Rig(BaseLimbRig):
def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
if i == 3:
self.set_bone_parent(parent_mch, prev_org, use_connect=True)
- self.set_bone_parent(self.bones.mch.toe_socket, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.mch.toe_socket, self.get_ik_control_output())
else:
super().parent_fk_parent_bone(i, parent_mch, prev_ctrl, org, prev_org)
diff --git a/rigify/rigs/limbs/simple_tentacle.py b/rigify/rigs/limbs/simple_tentacle.py
index 10bdd2b5..25d26e86 100644
--- a/rigify/rigs/limbs/simple_tentacle.py
+++ b/rigify/rigs/limbs/simple_tentacle.py
@@ -78,7 +78,7 @@ class Rig(TweakChainRig):
)
# Widgets
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
diff --git a/rigify/rigs/limbs/super_finger.py b/rigify/rigs/limbs/super_finger.py
index 1a9171a7..0b3fcd8a 100644
--- a/rigify/rigs/limbs/super_finger.py
+++ b/rigify/rigs/limbs/super_finger.py
@@ -24,11 +24,12 @@ import re
from itertools import count
from ...utils.errors import MetarigError
-from ...utils.bones import flip_bone, align_chain_x_axis
+from ...utils.bones import put_bone, flip_bone, align_chain_x_axis, set_bone_widget_transform
from ...utils.naming import make_derived_name
from ...utils.widgets import create_widget
from ...utils.widgets_basic import create_circle_widget
from ...utils.misc import map_list
+from ...utils.layers import ControlLayersOption
from ...base_rig import stage
@@ -40,7 +41,7 @@ class Rig(SimpleChainRig):
def initialize(self):
super().initialize()
- self.bbone_segments = 8
+ self.bbone_segments = self.params.bbones
self.first_parent = self.get_bone_parent(self.bones.org[0])
def prepare_bones(self):
@@ -116,6 +117,8 @@ class Rig(SimpleChainRig):
for args in zip(count(0), self.bones.ctrl.fk, self.bones.org + [None]):
self.configure_control_bone(*args)
+ ControlLayersOption.TWEAK.assign(self.params, self.obj, self.bones.ctrl.fk)
+
def configure_control_bone(self, i, ctrl, org):
if org:
self.copy_bone_properties(org, ctrl)
@@ -125,11 +128,13 @@ class Rig(SimpleChainRig):
bone.lock_rotation = (True, True, True)
bone.lock_scale = (True, True, True)
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
if ctrl == self.bones.ctrl.fk[-1]:
# Tip control
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.0)
else:
+ set_bone_widget_transform(self.obj, ctrl, self.bones.org[i])
+
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
##############################
@@ -234,11 +239,12 @@ class Rig(SimpleChainRig):
def configure_master_properties(self):
master = self.bones.ctrl.master
- self.make_property(master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect")
+ if self.bbone_segments > 1:
+ self.make_property(master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect")
- # Create UI
- panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten())
- panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True)
+ # Create UI
+ panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten())
+ panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True)
def rig_deform_bone(self, i, deform, org):
master = self.bones.ctrl.master
@@ -246,8 +252,9 @@ class Rig(SimpleChainRig):
self.make_constraint(deform, 'COPY_TRANSFORMS', org)
- self.make_driver(bone.bone, 'bbone_easein', variables=[(master, 'finger_curve')])
- self.make_driver(bone.bone, 'bbone_easeout', variables=[(master, 'finger_curve')])
+ if self.bbone_segments > 1:
+ self.make_driver(bone.bone, 'bbone_easein', variables=[(master, 'finger_curve')])
+ self.make_driver(bone.bone, 'bbone_easeout', variables=[(master, 'finger_curve')])
###############
# OPTIONS
@@ -261,6 +268,15 @@ class Rig(SimpleChainRig):
('-X', '-X manual', ''), ('-Y', '-Y manual', ''), ('-Z', '-Z manual', '')]
params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='automatic')
+ params.bbones = bpy.props.IntProperty(
+ name = 'B-Bone Segments',
+ default = 10,
+ min = 1,
+ description = 'Number of B-Bone segments'
+ )
+
+ ControlLayersOption.TWEAK.add_parameters(params)
+
@classmethod
def parameters_ui(self, layout, params):
""" Create the ui for the rig parameters.
@@ -269,6 +285,10 @@ class Rig(SimpleChainRig):
r.label(text="Bend rotation axis:")
r.prop(params, "primary_rotation_axis", text="")
+ layout.prop(params, 'bbones')
+
+ ControlLayersOption.TWEAK.parameters_ui(layout, params)
+
def create_sample(obj):
# generated by rigify.utils.write_metarig
@@ -321,10 +341,6 @@ def create_sample(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
- pbone.rigify_parameters.separate_extra_layers = True
- except AttributeError:
- pass
- try:
pbone.rigify_parameters.extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
diff --git a/rigify/rigs/limbs/super_palm.py b/rigify/rigs/limbs/super_palm.py
index 8bcbabf8..9c03b2fe 100644
--- a/rigify/rigs/limbs/super_palm.py
+++ b/rigify/rigs/limbs/super_palm.py
@@ -24,6 +24,7 @@ import re
from math import cos, pi
from itertools import count, repeat
+from rigify.utils.rig import is_rig_base_bone
from rigify.utils.naming import strip_org, make_derived_name
from rigify.utils.widgets import create_widget
from rigify.utils.misc import map_list
@@ -43,7 +44,7 @@ def bone_siblings(obj, bone):
bones = []
for b in parent.children:
- if b.name != bone:
+ if b.name != bone and not is_rig_base_bone(obj, b.name):
bones += [b.name]
return bones