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')
-rw-r--r--rigify/rigs/basic/copy_chain.py176
-rw-r--r--rigify/rigs/basic/super_copy.py151
-rw-r--r--rigify/rigs/chain_rigs.py387
-rw-r--r--rigify/rigs/experimental/super_chain.py2
-rw-r--r--rigify/rigs/faces/super_face.py2
-rw-r--r--rigify/rigs/limbs/arm.py122
-rw-r--r--rigify/rigs/limbs/leg.py130
-rw-r--r--rigify/rigs/limbs/super_limb.py2
-rw-r--r--rigify/rigs/spines/super_spine.py10
9 files changed, 598 insertions, 384 deletions
diff --git a/rigify/rigs/basic/copy_chain.py b/rigify/rigs/basic/copy_chain.py
index 4e426284..5145d735 100644
--- a/rigify/rigs/basic/copy_chain.py
+++ b/rigify/rigs/basic/copy_chain.py
@@ -20,124 +20,96 @@
import bpy
-from ...utils import MetarigError
-from ...utils import copy_bone
-from ...utils import connected_children_names
-from ...utils import strip_org, make_deformer_name
-from ...utils import create_bone_widget
+from ..chain_rigs import SimpleChainRig
+from ...utils.errors import MetarigError
+from ...utils.rig import connected_children_names
+from ...utils.naming import strip_org, make_deformer_name
+from ...utils.widgets_basic import create_bone_widget
-class Rig:
+from ...base_rig import BaseRig, stage
+
+
+class Rig(SimpleChainRig):
""" A "copy_chain" rig. All it does is duplicate the original bone chain
and constrain it.
This is a control and deformation rig.
-
"""
- def __init__(self, obj, bone_name, params):
+ def initialize(self):
+ super().initialize()
+
""" Gather and validate data about the rig.
"""
- self.obj = obj
- self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
- self.params = params
- self.make_controls = params.make_controls
- self.make_deforms = params.make_deforms
+ self.make_controls = self.params.make_controls
+ self.make_deforms = self.params.make_deforms
- if len(self.org_bones) <= 1:
- raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone_name)))
+ ##############################
+ # Control chain
- def generate(self):
- """ Generate the rig.
- Do NOT modify any of the original bones, except for adding constraints.
- The main armature should be selected and active before this is called.
+ @stage.generate_bones
+ def make_control_chain(self):
+ if self.make_controls:
+ super().make_control_chain()
- """
- bpy.ops.object.mode_set(mode='EDIT')
-
- # Create the deformation and control bone chains.
- # Just copies of the original chain.
- def_chain = []
- ctrl_chain = []
- for i in range(len(self.org_bones)):
- name = self.org_bones[i]
-
- # Control bone
- if self.make_controls:
- # Copy
- ctrl_bone = copy_bone(self.obj, name)
- eb = self.obj.data.edit_bones
- ctrl_bone_e = eb[ctrl_bone]
- # Name
- ctrl_bone_e.name = strip_org(name)
- # Parenting
- if i == 0:
- # First bone
- ctrl_bone_e.parent = eb[self.org_bones[0]].parent
- else:
- # The rest
- ctrl_bone_e.parent = eb[ctrl_chain[-1]]
- # Add to list
- ctrl_chain += [ctrl_bone_e.name]
- else:
- ctrl_chain += [None]
-
- # Deformation bone
- if self.make_deforms:
- # Copy
- def_bone = copy_bone(self.obj, name)
- eb = self.obj.data.edit_bones
- def_bone_e = eb[def_bone]
- # Name
- def_bone_e.name = make_deformer_name(strip_org(name))
- # Parenting
- if i == 0:
- # First bone
- def_bone_e.parent = eb[self.org_bones[0]].parent
- else:
- # The rest
- def_bone_e.parent = eb[def_chain[-1]]
- # Add to list
- def_chain += [def_bone_e.name]
- else:
- def_chain += [None]
-
- bpy.ops.object.mode_set(mode='OBJECT')
- pb = self.obj.pose.bones
-
- # Constraints for org and def
- for org, ctrl, defrm in zip(self.org_bones, ctrl_chain, def_chain):
- if self.make_controls:
- con = pb[org].constraints.new('COPY_TRANSFORMS')
- con.name = "copy_transforms"
- con.target = self.obj
- con.subtarget = ctrl
-
- if self.make_deforms:
- con = pb[defrm].constraints.new('COPY_TRANSFORMS')
- con.name = "copy_transforms"
- con.target = self.obj
- con.subtarget = org
-
- # Create control widgets
+ @stage.parent_bones
+ def parent_control_chain(self):
if self.make_controls:
- for bone in ctrl_chain:
- create_bone_widget(self.obj, bone)
+ super().parent_control_chain()
+ @stage.configure_bones
+ def configure_control_chain(self):
+ if self.make_controls:
+ super().configure_control_chain()
-def add_parameters(params):
- """ Add the parameters of this rig type to the
- RigifyParameters PropertyGroup
- """
- params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy")
- params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy")
+ @stage.generate_widgets
+ def make_control_widgets(self):
+ if self.make_controls:
+ super().make_control_widgets()
+ ##############################
+ # ORG chain
-def parameters_ui(layout, params):
- """ Create the ui for the rig parameters.
- """
- r = layout.row()
- r.prop(params, "make_controls")
- r = layout.row()
- r.prop(params, "make_deforms")
+ @stage.rig_bones
+ def rig_org_chain(self):
+ if self.make_controls:
+ super().rig_org_chain()
+
+ ##############################
+ # Deform chain
+
+ @stage.generate_bones
+ def make_deform_chain(self):
+ if self.make_deforms:
+ super().make_deform_chain()
+
+ @stage.parent_bones
+ def parent_deform_chain(self):
+ if self.make_deforms:
+ super().parent_deform_chain()
+
+ @stage.rig_bones
+ def rig_deform_chain(self):
+ if self.make_deforms:
+ super().rig_deform_chain()
+
+
+ @classmethod
+ def add_parameters(self, params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy")
+ params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy")
+
+
+ @classmethod
+ def parameters_ui(self, layout, params):
+ """ Create the ui for the rig parameters.
+ """
+ r = layout.row()
+ r.prop(params, "make_controls")
+ r = layout.row()
+ r.prop(params, "make_deforms")
def create_sample(obj):
diff --git a/rigify/rigs/basic/super_copy.py b/rigify/rigs/basic/super_copy.py
index b2045346..5abbf22e 100644
--- a/rigify/rigs/basic/super_copy.py
+++ b/rigify/rigs/basic/super_copy.py
@@ -20,107 +20,112 @@
import bpy
-from ...utils import copy_bone
-from ...utils import strip_org, make_deformer_name
-from ...utils import create_bone_widget, create_circle_widget
+from ...base_rig import BaseRig
+from ...utils.naming import strip_org, make_deformer_name
+from ...utils.widgets_basic import create_bone_widget, create_circle_widget
-class Rig:
+
+class Rig(BaseRig):
""" A "copy" rig. All it does is duplicate the original bone and
constrain it.
This is a control and deformation rig.
"""
- def __init__(self, obj, bone, params):
+ def find_org_bones(self, pose_bone):
+ return pose_bone.name
+
+
+ def initialize(self):
""" Gather and validate data about the rig.
"""
- self.obj = obj
- self.org_bone = bone
- self.org_name = strip_org(bone)
- self.params = params
- self.make_control = params.make_control
- self.make_widget = params.make_widget
- self.make_deform = params.make_deform
-
- def generate(self):
- """ Generate the rig.
- Do NOT modify any of the original bones, except for adding constraints.
- The main armature should be selected and active before this is called.
+ self.org_name = strip_org(self.bones.org)
- """
- bpy.ops.object.mode_set(mode='EDIT')
+ self.make_control = self.params.make_control
+ self.make_widget = self.params.make_widget
+ self.make_deform = self.params.make_deform
+
+
+ def generate_bones(self):
+ bones = self.bones
# Make a control bone (copy of original).
if self.make_control:
- bone = copy_bone(self.obj, self.org_bone, self.org_name)
+ bones.ctrl = self.copy_bone(bones.org, self.org_name, parent=True)
# Make a deformation bone (copy of original, child of original).
if self.make_deform:
- def_bone = copy_bone(self.obj, self.org_bone, make_deformer_name(self.org_name))
+ bones.deform = self.copy_bone(bones.org, make_deformer_name(self.org_name), bbone=True)
- # Get edit bones
- eb = self.obj.data.edit_bones
- # UNUSED
- # if self.make_control:
- # bone_e = eb[bone]
- if self.make_deform:
- def_bone_e = eb[def_bone]
- # Parent
+ def parent_bones(self):
+ bones = self.bones
+
if self.make_deform:
- def_bone_e.use_connect = False
- def_bone_e.parent = eb[self.org_bone]
+ self.set_bone_parent(bones.deform, bones.org, use_connect=False)
+
- bpy.ops.object.mode_set(mode='OBJECT')
- pb = self.obj.pose.bones
+ def configure_bones(self):
+ bones = self.bones
+
+ if self.make_control:
+ self.copy_bone_properties(bones.org, bones.ctrl)
+
+
+ def rig_bones(self):
+ bones = self.bones
if self.make_control:
# Constrain the original bone.
- con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS')
- con.name = "copy_transforms"
- con.target = self.obj
- con.subtarget = bone
+ self.make_constraint(bones.org, 'COPY_TRANSFORMS', bones.ctrl)
+
+ def generate_widgets(self):
+ bones = self.bones
+
+ if self.make_control:
# Create control widget
if self.make_widget:
- create_circle_widget(self.obj, bone, radius=0.5)
+ create_circle_widget(self.obj, bones.ctrl, radius=0.5)
else:
- create_bone_widget(self.obj, bone)
+ create_bone_widget(self.obj, bones.ctrl)
-def add_parameters(params):
- """ Add the parameters of this rig type to the
- RigifyParameters PropertyGroup
- """
- params.make_control = bpy.props.BoolProperty(
- name = "Control",
- default = True,
- description = "Create a control bone for the copy"
- )
-
- params.make_widget = bpy.props.BoolProperty(
- name = "Widget",
- default = True,
- description = "Choose a widget for the bone control"
- )
-
- params.make_deform = bpy.props.BoolProperty(
- name = "Deform",
- default = True,
- description = "Create a deform bone for the copy"
- )
-
-
-def parameters_ui(layout, params):
- """ Create the ui for the rig parameters.
- """
- r = layout.row()
- r.prop(params, "make_control")
- r = layout.row()
- r.prop(params, "make_widget")
- r.enabled = params.make_control
- r = layout.row()
- r.prop(params, "make_deform")
+ @classmethod
+ def add_parameters(self, params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.make_control = bpy.props.BoolProperty(
+ name = "Control",
+ default = True,
+ description = "Create a control bone for the copy"
+ )
+
+ params.make_widget = bpy.props.BoolProperty(
+ name = "Widget",
+ default = True,
+ description = "Choose a widget for the bone control"
+ )
+
+ params.make_deform = bpy.props.BoolProperty(
+ name = "Deform",
+ default = True,
+ description = "Create a deform bone for the copy"
+ )
+
+
+ @classmethod
+ def parameters_ui(self, layout, params):
+ """ Create the ui for the rig parameters.
+ """
+ r = layout.row()
+ r.prop(params, "make_control")
+ r = layout.row()
+ r.prop(params, "make_widget")
+ r.enabled = params.make_control
+ r = layout.row()
+ r.prop(params, "make_deform")
def create_sample(obj):
@@ -159,3 +164,5 @@ def create_sample(obj):
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone
+
+ return bones
diff --git a/rigify/rigs/chain_rigs.py b/rigify/rigs/chain_rigs.py
new file mode 100644
index 00000000..3f53cd69
--- /dev/null
+++ b/rigify/rigs/chain_rigs.py
@@ -0,0 +1,387 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+# <pep8 compliant>
+
+import bpy
+from itertools import count
+
+from ..utils.rig import connected_children_names
+from ..utils.naming import strip_org, make_derived_name
+from ..utils.bones import put_bone, flip_bone, flip_bone_chain, is_same_position, is_connected_position
+from ..utils.bones import copy_bone_position, connect_bbone_chain_handles
+from ..utils.widgets_basic import create_bone_widget, create_sphere_widget
+from ..utils.misc import map_list
+
+from ..base_rig import BaseRig, stage
+
+
+class SimpleChainRig(BaseRig):
+ """A rig that consists of 3 connected chains of control, org and deform bones."""
+ def find_org_bones(self, bone):
+ return [bone.name] + connected_children_names(self.obj, bone.name)
+
+ def initialize(self):
+ if len(self.bones.org) <= 1:
+ self.raise_error("Input to rig type must be a chain of 2 or more bones.")
+
+ def parent_bones(self):
+ self.rig_parent_bone = self.get_bone_parent(self.bones.org[0])
+
+ bbone_segments = None
+
+ ##############################
+ # BONES
+ #
+ # org[]:
+ # ORG bones
+ # ctrl:
+ # fk[]:
+ # FK control chain.
+ # deform[]:
+ # DEF bones
+ #
+ ##############################
+
+ ##############################
+ # Control chain
+
+ @stage.generate_bones
+ def make_control_chain(self):
+ self.bones.ctrl.fk = map_list(self.make_control_bone, count(0), self.bones.org)
+
+ def make_control_bone(self, i, org):
+ return self.copy_bone(org, make_derived_name(org, 'ctrl'), parent=True)
+
+ @stage.parent_bones
+ def parent_control_chain(self):
+ self.parent_bone_chain(self.bones.ctrl.fk, use_connect=True)
+
+ @stage.configure_bones
+ def configure_control_chain(self):
+ for args in zip(count(0), self.bones.ctrl.fk, self.bones.org):
+ self.configure_control_bone(*args)
+
+ def configure_control_bone(self, i, ctrl, org):
+ self.copy_bone_properties(org, ctrl)
+
+ @stage.generate_widgets
+ def make_control_widgets(self):
+ for ctrl in self.bones.ctrl.fk:
+ self.make_control_widget(ctrl)
+
+ def make_control_widget(self, ctrl):
+ create_bone_widget(self.obj, ctrl)
+
+ ##############################
+ # ORG chain
+
+ @stage.parent_bones
+ def parent_org_chain(self):
+ pass
+
+ @stage.rig_bones
+ def rig_org_chain(self):
+ for args in zip(count(0), self.bones.org, self.bones.ctrl.fk):
+ self.rig_org_bone(*args)
+
+ def rig_org_bone(self, i, org, ctrl):
+ self.make_constraint(org, 'COPY_TRANSFORMS', ctrl)
+
+ ##############################
+ # Deform chain
+
+ @stage.generate_bones
+ def make_deform_chain(self):
+ self.bones.deform = map_list(self.make_deform_bone, count(0), self.bones.org)
+
+ def make_deform_bone(self, i, org):
+ name = self.copy_bone(org, make_derived_name(org, 'def'), parent=True, bbone=True)
+ if self.bbone_segments:
+ self.get_bone(name).bbone_segments = self.bbone_segments
+ return name
+
+ @stage.parent_bones
+ def parent_deform_chain(self):
+ self.parent_bone_chain(self.bones.deform, use_connect=True)
+
+ @stage.rig_bones
+ def rig_deform_chain(self):
+ for args in zip(count(0), self.bones.deform, self.bones.org):
+ self.rig_deform_bone(*args)
+
+ def rig_deform_bone(self, i, deform, org):
+ self.make_constraint(deform, 'COPY_TRANSFORMS', org)
+
+
+class TweakChainRig(SimpleChainRig):
+ """A rig that adds tweak controls to the triple chain."""
+
+ ##############################
+ # BONES
+ #
+ # org[]:
+ # ORG bones
+ # ctrl:
+ # fk[]:
+ # FK control chain.
+ # tweak[]:
+ # Tweak control chain.
+ # deform[]:
+ # DEF bones
+ #
+ ##############################
+
+ ##############################
+ # Tweak chain
+
+ @stage.generate_bones
+ def make_tweak_chain(self):
+ orgs = self.bones.org
+ self.bones.ctrl.tweak = map_list(self.make_tweak_bone, count(0), orgs + orgs[-1:])
+
+ def make_tweak_bone(self, i, org):
+ name = self.copy_bone(org, 'tweak_' + strip_org(org), parent=False, scale=0.5)
+
+ if i == len(self.bones.org):
+ put_bone(self.obj, name, self.get_bone(org).tail)
+
+ return name
+
+ @stage.parent_bones
+ def parent_tweak_chain(self):
+ ctrl = self.bones.ctrl
+ for tweak, main in zip(ctrl.tweak, ctrl.fk + ctrl.fk[-1:]):
+ self.set_bone_parent(tweak, main)
+
+ @stage.configure_bones
+ def configure_tweak_chain(self):
+ for args in zip(count(0), self.bones.ctrl.tweak):
+ self.configure_tweak_bone(*args)
+
+ def configure_tweak_bone(self, i, tweak):
+ tweak_pb = self.get_bone(tweak)
+ tweak_pb.rotation_mode = 'ZXY'
+
+ if i == len(self.bones.org):
+ tweak_pb.lock_rotation_w = True
+ tweak_pb.lock_rotation = (True, True, True)
+ tweak_pb.lock_scale = (True, True, True)
+ else:
+ tweak_pb.lock_rotation_w = False
+ tweak_pb.lock_rotation = (True, False, True)
+ tweak_pb.lock_scale = (False, True, False)
+
+ @stage.generate_widgets
+ def make_tweak_widgets(self):
+ for tweak in self.bones.ctrl.tweak:
+ self.make_tweak_widget(tweak)
+
+ def make_tweak_widget(self, tweak):
+ create_sphere_widget(self.obj, tweak)
+
+ ##############################
+ # ORG chain
+
+ @stage.rig_bones
+ def rig_org_chain(self):
+ tweaks = self.bones.ctrl.tweak
+ for args in zip(count(0), self.bones.org, tweaks, tweaks[1:]):
+ self.rig_org_bone(*args)
+
+ def rig_org_bone(self, i, org, tweak, next_tweak):
+ self.make_constraint(org, 'COPY_TRANSFORMS', tweak)
+ if next_tweak:
+ self.make_constraint(org, 'DAMPED_TRACK', next_tweak)
+ self.make_constraint(org, 'STRETCH_TO', next_tweak)
+
+
+class ConnectingChainRig(TweakChainRig):
+ """Chain rig that can attach to an end of the parent, merging bbone chains."""
+
+ bbone_segments = 8
+ use_connect_reverse = None
+
+ def initialize(self):
+ super().initialize()
+
+ self.use_connect_chain = self.params.connect_chain
+ self.connected_tweak = None
+
+ if self.use_connect_chain:
+ first_org = self.bones.org[0]
+ parent = self.rigify_parent
+ parent_orgs = parent.bones.org
+
+ if not isinstance(parent, SimpleChainRig):
+ self.raise_error("Cannot connect to non-chain parent rig.")
+
+ ok_reverse = is_same_position(self.obj, parent_orgs[0], first_org)
+ ok_direct = is_connected_position(self.obj, parent_orgs[-1], first_org)
+
+ if self.use_connect_reverse is None:
+ self.use_connect_reverse = ok_reverse and not ok_direct
+
+ if not (ok_reverse if self.use_connect_reverse else ok_direct):
+ self.raise_error("Cannot connect chain - bone position is disjoint.")
+
+ if isinstance(parent, ConnectingChainRig) and parent.use_connect_reverse:
+ self.raise_error("Cannot connect chain - parent is reversed.")
+
+ def prepare_bones(self):
+ # Exactly match bone position to parent
+ if self.use_connect_chain:
+ first_bone = self.get_bone(self.bones.org[0])
+ parent_orgs = self.rigify_parent.bones.org
+
+ if self.use_connect_reverse:
+ first_bone.head = self.get_bone(parent_orgs[0]).head
+ else:
+ first_bone.head = self.get_bone(parent_orgs[-1]).tail
+
+ def parent_bones(self):
+ # Use the parent of the shared tweak as the rig parent
+ root = self.connected_tweak or self.bones.org[0]
+
+ self.rig_parent_bone = self.get_bone_parent(root)
+
+ ##############################
+ # Control chain
+
+ @stage.parent_bones
+ def parent_control_chain(self):
+ super().parent_control_chain()
+
+ self.set_bone_parent(self.bones.ctrl.fk[0], self.rig_parent_bone)
+
+ ##############################
+ # Tweak chain
+
+ def check_connect_tweak(self, org):
+ """ Check if it is possible to share the last parent tweak control. """
+
+ assert self.connected_tweak is None
+
+ if self.use_connect_chain and isinstance(self.rigify_parent, TweakChainRig):
+ # Share the last tweak bone of the parent rig
+ parent_tweaks = self.rigify_parent.bones.ctrl.tweak
+ index = 0 if self.use_connect_reverse else -1
+ name = parent_tweaks[index]
+
+ if not is_same_position(self.obj, name, org):
+ self.raise_error("Cannot connect tweaks - position mismatch.")
+
+ if not self.use_connect_reverse:
+ copy_bone_position(self.obj, org, name, scale=0.5)
+
+ name = self.rename_bone(name, 'tweak_' + strip_org(org))
+
+ self.connected_tweak = parent_tweaks[index] = name
+
+ return name
+ else:
+ return None
+
+ def make_tweak_bone(self, i, org):
+ if i == 0 and self.check_connect_tweak(org):
+ return self.connected_tweak
+ else:
+ return super().make_tweak_bone(i, org)
+
+ @stage.parent_bones
+ def parent_tweak_chain(self):
+ ctrl = self.bones.ctrl
+ for i, tweak, main in zip(count(0), ctrl.tweak, ctrl.fk + ctrl.fk[-1:]):
+ if i > 0 or not (self.connected_tweak and self.use_connect_reverse):
+ self.set_bone_parent(tweak, main)
+
+ def configure_tweak_bone(self, i, tweak):
+ super().configure_tweak_bone(i, tweak)
+
+ if self.use_connect_chain and self.use_connect_reverse and i == len(self.bones.org):
+ tweak_pb = self.get_bone(tweak)
+ tweak_pb.lock_rotation_w = False
+ tweak_pb.lock_rotation = (True, False, True)
+ tweak_pb.lock_scale = (False, True, False)
+
+ ##############################
+ # ORG chain
+
+ @stage.parent_bones
+ def parent_org_chain(self):
+ if self.use_connect_chain and self.use_connect_reverse:
+ flip_bone_chain(self.obj, self.bones.org)
+
+ for org, tweak in zip(self.bones.org, self.bones.ctrl.tweak[1:]):
+ self.set_bone_parent(org, tweak)
+
+ else:
+ self.set_bone_parent(self.bones.org[0], self.rig_parent_bone)
+
+ def rig_org_bone(self, i, org, tweak, next_tweak):
+ if self.use_connect_chain and self.use_connect_reverse:
+ self.make_constraint(org, 'DAMPED_TRACK', tweak)
+ self.make_constraint(org, 'STRETCH_TO', tweak)
+ else:
+ super().rig_org_bone(i, org, tweak, next_tweak)
+
+ ##############################
+ # Deform chain
+
+ def make_deform_bone(self, i, org):
+ name = super().make_deform_bone(i, org)
+
+ if self.use_connect_chain and self.use_connect_reverse:
+ self.set_bone_parent(name, None)
+ flip_bone(self.obj, name)
+
+ return name
+
+ @stage.parent_bones
+ def parent_deform_chain(self):
+ if self.use_connect_chain:
+ deform = self.bones.deform
+ parent_deform = self.rigify_parent.bones.deform
+
+ if self.use_connect_reverse:
+ self.set_bone_parent(deform[-1], self.bones.org[-1])
+ self.parent_bone_chain(reversed(deform), use_connect=True)
+
+ connect_bbone_chain_handles(self.obj, [ deform[0], parent_deform[0] ])
+ return
+
+ else:
+ self.set_bone_parent(deform[0], parent_deform[-1], use_connect=True)
+
+ super().parent_deform_chain()
+
+ ##############################
+ # Settings
+
+ @classmethod
+ def add_parameters(self, params):
+ params.connect_chain = bpy.props.BoolProperty(
+ name='Connect chain',
+ default=False,
+ description='Connect the B-Bone chain to the parent rig'
+ )
+
+ @classmethod
+ def parameters_ui(self, layout, params):
+ r = layout.row()
+ r.prop(params, "connect_chain")
diff --git a/rigify/rigs/experimental/super_chain.py b/rigify/rigs/experimental/super_chain.py
index f3d0e182..592441fe 100644
--- a/rigify/rigs/experimental/super_chain.py
+++ b/rigify/rigs/experimental/super_chain.py
@@ -14,7 +14,7 @@ class Rig:
def __init__(self, obj, bone_name, params):
""" Chain with pivot Rig """
- eb = obj.data.edit_bones
+ eb = obj.data.bones
self.obj = obj
self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
diff --git a/rigify/rigs/faces/super_face.py b/rigify/rigs/faces/super_face.py
index 7e36ce68..4eda647d 100644
--- a/rigify/rigs/faces/super_face.py
+++ b/rigify/rigs/faces/super_face.py
@@ -44,7 +44,7 @@ class Rig:
grand_children += connected_children_names( self.obj, child )
self.org_bones = [bone_name] + children + grand_children
- self.face_length = obj.data.edit_bones[ self.org_bones[0] ].length
+ self.face_length = obj.data.bones[ self.org_bones[0] ].length
self.params = params
if params.primary_layers_extra:
diff --git a/rigify/rigs/limbs/arm.py b/rigify/rigs/limbs/arm.py
index 3b2f3658..aacc1e86 100644
--- a/rigify/rigs/limbs/arm.py
+++ b/rigify/rigs/limbs/arm.py
@@ -15,17 +15,8 @@ from ...utils.mechanism import make_property, make_driver
from ..widgets import create_ikarrow_widget
from math import trunc, pi
-extra_script = """
-controls = [%s]
-ctrl = '%s'
-
-if is_selected( controls ):
- 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 )
-"""
+from ...utils.switch_parent import SwitchParentBuilder
+
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
@@ -561,35 +552,6 @@ class Rig:
eb[ bones['ik']['mch_target'] ].parent = eb[ ctrl ]
eb[ bones['ik']['mch_target'] ].use_connect = False
- # MCH for ik control
- ctrl_socket = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_socket'))
- eb[ctrl_socket].tail = eb[ctrl_socket].head + 0.8*(eb[ctrl_socket].tail-eb[ctrl_socket].head)
- eb[ctrl_socket].parent = None
- eb[ctrl].parent = eb[ctrl_socket]
-
- # MCH for pole ik control
- ctrl_pole_socket = copy_bone(self.obj, org_bones[2], get_bone_name(org_bones[2], 'mch', 'pole_ik_socket'))
- eb[ctrl_pole_socket].tail = eb[ctrl_pole_socket].head + 0.8 * (eb[ctrl_pole_socket].tail - eb[ctrl_pole_socket].head)
- eb[ctrl_pole_socket].parent = None
- eb[pole_target].parent = eb[ctrl_pole_socket]
-
- ctrl_root = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_root'))
- eb[ctrl_root].tail = eb[ctrl_root].head + 0.7*(eb[ctrl_root].tail-eb[ctrl_root].head)
- eb[ctrl_root].use_connect = False
- eb[ctrl_root].parent = eb['root']
-
- if eb[org_bones[0]].parent:
- arm_parent = eb[org_bones[0]].parent
- ctrl_parent = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_parent'))
- eb[ctrl_parent].tail = eb[ctrl_parent].head + 0.6*(eb[ctrl_parent].tail-eb[ctrl_parent].head)
- eb[ctrl_parent].use_connect = False
- if eb[org_bones[0]].parent_recursive:
- eb[ctrl_parent].parent = eb[org_bones[0]].parent_recursive[-1]
- else:
- eb[ctrl_parent].parent = eb[org_bones[0]].parent
- else:
- arm_parent = None
-
mch_name = get_bone_name(strip_org(org_bones[0]), 'mch', 'parent_socket')
mch_main_parent = copy_bone(self.obj, org_bones[0], mch_name)
eb[mch_main_parent].length = eb[org_bones[0]].length / 12
@@ -597,30 +559,28 @@ class Rig:
eb[mch_main_parent].roll = 0.0
eb[bones['main_parent']].parent = eb[mch_main_parent]
- # Set up constraints
+ # Switchable parent
+ pbuilder = SwitchParentBuilder(self.rigify_generator)
- # Constrain ik ctrl to root / parent
+ if eb[org_bones[0]].parent:
+ pbuilder.register_parent(self.rigify_wrapper, eb[org_bones[0]].parent.name)
- make_constraint( self, ctrl_socket, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : ctrl_root,
- })
+ pbuilder.register_parent(self.rigify_wrapper, org_bones[2], exclude_self=True)
- make_constraint(self, ctrl_pole_socket, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': ctrl_root,
- })
+ pcontrols = [ bones['main_parent'], bones['ik']['ctrl']['limb'], ctrl, pole_target ]
- if arm_parent:
- make_constraint( self, ctrl_socket, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : ctrl_parent,
- })
+ pbuilder.build_child(
+ self.rigify_wrapper, ctrl,
+ prop_bone=bones['main_parent'], prop_id='IK_parent', prop_name='IK Parent', controls=pcontrols,
+ )
- make_constraint(self, ctrl_pole_socket, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': ctrl_parent,
- })
+ pbuilder.build_child(
+ self.rigify_wrapper, pole_target, extra_parents=[ctrl],
+ prop_bone=bones['main_parent'], prop_id='pole_parent', prop_name='Pole Parent', controls=pcontrols,
+ no_fix_rotation=True, no_fix_scale=True
+ )
+
+ # Set up constraints
# Constrain mch target bone to the ik control and mch stretch
make_constraint( self, bones['ik']['mch_target'], {
@@ -675,10 +635,6 @@ class Rig:
create_hand_widget(self.obj, ctrl, bone_transform_name=None)
bones['ik']['ctrl']['terminal'] = [ctrl]
- if arm_parent:
- bones['ik']['mch_hand'] = [ctrl_socket, ctrl_pole_socket, ctrl_root, ctrl_parent]
- else:
- bones['ik']['mch_hand'] = [ctrl_socket, ctrl_pole_socket, ctrl_root]
return bones
@@ -687,13 +643,10 @@ class Rig:
bpy.ops.object.mode_set(mode='OBJECT')
pb = self.obj.pose.bones
- ctrl = pb[bones['ik']['mch_hand'][0]]
- ctrl_pole = pb[bones['ik']['mch_hand'][1]]
-
#owner = pb[bones['ik']['ctrl']['limb']]
owner = pb[bones['main_parent']]
- props = ["IK_follow", "root/parent", "pole_vector", "pole_follow"]
+ props = ["pole_vector"]
for prop in props:
@@ -723,30 +676,6 @@ class Rig:
else:
make_driver(cns, "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
- elif prop == 'IK_follow':
- make_property(owner, prop, True)
-
- make_driver(ctrl.constraints[0], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- if len(ctrl.constraints) > 1:
- make_driver(ctrl.constraints[1], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- make_driver(ctrl_pole.constraints[0], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- if len(ctrl_pole.constraints) > 1:
- make_driver(ctrl_pole.constraints[1], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- elif prop == 'root/parent':
- if len(ctrl.constraints) > 1:
- make_property(owner, prop, 0.0)
-
- make_driver(ctrl.constraints[1], "influence", variables=[(self.obj, owner, prop)])
-
- elif prop == 'pole_follow':
- if len(ctrl_pole.constraints) > 1:
- make_property(owner, prop, 0.0)
-
- make_driver(ctrl_pole.constraints[1], "influence", variables=[(self.obj, owner, prop)])
@staticmethod
def get_future_names(bones):
@@ -822,22 +751,13 @@ class Rig:
bones = self.create_arm(bones)
self.create_drivers(bones)
- controls = [bones['ik']['ctrl']['limb'], bones['ik']['ctrl']['terminal'][0]]
-
- controls.append(bones['main_parent'])
-
# Create UI
- 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', 'pole_follow', 'root/parent', 'root/parent')
return {
'script': [script],
'utilities': UTILITIES_RIG_ARM,
'register': REGISTER_RIG_ARM,
- 'noparent_bones': [bones['ik']['mch_hand'][i] for i in [0,1]],
}
@@ -858,7 +778,7 @@ def add_parameters(params):
default = 'automatic'
)
- params.auto_align_extremity = bpy.BoolProperty(
+ params.auto_align_extremity = bpy.props.BoolProperty(
name='auto_align_extremity',
default=False,
description="Auto Align Extremity Bone"
diff --git a/rigify/rigs/limbs/leg.py b/rigify/rigs/limbs/leg.py
index 2b846eca..59e6f799 100644
--- a/rigify/rigs/limbs/leg.py
+++ b/rigify/rigs/limbs/leg.py
@@ -17,17 +17,8 @@ from ...utils.mechanism import make_property, make_driver
from ..widgets import create_ikarrow_widget
from math import trunc, pi
-extra_script = """
-controls = [%s]
-ctrl = '%s'
-
-if is_selected( controls ):
- 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 )
-"""
+from ...utils.switch_parent import SwitchParentBuilder
+
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
@@ -599,35 +590,6 @@ class Rig:
eb[ctrl].parent = None
eb[ctrl].use_connect = False
- # MCH for ik control
- ctrl_socket = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_socket'))
- eb[ctrl_socket].tail = eb[ctrl_socket].head + 0.8*(eb[ctrl_socket].tail-eb[ctrl_socket].head)
- eb[ctrl_socket].parent = None
- eb[ctrl].parent = eb[ctrl_socket]
-
- # MCH for pole ik control
- ctrl_pole_socket = copy_bone(self.obj, org_bones[2], get_bone_name(org_bones[2], 'mch', 'pole_ik_socket'))
- eb[ctrl_pole_socket].tail = eb[ctrl_pole_socket].head + 0.8 * (eb[ctrl_pole_socket].tail - eb[ctrl_pole_socket].head)
- eb[ctrl_pole_socket].parent = None
- eb[pole_target].parent = eb[ctrl_pole_socket]
-
- ctrl_root = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_root'))
- eb[ctrl_root].tail = eb[ctrl_root].head + 0.7*(eb[ctrl_root].tail-eb[ctrl_root].head)
- eb[ctrl_root].use_connect = False
- eb[ctrl_root].parent = eb['root']
-
- if eb[org_bones[0]].parent:
- leg_parent = eb[org_bones[0]].parent
- ctrl_parent = copy_bone(self.obj, org_bones[2], get_bone_name( org_bones[2], 'mch', 'ik_parent'))
- eb[ctrl_parent].tail = eb[ctrl_parent].head + 0.6*(eb[ctrl_parent].tail-eb[ctrl_parent].head)
- eb[ctrl_parent].use_connect = False
- if eb[org_bones[0]].parent_recursive:
- eb[ctrl_parent].parent = eb[org_bones[0]].parent_recursive[-1]
- else:
- eb[ctrl_parent].parent = eb[org_bones[0]].parent
- else:
- leg_parent = None
-
mch_name = get_bone_name(strip_org(org_bones[0]), 'mch', 'parent_socket')
mch_main_parent = copy_bone(self.obj, org_bones[0], mch_name)
eb[mch_main_parent].length = eb[org_bones[0]].length / 12
@@ -658,6 +620,26 @@ class Rig:
eb[ctrl].tail[2] = eb[ctrl].head[2]
eb[ctrl].roll = 0
+ # Switchable parent
+ pbuilder = SwitchParentBuilder(self.rigify_generator)
+
+ if eb[org_bones[0]].parent:
+ pbuilder.register_parent(self.rigify_wrapper, eb[org_bones[0]].parent.name)
+
+ pbuilder.register_parent(self.rigify_wrapper, org_bones[2], exclude_self=True)
+
+ pcontrols = [ bones['main_parent'], bones['ik']['ctrl']['limb'], heel, ctrl, pole_target ]
+
+ pbuilder.build_child(
+ self.rigify_wrapper, ctrl,
+ prop_bone=bones['main_parent'], prop_id='IK_parent', prop_name='IK Parent', controls=pcontrols,
+ )
+
+ pbuilder.build_child(
+ self.rigify_wrapper, pole_target, extra_parents=[(bones['ik']['mch_target'], ctrl)],
+ prop_bone=bones['main_parent'], prop_id='pole_parent', prop_name='Pole Parent', controls=pcontrols,
+ no_fix_rotation=True, no_fix_scale=True
+ )
# Parent
eb[ heel ].use_connect = False
@@ -847,30 +829,6 @@ class Rig:
# Set up constraints
- # Constrain ik ctrl to root / parent
-
- make_constraint( self, ctrl_socket, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : ctrl_root,
- })
-
- make_constraint(self, ctrl_pole_socket, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': ctrl_root,
- })
-
- if leg_parent:
- make_constraint( self, ctrl_socket, {
- 'constraint' : 'COPY_TRANSFORMS',
- 'subtarget' : ctrl_parent,
- 'influence' : 0.0,
- })
-
- make_constraint(self, ctrl_pole_socket, {
- 'constraint': 'COPY_TRANSFORMS',
- 'subtarget': bones['ik']['mch_target'],
- })
-
# Constrain mch target bone to the ik control and mch stretch
make_constraint( self, bones['ik']['mch_target'], {
'constraint' : 'COPY_LOCATION',
@@ -982,11 +940,6 @@ class Rig:
bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
- if leg_parent:
- bones['ik']['mch_foot'] = [ctrl_socket, ctrl_pole_socket, ctrl_root, ctrl_parent]
- else:
- bones['ik']['mch_foot'] = [ctrl_socket, ctrl_pole_socket, ctrl_root]
-
return bones
def create_drivers(self, bones):
@@ -994,13 +947,10 @@ class Rig:
bpy.ops.object.mode_set(mode='OBJECT')
pb = self.obj.pose.bones
- ctrl = pb[bones['ik']['mch_foot'][0]]
- ctrl_pole = pb[bones['ik']['mch_foot'][1]]
-
#owner = pb[bones['ik']['ctrl']['limb']]
owner = pb[bones['main_parent']]
- props = ["IK_follow", "root/parent", "pole_vector", "pole_follow"]
+ props = ["pole_vector"]
for prop in props:
@@ -1031,31 +981,6 @@ class Rig:
make_driver(cns, "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
- elif prop == 'IK_follow':
- make_property(owner, prop, True)
-
- make_driver(ctrl.constraints[0], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- if len(ctrl.constraints) > 1:
- make_driver(ctrl.constraints[1], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- make_driver(ctrl_pole.constraints[0], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- if len(ctrl_pole.constraints) > 1:
- make_driver(ctrl_pole.constraints[1], "mute", variables=[(self.obj, owner, prop)], polynomial=[1.0, -1.0])
-
- elif prop == 'root/parent':
- if len(ctrl.constraints) > 1:
- make_property(owner, prop, 0.0)
-
- make_driver(ctrl.constraints[1], "influence", variables=[(self.obj, owner, prop)])
-
- elif prop == 'pole_follow':
- if len(ctrl_pole.constraints) > 1:
- make_property(owner, prop, 0.0)
-
- make_driver(ctrl_pole.constraints[1], "influence", variables=[(self.obj, owner, prop)])
-
@staticmethod
def get_future_names(bones):
@@ -1133,22 +1058,13 @@ class Rig:
bones = self.create_leg(bones)
self.create_drivers(bones)
- controls = [bones['ik']['ctrl']['limb'], bones['ik']['ctrl']['terminal'][-1], bones['ik']['ctrl']['terminal'][-2] ]
-
- controls.append(bones['main_parent'])
-
# Create UI
- controls_string = ", ".join(["'" + x + "'" for x in controls])
-
script = create_script(bones, 'leg')
- script += extra_script % (controls_string, bones['main_parent'], 'IK_follow',
- 'pole_follow', 'pole_follow', 'root/parent', 'root/parent')
return {
'script': [script],
'utilities': UTILITIES_RIG_LEG,
'register': REGISTER_RIG_LEG,
- 'noparent_bones': [bones['ik']['mch_foot'][i] for i in [0,1]],
}
diff --git a/rigify/rigs/limbs/super_limb.py b/rigify/rigs/limbs/super_limb.py
index 3d2bb8e2..0d557bb7 100644
--- a/rigify/rigs/limbs/super_limb.py
+++ b/rigify/rigs/limbs/super_limb.py
@@ -21,6 +21,8 @@ class Rig:
self.limb = pawRig(obj, bone_name, params)
def generate(self):
+ self.limb.rigify_generator = self.rigify_generator
+ self.limb.rigify_wrapper = self.rigify_wrapper
return self.limb.generate()
diff --git a/rigify/rigs/spines/super_spine.py b/rigify/rigs/spines/super_spine.py
index 5afe15b0..ebc76fcb 100644
--- a/rigify/rigs/spines/super_spine.py
+++ b/rigify/rigs/spines/super_spine.py
@@ -8,6 +8,8 @@ from ...utils import MetarigError, make_mechanism_name, create_cube_widget
from ...utils import ControlLayersOption
from ...utils.mechanism import make_property, make_driver
+from ...utils.switch_parent import SwitchParentBuilder
+
script = """
controls = [%s]
torso = '%s'
@@ -951,6 +953,14 @@ class Rig:
bones['chest'] = self.create_chest(upper_torso_bones)
bones['hips'] = self.create_hips(lower_torso_bones)
+ # Register viable parent bones
+ pbuilder = SwitchParentBuilder(self.rigify_generator)
+ pbuilder.register_parent(self.rigify_wrapper, bones['pivot']['ctrl'], name='Torso')
+ pbuilder.register_parent(self.rigify_wrapper, bone_chains['lower'][0], name='Hips')
+ pbuilder.register_parent(self.rigify_wrapper, bone_chains['upper'][-1], name='Chest')
+ if self.use_head:
+ pbuilder.register_parent(self.rigify_wrapper, bone_chains['neck'][-1], name='Head')
+
# TODO: Add create tail
if tail_bones:
bones['tail'] = self.create_tail(tail_bones)