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:
authorLucio Rossi <lucio.rossi75@gmail.com>2017-05-14 19:30:06 +0300
committerLucio Rossi <lucio.rossi75@gmail.com>2017-05-14 19:30:06 +0300
commitf36789d8bc728bc7ec3c9738f1ca76e8f017ce7a (patch)
treeb21bf3b259ee87b4eafb1503936b15bee38be1ca /rigify/legacy/rigs
parent8e68bf2879d81780e51dbdc3481bb486e7430e74 (diff)
Rigify 0.5 with legacy mode
Diffstat (limited to 'rigify/legacy/rigs')
-rw-r--r--rigify/legacy/rigs/__init__.py0
-rw-r--r--rigify/legacy/rigs/basic/__init__.py0
-rw-r--r--rigify/legacy/rigs/basic/copy.py139
-rw-r--r--rigify/legacy/rigs/basic/copy_chain.py206
-rw-r--r--rigify/legacy/rigs/biped/__init__.py0
-rw-r--r--rigify/legacy/rigs/biped/arm/__init__.py306
-rw-r--r--rigify/legacy/rigs/biped/arm/deform.py58
-rw-r--r--rigify/legacy/rigs/biped/arm/fk.py86
-rw-r--r--rigify/legacy/rigs/biped/arm/ik.py90
-rw-r--r--rigify/legacy/rigs/biped/leg/__init__.py345
-rw-r--r--rigify/legacy/rigs/biped/leg/deform.py92
-rw-r--r--rigify/legacy/rigs/biped/leg/fk.py130
-rw-r--r--rigify/legacy/rigs/biped/leg/ik.py350
-rw-r--r--rigify/legacy/rigs/biped/limb_common.py1287
-rw-r--r--rigify/legacy/rigs/finger.py411
-rw-r--r--rigify/legacy/rigs/misc/__init__.py0
-rw-r--r--rigify/legacy/rigs/misc/delta.py165
-rw-r--r--rigify/legacy/rigs/neck_short.py388
-rw-r--r--rigify/legacy/rigs/palm.py273
-rw-r--r--rigify/legacy/rigs/pitchipoy/__init__.py0
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/__init__.py0
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/arm.py116
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/leg.py333
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py70
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/paw.py214
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/super_limb.py785
-rw-r--r--rigify/legacy/rigs/pitchipoy/limbs/ui.py143
-rw-r--r--rigify/legacy/rigs/pitchipoy/simple_tentacle.py350
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_copy.py159
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_face.py2400
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_finger.py414
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_palm.py324
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_torso_turbo.py911
-rw-r--r--rigify/legacy/rigs/pitchipoy/super_widgets.py164
-rw-r--r--rigify/legacy/rigs/pitchipoy/tentacle.py509
-rw-r--r--rigify/legacy/rigs/spine.py567
36 files changed, 11785 insertions, 0 deletions
diff --git a/rigify/legacy/rigs/__init__.py b/rigify/legacy/rigs/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/__init__.py
diff --git a/rigify/legacy/rigs/basic/__init__.py b/rigify/legacy/rigs/basic/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/basic/__init__.py
diff --git a/rigify/legacy/rigs/basic/copy.py b/rigify/legacy/rigs/basic/copy.py
new file mode 100644
index 00000000..50a25767
--- /dev/null
+++ b/rigify/legacy/rigs/basic/copy.py
@@ -0,0 +1,139 @@
+#====================== 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 ...utils import copy_bone
+from ...utils import strip_org, make_deformer_name
+from ...utils import create_bone_widget
+
+
+class Rig:
+ """ 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):
+ """ 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_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.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Make a control bone (copy of original).
+ if self.make_control:
+ bone = copy_bone(self.obj, self.org_bone, self.org_name)
+
+ # 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))
+
+ # 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
+ if self.make_deform:
+ def_bone_e.use_connect = False
+ def_bone_e.parent = eb[self.org_bone]
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.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
+
+ # Create control widget
+ create_bone_widget(self.obj, bone)
+
+
+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_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_deform")
+
+
+def create_sample(obj):
+ """ Create a sample metarig for this rig type.
+ """
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('Bone')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.0000, 0.2000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['Bone'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['Bone']]
+ pbone.rigify_type = 'basic.copy'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/basic/copy_chain.py b/rigify/legacy/rigs/basic/copy_chain.py
new file mode 100644
index 00000000..4e426284
--- /dev/null
+++ b/rigify/legacy/rigs/basic/copy_chain.py
@@ -0,0 +1,206 @@
+#====================== 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 ...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
+
+
+class Rig:
+ """ 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):
+ """ 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
+
+ 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)))
+
+ 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.
+
+ """
+ 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
+ if self.make_controls:
+ for bone in ctrl_chain:
+ create_bone_widget(self.obj, bone)
+
+
+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")
+
+
+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")
+
+
+def create_sample(obj):
+ """ Create a sample metarig for this rig type.
+ """
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('bone.01')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.0000, 0.3333
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['bone.01'] = bone.name
+ bone = arm.edit_bones.new('bone.02')
+ bone.head[:] = 0.0000, 0.0000, 0.3333
+ bone.tail[:] = 0.0000, 0.0000, 0.6667
+ bone.roll = 3.1416
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['bone.01']]
+ bones['bone.02'] = bone.name
+ bone = arm.edit_bones.new('bone.03')
+ bone.head[:] = 0.0000, 0.0000, 0.6667
+ bone.tail[:] = 0.0000, 0.0000, 1.0000
+ bone.roll = 3.1416
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['bone.02']]
+ bones['bone.03'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['bone.01']]
+ pbone.rigify_type = 'basic.copy_chain'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['bone.02']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['bone.03']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/biped/__init__.py b/rigify/legacy/rigs/biped/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/biped/__init__.py
diff --git a/rigify/legacy/rigs/biped/arm/__init__.py b/rigify/legacy/rigs/biped/arm/__init__.py
new file mode 100644
index 00000000..e418a45a
--- /dev/null
+++ b/rigify/legacy/rigs/biped/arm/__init__.py
@@ -0,0 +1,306 @@
+#====================== 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
+import importlib
+from . import fk, ik, deform
+
+importlib.reload(fk)
+importlib.reload(ik)
+importlib.reload(deform)
+
+script = """
+fk_arm = ["%s", "%s", "%s"]
+ik_arm = ["%s", "%s", "%s", "%s"]
+if is_selected(fk_arm+ik_arm):
+ layout.prop(pose_bones[ik_arm[2]], '["ikfk_switch"]', text="FK / IK (" + ik_arm[2] + ")", slider=True)
+ props = layout.operator("pose.rigify_arm_fk2ik_" + rig_id, text="Snap FK->IK (" + fk_arm[0] + ")")
+ props.uarm_fk = fk_arm[0]
+ props.farm_fk = fk_arm[1]
+ props.hand_fk = fk_arm[2]
+ props.uarm_ik = ik_arm[0]
+ props.farm_ik = ik_arm[1]
+ props.hand_ik = ik_arm[2]
+ props = layout.operator("pose.rigify_arm_ik2fk_" + rig_id, text="Snap IK->FK (" + fk_arm[0] + ")")
+ props.uarm_fk = fk_arm[0]
+ props.farm_fk = fk_arm[1]
+ props.hand_fk = fk_arm[2]
+ props.uarm_ik = ik_arm[0]
+ props.farm_ik = ik_arm[1]
+ props.hand_ik = ik_arm[2]
+ props.pole = ik_arm[3]
+if is_selected(fk_arm):
+ try:
+ pose_bones[fk_arm[0]]["isolate"]
+ layout.prop(pose_bones[fk_arm[0]], '["isolate"]', text="Isolate Rotation (" + fk_arm[0] + ")", slider=True)
+ except KeyError:
+ pass
+ layout.prop(pose_bones[fk_arm[0]], '["stretch_length"]', text="Length FK (" + fk_arm[0] + ")", slider=True)
+if is_selected(ik_arm):
+ layout.prop(pose_bones[ik_arm[2]], '["stretch_length"]', text="Length IK (" + ik_arm[2] + ")", slider=True)
+ layout.prop(pose_bones[ik_arm[2]], '["auto_stretch"]', text="Auto-Stretch IK (" + ik_arm[2] + ")", slider=True)
+if is_selected([ik_arm[3]]):
+ layout.prop(pose_bones[ik_arm[3]], '["follow"]', text="Follow Parent (" + ik_arm[3] + ")", slider=True)
+"""
+
+hose_script = """
+hose_arm = ["%s", "%s", "%s", "%s", "%s"]
+if is_selected(hose_arm):
+ layout.prop(pose_bones[hose_arm[2]], '["smooth_bend"]', text="Smooth Elbow (" + hose_arm[2] + ")", slider=True)
+"""
+
+end_script = """
+if is_selected(fk_arm+ik_arm):
+ layout.separator()
+"""
+
+
+class Rig:
+ """ An arm rig, with IK/FK switching and hinge switch.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ self.obj = obj
+ self.params = params
+
+ # Gather deform rig
+ self.deform_rig = deform.Rig(obj, bone, params)
+
+ # Gather FK rig
+ self.fk_rig = fk.Rig(obj, bone, params)
+
+ # Gather IK rig
+ self.ik_rig = ik.Rig(obj, bone, params, ikfk_switch=True)
+
+ 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.
+
+ """
+ hose_controls = self.deform_rig.generate()
+ fk_controls = self.fk_rig.generate()
+ ik_controls = self.ik_rig.generate()
+ ui_script = script % (fk_controls[0], fk_controls[1], fk_controls[2], ik_controls[0], ik_controls[1], ik_controls[2], ik_controls[3])
+ if self.params.use_complex_arm:
+ ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2], hose_controls[3], hose_controls[4])
+ ui_script += end_script
+ return [ui_script]
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+
+ """
+ params.use_complex_arm = bpy.props.BoolProperty(name="Complex Arm Rig", default=True, description="Generate the full, complex arm rig with twist bones and rubber-hose controls")
+ params.bend_hint = bpy.props.BoolProperty(name="Bend Hint", default=True, description="Give IK chain a hint about which way to bend. Useful for perfectly straight chains")
+
+ items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+ params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+ params.elbow_base_name = bpy.props.StringProperty(name="Elbow Name", default="elbow", description="Base name for the generated elbow-related controls")
+
+ params.separate_ik_layers = bpy.props.BoolProperty(name="Separate IK Control Layers:", default=False, description="Enable putting the ik controls on a separate layer from the fk controls")
+ params.ik_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the ik controls to be on")
+
+ params.separate_hose_layers = bpy.props.BoolProperty(name="Separate Rubber-hose Control Layers:", default=False, description="Enable putting the rubber-hose controls on a separate layer from the other controls")
+ params.hose_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the rubber-hose controls to be on")
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+
+ """
+ col = layout.column()
+ col.prop(params, "use_complex_arm")
+
+ r = layout.row()
+ r.label(text="Elbow rotation axis:")
+ r.prop(params, "primary_rotation_axis", text="")
+
+ r = layout.row()
+ r.prop(params, "elbow_base_name")
+
+ r = layout.row()
+ r.prop(params, "bend_hint")
+
+ r = layout.row()
+ r.prop(params, "separate_ik_layers")
+
+ r = layout.row()
+ r.active = params.separate_ik_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=0, toggle=True, text="")
+ row.prop(params, "ik_layers", index=1, toggle=True, text="")
+ row.prop(params, "ik_layers", index=2, toggle=True, text="")
+ row.prop(params, "ik_layers", index=3, toggle=True, text="")
+ row.prop(params, "ik_layers", index=4, toggle=True, text="")
+ row.prop(params, "ik_layers", index=5, toggle=True, text="")
+ row.prop(params, "ik_layers", index=6, toggle=True, text="")
+ row.prop(params, "ik_layers", index=7, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=16, toggle=True, text="")
+ row.prop(params, "ik_layers", index=17, toggle=True, text="")
+ row.prop(params, "ik_layers", index=18, toggle=True, text="")
+ row.prop(params, "ik_layers", index=19, toggle=True, text="")
+ row.prop(params, "ik_layers", index=20, toggle=True, text="")
+ row.prop(params, "ik_layers", index=21, toggle=True, text="")
+ row.prop(params, "ik_layers", index=22, toggle=True, text="")
+ row.prop(params, "ik_layers", index=23, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=8, toggle=True, text="")
+ row.prop(params, "ik_layers", index=9, toggle=True, text="")
+ row.prop(params, "ik_layers", index=10, toggle=True, text="")
+ row.prop(params, "ik_layers", index=11, toggle=True, text="")
+ row.prop(params, "ik_layers", index=12, toggle=True, text="")
+ row.prop(params, "ik_layers", index=13, toggle=True, text="")
+ row.prop(params, "ik_layers", index=14, toggle=True, text="")
+ row.prop(params, "ik_layers", index=15, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=24, toggle=True, text="")
+ row.prop(params, "ik_layers", index=25, toggle=True, text="")
+ row.prop(params, "ik_layers", index=26, toggle=True, text="")
+ row.prop(params, "ik_layers", index=27, toggle=True, text="")
+ row.prop(params, "ik_layers", index=28, toggle=True, text="")
+ row.prop(params, "ik_layers", index=29, toggle=True, text="")
+ row.prop(params, "ik_layers", index=30, toggle=True, text="")
+ row.prop(params, "ik_layers", index=31, toggle=True, text="")
+
+ if params.use_complex_arm:
+ r = layout.row()
+ r.prop(params, "separate_hose_layers")
+
+ r = layout.row()
+ r.active = params.separate_hose_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=0, toggle=True, text="")
+ row.prop(params, "hose_layers", index=1, toggle=True, text="")
+ row.prop(params, "hose_layers", index=2, toggle=True, text="")
+ row.prop(params, "hose_layers", index=3, toggle=True, text="")
+ row.prop(params, "hose_layers", index=4, toggle=True, text="")
+ row.prop(params, "hose_layers", index=5, toggle=True, text="")
+ row.prop(params, "hose_layers", index=6, toggle=True, text="")
+ row.prop(params, "hose_layers", index=7, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=16, toggle=True, text="")
+ row.prop(params, "hose_layers", index=17, toggle=True, text="")
+ row.prop(params, "hose_layers", index=18, toggle=True, text="")
+ row.prop(params, "hose_layers", index=19, toggle=True, text="")
+ row.prop(params, "hose_layers", index=20, toggle=True, text="")
+ row.prop(params, "hose_layers", index=21, toggle=True, text="")
+ row.prop(params, "hose_layers", index=22, toggle=True, text="")
+ row.prop(params, "hose_layers", index=23, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=8, toggle=True, text="")
+ row.prop(params, "hose_layers", index=9, toggle=True, text="")
+ row.prop(params, "hose_layers", index=10, toggle=True, text="")
+ row.prop(params, "hose_layers", index=11, toggle=True, text="")
+ row.prop(params, "hose_layers", index=12, toggle=True, text="")
+ row.prop(params, "hose_layers", index=13, toggle=True, text="")
+ row.prop(params, "hose_layers", index=14, toggle=True, text="")
+ row.prop(params, "hose_layers", index=15, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=24, toggle=True, text="")
+ row.prop(params, "hose_layers", index=25, toggle=True, text="")
+ row.prop(params, "hose_layers", index=26, toggle=True, text="")
+ row.prop(params, "hose_layers", index=27, toggle=True, text="")
+ row.prop(params, "hose_layers", index=28, toggle=True, text="")
+ row.prop(params, "hose_layers", index=29, toggle=True, text="")
+ row.prop(params, "hose_layers", index=30, toggle=True, text="")
+ row.prop(params, "hose_layers", index=31, toggle=True, text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_meta_rig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('upper_arm')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.3000, 0.0300, 0.0000
+ bone.roll = 1.5708
+ bone.use_connect = False
+ bones['upper_arm'] = bone.name
+ bone = arm.edit_bones.new('forearm')
+ bone.head[:] = 0.3000, 0.0300, 0.0000
+ bone.tail[:] = 0.6000, 0.0000, 0.0000
+ bone.roll = 1.5708
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['upper_arm']]
+ bones['forearm'] = bone.name
+ bone = arm.edit_bones.new('hand')
+ bone.head[:] = 0.6000, 0.0000, 0.0000
+ bone.tail[:] = 0.7000, 0.0000, 0.0000
+ bone.roll = 3.1416
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['forearm']]
+ bones['hand'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['upper_arm']]
+ pbone.rigify_type = 'biped.arm'
+ pbone.lock_location = (True, True, True)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forearm']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['hand']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/biped/arm/deform.py b/rigify/legacy/rigs/biped/arm/deform.py
new file mode 100644
index 00000000..a5444207
--- /dev/null
+++ b/rigify/legacy/rigs/biped/arm/deform.py
@@ -0,0 +1,58 @@
+#====================== 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 .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import connected_children_names
+from ....utils import strip_org
+
+
+class Rig:
+ """ An FK arm rig, with hinge switch.
+
+ """
+ def __init__(self, obj, bone, params):
+ self.obj = obj
+ self.params = params
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(self.org_bones) != 3:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone)))
+
+ # Get rig parameters
+ if params.separate_hose_layers:
+ layers = list(params.hose_layers)
+ else:
+ layers = None
+ use_complex_rig = params.use_complex_arm
+ elbow_base_name = params.elbow_base_name
+ primary_rotation_axis = params.primary_rotation_axis
+
+ # Based on common limb
+ self.rubber_hose_limb = limb_common.RubberHoseLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], use_complex_rig, elbow_base_name, primary_rotation_axis, layers)
+
+ def generate(self):
+ bone_list = self.rubber_hose_limb.generate()
+ return bone_list
diff --git a/rigify/legacy/rigs/biped/arm/fk.py b/rigify/legacy/rigs/biped/arm/fk.py
new file mode 100644
index 00000000..03ff6fc9
--- /dev/null
+++ b/rigify/legacy/rigs/biped/arm/fk.py
@@ -0,0 +1,86 @@
+#====================== 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 .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import connected_children_names
+from ....utils import create_widget
+from ....utils import strip_org
+from ....utils import get_layers
+
+
+class Rig:
+ """ An FK arm rig, with hinge switch.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed, and
+ store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ self.obj = obj
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(self.org_bones) != 3:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of at least 3 bones" % (strip_org(bone)))
+
+ # Get params
+ if "layers" in params:
+ layers = get_layers(params["layers"])
+ else:
+ layers = None
+
+ primary_rotation_axis = params.primary_rotation_axis
+
+ # Arm is based on common limb
+ self.fk_limb = limb_common.FKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], primary_rotation_axis, layers)
+
+ 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.
+
+ """
+ bone_list = self.fk_limb.generate()
+ uarm = bone_list[0]
+ farm = bone_list[1]
+ hand = bone_list[2]
+
+ # Create hand widget
+ ob = create_widget(self.obj, hand)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [uarm, farm, hand]
diff --git a/rigify/legacy/rigs/biped/arm/ik.py b/rigify/legacy/rigs/biped/arm/ik.py
new file mode 100644
index 00000000..e4cd2b5d
--- /dev/null
+++ b/rigify/legacy/rigs/biped/arm/ik.py
@@ -0,0 +1,90 @@
+#====================== 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 .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import connected_children_names
+from ....utils import strip_org
+from ....utils import create_widget
+
+
+class Rig:
+ """ An IK arm rig, with an optional ik/fk switch.
+
+ """
+ def __init__(self, obj, bone, params, ikfk_switch=False):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed, and
+ store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ ikfk_switch: if True, create an ik/fk switch slider
+ """
+ self.obj = obj
+ self.params = params
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+ if len(self.org_bones) != 3:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones" % (strip_org(bone)))
+
+ # Get the rig parameters
+ if params.separate_ik_layers:
+ layers = list(params.ik_layers)
+ else:
+ layers = None
+ bend_hint = params.bend_hint
+ primary_rotation_axis = params.primary_rotation_axis
+ pole_target_base_name = self.params.elbow_base_name + "_target"
+
+ # Arm is based on common limb
+ self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], None, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch)
+
+ 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.
+
+ """
+ bone_list = self.ik_limb.generate()
+ uarm = bone_list[0]
+ farm = bone_list[1]
+ hand = bone_list[2]
+ # hand_mch = bone_list[3]
+ pole = bone_list[4]
+ # vispole = bone_list[5]
+ # vishand = bone_list[6]
+
+ ob = create_widget(self.obj, hand)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [uarm, farm, hand, pole]
diff --git a/rigify/legacy/rigs/biped/leg/__init__.py b/rigify/legacy/rigs/biped/leg/__init__.py
new file mode 100644
index 00000000..97241ead
--- /dev/null
+++ b/rigify/legacy/rigs/biped/leg/__init__.py
@@ -0,0 +1,345 @@
+#====================== 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
+import importlib
+from . import fk, ik, deform
+
+importlib.reload(fk)
+importlib.reload(ik)
+importlib.reload(deform)
+
+script = """
+fk_leg = ["%s", "%s", "%s", "%s"]
+ik_leg = ["%s", "%s", "%s", "%s", "%s", "%s"]
+if is_selected(fk_leg+ik_leg):
+ layout.prop(pose_bones[ik_leg[2]], '["ikfk_switch"]', text="FK / IK (" + ik_leg[2] + ")", slider=True)
+ p = layout.operator("pose.rigify_leg_fk2ik_" + rig_id, text="Snap FK->IK (" + fk_leg[0] + ")")
+ p.thigh_fk = fk_leg[0]
+ p.shin_fk = fk_leg[1]
+ p.foot_fk = fk_leg[2]
+ p.mfoot_fk = fk_leg[3]
+ p.thigh_ik = ik_leg[0]
+ p.shin_ik = ik_leg[1]
+ p.foot_ik = ik_leg[2]
+ p.mfoot_ik = ik_leg[5]
+ p = layout.operator("pose.rigify_leg_ik2fk_" + rig_id, text="Snap IK->FK (" + fk_leg[0] + ")")
+ p.thigh_fk = fk_leg[0]
+ p.shin_fk = fk_leg[1]
+ p.mfoot_fk = fk_leg[3]
+ p.thigh_ik = ik_leg[0]
+ p.shin_ik = ik_leg[1]
+ p.foot_ik = ik_leg[2]
+ p.pole = ik_leg[3]
+ p.footroll = ik_leg[4]
+ p.mfoot_ik = ik_leg[5]
+if is_selected(fk_leg):
+ try:
+ pose_bones[fk_leg[0]]["isolate"]
+ layout.prop(pose_bones[fk_leg[0]], '["isolate"]', text="Isolate Rotation (" + fk_leg[0] + ")", slider=True)
+ except KeyError:
+ pass
+ layout.prop(pose_bones[fk_leg[0]], '["stretch_length"]', text="Length FK (" + fk_leg[0] + ")", slider=True)
+if is_selected(ik_leg):
+ layout.prop(pose_bones[ik_leg[2]], '["stretch_length"]', text="Length IK (" + ik_leg[2] + ")", slider=True)
+ layout.prop(pose_bones[ik_leg[2]], '["auto_stretch"]', text="Auto-Stretch IK (" + ik_leg[2] + ")", slider=True)
+if is_selected([ik_leg[3]]):
+ layout.prop(pose_bones[ik_leg[3]], '["follow"]', text="Follow Foot (" + ik_leg[3] + ")", slider=True)
+"""
+
+hose_script = """
+hose_leg = ["%s", "%s", "%s", "%s", "%s"]
+if is_selected(hose_leg):
+ layout.prop(pose_bones[hose_leg[2]], '["smooth_bend"]', text="Smooth Knee (" + hose_leg[2] + ")", slider=True)
+"""
+
+end_script = """
+if is_selected(fk_leg+ik_leg):
+ layout.separator()
+"""
+
+
+class Rig:
+ """ A leg rig, with IK/FK switching, a hinge switch, and foot roll.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ self.obj = obj
+ self.params = params
+
+ # Gather deform rig
+ self.deform_rig = deform.Rig(obj, bone, params)
+
+ # Gather FK rig
+ self.fk_rig = fk.Rig(obj, bone, params)
+
+ # Gather IK rig
+ self.ik_rig = ik.Rig(obj, bone, params, ikfk_switch=True)
+
+ 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.
+
+ """
+ hose_controls = self.deform_rig.generate()
+ fk_controls = self.fk_rig.generate()
+ ik_controls = self.ik_rig.generate()
+ ui_script = script % (fk_controls[0], fk_controls[1], fk_controls[2], fk_controls[3], ik_controls[0], ik_controls[1], ik_controls[2], ik_controls[3], ik_controls[4], ik_controls[5])
+ if self.params.use_complex_leg:
+ ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2], hose_controls[3], hose_controls[4])
+ ui_script += end_script
+ return [ui_script]
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+
+ """
+ params.use_complex_leg = bpy.props.BoolProperty(name="Complex Leg Rig", default=True, description="Generate the full, complex leg rig with twist bones and rubber-hose controls")
+ params.bend_hint = bpy.props.BoolProperty(name="Bend Hint", default=True, description="Give IK chain a hint about which way to bend (useful for perfectly straight chains)")
+
+ items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+ params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+ params.knee_base_name = bpy.props.StringProperty(name="Knee Name", default="knee", description="Base name for the generated knee-related controls")
+
+ params.separate_ik_layers = bpy.props.BoolProperty(name="Separate IK Control Layers:", default=False, description="Enable putting the ik controls on a separate layer from the fk controls")
+ params.ik_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the ik controls to be on")
+
+ params.separate_hose_layers = bpy.props.BoolProperty(name="Separate Rubber-hose Control Layers:", default=False, description="Enable putting the rubber-hose controls on a separate layer from the other controls")
+ params.hose_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the rubber-hose controls to be on")
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+
+ """
+ col = layout.column()
+ col.prop(params, "use_complex_leg")
+
+ r = layout.row()
+ r.label(text="Knee rotation axis:")
+ r.prop(params, "primary_rotation_axis", text="")
+
+ r = layout.row()
+ r.prop(params, "knee_base_name")
+
+ r = layout.row()
+ r.prop(params, "bend_hint")
+
+ r = layout.row()
+ r.prop(params, "separate_ik_layers")
+
+ r = layout.row()
+ r.active = params.separate_ik_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=0, toggle=True, text="")
+ row.prop(params, "ik_layers", index=1, toggle=True, text="")
+ row.prop(params, "ik_layers", index=2, toggle=True, text="")
+ row.prop(params, "ik_layers", index=3, toggle=True, text="")
+ row.prop(params, "ik_layers", index=4, toggle=True, text="")
+ row.prop(params, "ik_layers", index=5, toggle=True, text="")
+ row.prop(params, "ik_layers", index=6, toggle=True, text="")
+ row.prop(params, "ik_layers", index=7, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=16, toggle=True, text="")
+ row.prop(params, "ik_layers", index=17, toggle=True, text="")
+ row.prop(params, "ik_layers", index=18, toggle=True, text="")
+ row.prop(params, "ik_layers", index=19, toggle=True, text="")
+ row.prop(params, "ik_layers", index=20, toggle=True, text="")
+ row.prop(params, "ik_layers", index=21, toggle=True, text="")
+ row.prop(params, "ik_layers", index=22, toggle=True, text="")
+ row.prop(params, "ik_layers", index=23, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=8, toggle=True, text="")
+ row.prop(params, "ik_layers", index=9, toggle=True, text="")
+ row.prop(params, "ik_layers", index=10, toggle=True, text="")
+ row.prop(params, "ik_layers", index=11, toggle=True, text="")
+ row.prop(params, "ik_layers", index=12, toggle=True, text="")
+ row.prop(params, "ik_layers", index=13, toggle=True, text="")
+ row.prop(params, "ik_layers", index=14, toggle=True, text="")
+ row.prop(params, "ik_layers", index=15, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "ik_layers", index=24, toggle=True, text="")
+ row.prop(params, "ik_layers", index=25, toggle=True, text="")
+ row.prop(params, "ik_layers", index=26, toggle=True, text="")
+ row.prop(params, "ik_layers", index=27, toggle=True, text="")
+ row.prop(params, "ik_layers", index=28, toggle=True, text="")
+ row.prop(params, "ik_layers", index=29, toggle=True, text="")
+ row.prop(params, "ik_layers", index=30, toggle=True, text="")
+ row.prop(params, "ik_layers", index=31, toggle=True, text="")
+
+ if params.use_complex_leg:
+ r = layout.row()
+ r.prop(params, "separate_hose_layers")
+
+ r = layout.row()
+ r.active = params.separate_hose_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=0, toggle=True, text="")
+ row.prop(params, "hose_layers", index=1, toggle=True, text="")
+ row.prop(params, "hose_layers", index=2, toggle=True, text="")
+ row.prop(params, "hose_layers", index=3, toggle=True, text="")
+ row.prop(params, "hose_layers", index=4, toggle=True, text="")
+ row.prop(params, "hose_layers", index=5, toggle=True, text="")
+ row.prop(params, "hose_layers", index=6, toggle=True, text="")
+ row.prop(params, "hose_layers", index=7, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=16, toggle=True, text="")
+ row.prop(params, "hose_layers", index=17, toggle=True, text="")
+ row.prop(params, "hose_layers", index=18, toggle=True, text="")
+ row.prop(params, "hose_layers", index=19, toggle=True, text="")
+ row.prop(params, "hose_layers", index=20, toggle=True, text="")
+ row.prop(params, "hose_layers", index=21, toggle=True, text="")
+ row.prop(params, "hose_layers", index=22, toggle=True, text="")
+ row.prop(params, "hose_layers", index=23, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=8, toggle=True, text="")
+ row.prop(params, "hose_layers", index=9, toggle=True, text="")
+ row.prop(params, "hose_layers", index=10, toggle=True, text="")
+ row.prop(params, "hose_layers", index=11, toggle=True, text="")
+ row.prop(params, "hose_layers", index=12, toggle=True, text="")
+ row.prop(params, "hose_layers", index=13, toggle=True, text="")
+ row.prop(params, "hose_layers", index=14, toggle=True, text="")
+ row.prop(params, "hose_layers", index=15, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "hose_layers", index=24, toggle=True, text="")
+ row.prop(params, "hose_layers", index=25, toggle=True, text="")
+ row.prop(params, "hose_layers", index=26, toggle=True, text="")
+ row.prop(params, "hose_layers", index=27, toggle=True, text="")
+ row.prop(params, "hose_layers", index=28, toggle=True, text="")
+ row.prop(params, "hose_layers", index=29, toggle=True, text="")
+ row.prop(params, "hose_layers", index=30, toggle=True, text="")
+ row.prop(params, "hose_layers", index=31, toggle=True, text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_meta_rig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('thigh')
+ bone.head[:] = -0.0000, 0.0000, 1.0000
+ bone.tail[:] = -0.0000, -0.0500, 0.5000
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bones['thigh'] = bone.name
+ bone = arm.edit_bones.new('shin')
+ bone.head[:] = -0.0000, -0.0500, 0.5000
+ bone.tail[:] = -0.0000, 0.0000, 0.1000
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['thigh']]
+ bones['shin'] = bone.name
+ bone = arm.edit_bones.new('foot')
+ bone.head[:] = -0.0000, 0.0000, 0.1000
+ bone.tail[:] = 0.0000, -0.1200, 0.0300
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['shin']]
+ bones['foot'] = bone.name
+ bone = arm.edit_bones.new('heel')
+ bone.head[:] = -0.0000, 0.0000, 0.1000
+ bone.tail[:] = -0.0000, 0.0600, 0.0000
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['shin']]
+ bones['heel'] = bone.name
+ bone = arm.edit_bones.new('heel.02')
+ bone.head[:] = -0.0500, -0.0200, 0.0000
+ bone.tail[:] = 0.0500, -0.0200, 0.0000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['heel']]
+ bones['heel.02'] = bone.name
+ bone = arm.edit_bones.new('toe')
+ bone.head[:] = 0.0000, -0.1200, 0.0300
+ bone.tail[:] = 0.0000, -0.2000, 0.0300
+ bone.roll = 3.1416
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['foot']]
+ bones['toe'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['thigh']]
+ pbone.rigify_type = 'biped.leg'
+ pbone.lock_location = (True, True, True)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['shin']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['foot']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['heel']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['toe']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/biped/leg/deform.py b/rigify/legacy/rigs/biped/leg/deform.py
new file mode 100644
index 00000000..cde73250
--- /dev/null
+++ b/rigify/legacy/rigs/biped/leg/deform.py
@@ -0,0 +1,92 @@
+#====================== 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 .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import copy_bone
+from ....utils import connected_children_names, has_connected_children
+from ....utils import strip_org, make_deformer_name
+
+
+class Rig:
+ """ A leg deform-bone setup.
+
+ """
+ def __init__(self, obj, bone, params):
+ self.obj = obj
+ self.params = params
+
+ # Get the chain of 2 connected bones
+ leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(leg_bones) != 2:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- leg bones != 2" % (strip_org(bone)))
+
+ # Get the foot and heel
+ foot = None
+ heel = None
+ for b in self.obj.data.bones[leg_bones[1]].children:
+ if b.use_connect is True:
+ if len(b.children) >= 1 and has_connected_children(b):
+ foot = b.name
+ else:
+ heel = b.name
+
+ if foot is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- could not find foot bone (that is, a bone with >1 children connected) attached to bone '%s'" % (strip_org(bone), strip_org(leg_bones[1])))
+ if heel is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- could not find heel bone (that is, a bone with no children connected) attached to bone '%s'" % (strip_org(bone), strip_org(leg_bones[1])))
+ # Get the toe
+ toe = None
+ for b in self.obj.data.bones[foot].children:
+ if b.use_connect is True:
+ toe = b.name
+
+ if toe is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type -- toe is None" % (strip_org(bone)))
+
+ self.org_bones = leg_bones + [foot, toe, heel]
+
+ # Get rig parameters
+ if params.separate_hose_layers:
+ layers = list(params.hose_layers)
+ else:
+ layers = None
+ use_complex_rig = params.use_complex_leg
+ knee_base_name = params.knee_base_name
+ primary_rotation_axis = params.primary_rotation_axis
+
+ # Based on common limb
+ self.rubber_hose_limb = limb_common.RubberHoseLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], use_complex_rig, knee_base_name, primary_rotation_axis, layers)
+
+ def generate(self):
+ bone_list = self.rubber_hose_limb.generate()
+
+ # Set up toe
+ bpy.ops.object.mode_set(mode='EDIT')
+ toe = copy_bone(self.obj, self.org_bones[3], make_deformer_name(strip_org(self.org_bones[3])))
+ eb = self.obj.data.edit_bones
+ eb[toe].use_connect = False
+ eb[toe].parent = eb[self.org_bones[3]]
+
+ return bone_list
diff --git a/rigify/legacy/rigs/biped/leg/fk.py b/rigify/legacy/rigs/biped/leg/fk.py
new file mode 100644
index 00000000..bf055fa5
--- /dev/null
+++ b/rigify/legacy/rigs/biped/leg/fk.py
@@ -0,0 +1,130 @@
+#====================== 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 mathutils import Vector
+
+from .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import connected_children_names, has_connected_children
+from ....utils import strip_org
+from ....utils import get_layers
+from ....utils import create_widget
+
+
+class Rig:
+ """ An FK leg rig, with hinge switch.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed, and
+ store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ self.obj = obj
+ self.params = params
+
+ # Get the chain of 2 connected bones
+ leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(leg_bones) != 2:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ # Get the foot and heel
+ foot = None
+ heel = None
+ for b in self.obj.data.bones[leg_bones[1]].children:
+ if b.use_connect is True:
+ if len(b.children) >= 1 and has_connected_children(b):
+ foot = b.name
+ else:
+ heel = b.name
+
+ if foot is None or heel is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ # Get the toe
+ toe = None
+ for b in self.obj.data.bones[foot].children:
+ if b.use_connect is True:
+ toe = b.name
+
+ # Get the toe
+ if toe is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ self.org_bones = leg_bones + [foot, toe, heel]
+
+ # Get (optional) parent
+ if self.obj.data.bones[bone].parent is None:
+ self.org_parent = None
+ else:
+ self.org_parent = self.obj.data.bones[bone].parent.name
+
+ # Get rig parameters
+ if "layers" in params:
+ layers = get_layers(params["layers"])
+ else:
+ layers = None
+
+ primary_rotation_axis = params.primary_rotation_axis
+
+ # Leg is based on common limb
+ self.fk_limb = limb_common.FKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], primary_rotation_axis, layers)
+
+ 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.
+
+ """
+ ctrl_bones = self.fk_limb.generate()
+ thigh = ctrl_bones[0]
+ shin = ctrl_bones[1]
+ foot = ctrl_bones[2]
+ foot_mch = ctrl_bones[3]
+
+ # Position foot control
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+ foot_e = eb[foot]
+ vec = Vector(eb[self.org_bones[3]].vector)
+ vec.normalize()
+ foot_e.tail = foot_e.head + (vec * foot_e.length)
+ foot_e.roll = eb[self.org_bones[3]].roll
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Create foot widget
+ ob = create_widget(self.obj, foot)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [thigh, shin, foot, foot_mch]
diff --git a/rigify/legacy/rigs/biped/leg/ik.py b/rigify/legacy/rigs/biped/leg/ik.py
new file mode 100644
index 00000000..82422e27
--- /dev/null
+++ b/rigify/legacy/rigs/biped/leg/ik.py
@@ -0,0 +1,350 @@
+#====================== 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 mathutils import Vector
+
+from .. import limb_common
+
+from ....utils import MetarigError
+from ....utils import align_bone_x_axis
+from ....utils import copy_bone, flip_bone, put_bone
+from ....utils import connected_children_names, has_connected_children
+from ....utils import strip_org, make_mechanism_name, insert_before_lr
+from ....utils import create_widget, create_circle_widget
+
+
+class Rig:
+ """ An IK leg rig, with an optional ik/fk switch.
+
+ """
+ def __init__(self, obj, bone, params, ikfk_switch=False):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed, and
+ store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+ """
+ self.obj = obj
+ self.params = params
+ self.switch = ikfk_switch
+
+ # Get the chain of 2 connected bones
+ leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(leg_bones) != 2:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ # Get the foot and heel
+ foot = None
+ heel = None
+ rocker = None
+ for b in self.obj.data.bones[leg_bones[1]].children:
+ if b.use_connect is True:
+ if len(b.children) >= 1 and has_connected_children(b):
+ foot = b.name
+ else:
+ heel = b.name
+ if len(b.children) > 0:
+ rocker = b.children[0].name
+
+ if foot is None or heel is None:
+ print("blah")
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ # Get the toe
+ toe = None
+ for b in self.obj.data.bones[foot].children:
+ if b.use_connect is True:
+ toe = b.name
+
+ # Get toe
+ if toe is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type" % (strip_org(bone)))
+
+ self.org_bones = leg_bones + [foot, toe, heel, rocker]
+
+ # Get rig parameters
+ if params.separate_ik_layers:
+ self.layers = list(params.ik_layers)
+ else:
+ self.layers = None
+ bend_hint = params.bend_hint
+ primary_rotation_axis = params.primary_rotation_axis
+ pole_target_base_name = self.params.knee_base_name + "_target"
+
+ # Leg is based on common limb
+ self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], self.org_bones[2], pole_target_base_name, primary_rotation_axis, bend_hint, self.layers, ikfk_switch)
+
+ 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.
+ """
+ # Generate base IK limb
+ bone_list = self.ik_limb.generate()
+ thigh = bone_list[0]
+ shin = bone_list[1]
+ foot = bone_list[2]
+ foot_mch = bone_list[3]
+ pole = bone_list[4]
+ # vispole = bone_list[5]
+ # visfoot = bone_list[6]
+
+ # Build IK foot rig
+ bpy.ops.object.mode_set(mode='EDIT')
+ make_rocker = False
+ if self.org_bones[5] is not None:
+ make_rocker = True
+
+ # Create the bones
+ toe = copy_bone(self.obj, self.org_bones[3], strip_org(self.org_bones[3]))
+ toe_parent = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".parent")))
+ toe_parent_socket1 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket1")))
+ toe_parent_socket2 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket2")))
+
+ foot_roll = copy_bone(self.obj, self.org_bones[4], strip_org(insert_before_lr(self.org_bones[2], "_roll.ik")))
+ roll1 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.01")))
+ roll2 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll.02")))
+
+ if make_rocker:
+ rocker1 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.01")))
+ rocker2 = copy_bone(self.obj, self.org_bones[5], make_mechanism_name(strip_org(self.org_bones[2] + ".rocker.02")))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ org_foot_e = eb[self.org_bones[2]]
+ foot_e = eb[foot]
+ foot_ik_target_e = eb[foot_mch]
+ toe_e = eb[toe]
+ toe_parent_e = eb[toe_parent]
+ toe_parent_socket1_e = eb[toe_parent_socket1]
+ toe_parent_socket2_e = eb[toe_parent_socket2]
+ foot_roll_e = eb[foot_roll]
+ roll1_e = eb[roll1]
+ roll2_e = eb[roll2]
+ if make_rocker:
+ rocker1_e = eb[rocker1]
+ rocker2_e = eb[rocker2]
+
+ # Parenting
+ foot_ik_target_e.use_connect = False
+ foot_ik_target_e.parent = roll2_e
+
+ toe_e.parent = toe_parent_e
+ toe_parent_e.use_connect = False
+ toe_parent_e.parent = toe_parent_socket1_e
+ toe_parent_socket1_e.use_connect = False
+ toe_parent_socket1_e.parent = roll1_e
+ toe_parent_socket2_e.use_connect = False
+ toe_parent_socket2_e.parent = eb[self.org_bones[2]]
+
+ foot_roll_e.use_connect = False
+ foot_roll_e.parent = foot_e
+
+ roll1_e.use_connect = False
+ roll1_e.parent = foot_e
+
+ roll2_e.use_connect = False
+ roll2_e.parent = roll1_e
+
+ if make_rocker:
+ rocker1_e.use_connect = False
+ rocker2_e.use_connect = False
+
+ roll1_e.parent = rocker2_e
+ rocker2_e.parent = rocker1_e
+ rocker1_e.parent = foot_e
+
+ # Positioning
+ vec = Vector(toe_e.vector)
+ vec.normalize()
+ foot_e.tail = foot_e.head + (vec * foot_e.length)
+ foot_e.roll = toe_e.roll
+
+ flip_bone(self.obj, toe_parent_socket1)
+ flip_bone(self.obj, toe_parent_socket2)
+ toe_parent_socket1_e.head = Vector(org_foot_e.tail)
+ toe_parent_socket2_e.head = Vector(org_foot_e.tail)
+ toe_parent_socket1_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 2)
+ toe_parent_socket2_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 3)
+ toe_parent_socket2_e.roll = toe_parent_socket1_e.roll
+
+ tail = Vector(roll1_e.tail)
+ roll1_e.tail = Vector(org_foot_e.tail)
+ roll1_e.tail = Vector(org_foot_e.tail)
+ roll1_e.head = tail
+ roll2_e.head = Vector(org_foot_e.tail)
+ foot_roll_e.head = Vector(org_foot_e.tail)
+ put_bone(self.obj, foot_roll, roll1_e.head)
+ foot_roll_e.length /= 2
+
+ roll_axis = roll1_e.vector.cross(org_foot_e.vector)
+ align_bone_x_axis(self.obj, roll1, roll_axis)
+ align_bone_x_axis(self.obj, roll2, roll_axis)
+ foot_roll_e.roll = roll2_e.roll
+
+ if make_rocker:
+ d = toe_e.y_axis.dot(rocker1_e.x_axis)
+ if d >= 0.0:
+ flip_bone(self.obj, rocker2)
+ else:
+ flip_bone(self.obj, rocker1)
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ foot_p = pb[foot]
+ foot_roll_p = pb[foot_roll]
+ roll1_p = pb[roll1]
+ roll2_p = pb[roll2]
+ if make_rocker:
+ rocker1_p = pb[rocker1]
+ rocker2_p = pb[rocker2]
+ toe_p = pb[toe]
+ # toe_parent_p = pb[toe_parent]
+ toe_parent_socket1_p = pb[toe_parent_socket1]
+
+ # Foot roll control only rotates on x-axis, or x and y if rocker.
+ foot_roll_p.rotation_mode = 'XYZ'
+ if make_rocker:
+ foot_roll_p.lock_rotation = False, False, True
+ else:
+ foot_roll_p.lock_rotation = False, True, True
+ foot_roll_p.lock_location = True, True, True
+ foot_roll_p.lock_scale = True, True, True
+
+ # roll and rocker bones set to euler rotation
+ roll1_p.rotation_mode = 'XYZ'
+ roll2_p.rotation_mode = 'XYZ'
+ if make_rocker:
+ rocker1_p.rotation_mode = 'XYZ'
+ rocker2_p.rotation_mode = 'XYZ'
+
+ # toe_parent constraint
+ con = toe_parent_socket1_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = toe_parent_socket2
+
+ con = toe_parent_socket1_p.constraints.new('COPY_SCALE')
+ con.name = "copy_scale"
+ con.target = self.obj
+ con.subtarget = toe_parent_socket2
+
+ con = toe_parent_socket1_p.constraints.new('COPY_TRANSFORMS') # drive with IK switch
+ con.name = "fk"
+ con.target = self.obj
+ con.subtarget = toe_parent_socket2
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]'
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1.0
+ mod.coefficients[1] = -1.0
+
+ # Foot roll drivers
+ fcurve = roll1_p.driver_add("rotation_euler", 0)
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ driver.expression = "min(0,var)"
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]'
+
+ fcurve = roll2_p.driver_add("rotation_euler", 0)
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ driver.expression = "max(0,var)"
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[0]'
+
+ if make_rocker:
+ fcurve = rocker1_p.driver_add("rotation_euler", 0)
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ driver.expression = "max(0,-var)"
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]'
+
+ fcurve = rocker2_p.driver_add("rotation_euler", 0)
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ driver.expression = "max(0,var)"
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = foot_roll_p.path_from_id() + '.rotation_euler[1]'
+
+ # Constrain toe bone to toe control
+ con = pb[self.org_bones[3]].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = toe
+
+ # Set layers if specified
+ if self.layers:
+ foot_roll_p.bone.layers = self.layers
+ toe_p.bone.layers = [(i[0] or i[1]) for i in zip(toe_p.bone.layers, self.layers)] # Both FK and IK layers
+
+ # Create widgets
+ create_circle_widget(self.obj, toe, radius=0.7, head_tail=0.5)
+
+ ob = create_widget(self.obj, foot_roll)
+ if ob is not None:
+ verts = [(0.3999999761581421, 0.766044557094574, 0.6427875757217407), (0.17668449878692627, 3.823702598992895e-08, 3.2084670920085046e-08), (-0.17668461799621582, 9.874240447516058e-08, 8.285470443070153e-08), (-0.39999961853027344, 0.7660449147224426, 0.6427879333496094), (0.3562471270561218, 0.6159579753875732, 0.5168500542640686), (-0.35624682903289795, 0.6159582138061523, 0.5168502926826477), (0.20492683351039886, 0.09688037633895874, 0.0812922865152359), (-0.20492687821388245, 0.0968804731965065, 0.08129236847162247)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (1, 6), (4, 6), (2, 7), (5, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ ob = create_widget(self.obj, foot)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [thigh, shin, foot, pole, foot_roll, foot_mch]
diff --git a/rigify/legacy/rigs/biped/limb_common.py b/rigify/legacy/rigs/biped/limb_common.py
new file mode 100644
index 00000000..eadd6374
--- /dev/null
+++ b/rigify/legacy/rigs/biped/limb_common.py
@@ -0,0 +1,1287 @@
+#====================== 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 ========================
+
+from math import pi
+
+import bpy
+from rna_prop_ui import rna_idprop_ui_prop_get
+from mathutils import Vector
+
+from ...utils import angle_on_plane, align_bone_roll, align_bone_z_axis
+from ...utils import new_bone, copy_bone, put_bone, make_nonscaling_child
+from ...utils import strip_org, make_mechanism_name, make_deformer_name, insert_before_lr
+from ...utils import create_widget, create_limb_widget, create_line_widget, create_sphere_widget
+
+
+class FKLimb:
+ def __init__(self, obj, bone1, bone2, bone3, primary_rotation_axis, layers):
+ self.obj = obj
+
+ self.org_bones = [bone1, bone2, bone3]
+
+ # Get (optional) parent
+ if self.obj.data.bones[bone1].parent is None:
+ self.org_parent = None
+ else:
+ self.org_parent = self.obj.data.bones[bone1].parent.name
+
+ # Get the rig parameters
+ self.layers = layers
+ self.primary_rotation_axis = primary_rotation_axis
+
+ def generate(self):
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create non-scaling parent bone
+ if self.org_parent is not None:
+ loc = Vector(self.obj.data.edit_bones[self.org_bones[0]].head)
+ parent = make_nonscaling_child(self.obj, self.org_parent, loc, "_fk")
+ else:
+ parent = None
+
+ # Create the control bones
+ ulimb = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], ".fk")))
+ flimb = copy_bone(self.obj, self.org_bones[1], strip_org(insert_before_lr(self.org_bones[1], ".fk")))
+ elimb = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], ".fk")))
+
+ # Create the end-limb mechanism bone
+ elimb_mch = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[2])))
+
+ # Create the anti-stretch bones
+ # These sit between a parent and its child, and counteract the
+ # stretching of the parent so that the child is unaffected
+ fantistr = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_antistr.fk"))))
+ eantistr = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_antistr.fk"))))
+
+ # Create the hinge bones
+ if parent is not None:
+ socket1 = copy_bone(self.obj, ulimb, make_mechanism_name(ulimb + ".socket1"))
+ socket2 = copy_bone(self.obj, ulimb, make_mechanism_name(ulimb + ".socket2"))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ ulimb_e = eb[ulimb]
+ flimb_e = eb[flimb]
+ elimb_e = eb[elimb]
+
+ fantistr_e = eb[fantistr]
+ eantistr_e = eb[eantistr]
+
+ elimb_mch_e = eb[elimb_mch]
+
+ if parent is not None:
+ socket1_e = eb[socket1]
+ socket2_e = eb[socket2]
+
+ # Parenting
+ elimb_mch_e.use_connect = False
+ elimb_mch_e.parent = elimb_e
+
+ elimb_e.use_connect = False
+ elimb_e.parent = eantistr_e
+
+ eantistr_e.use_connect = False
+ eantistr_e.parent = flimb_e
+
+ flimb_e.use_connect = False
+ flimb_e.parent = fantistr_e
+
+ fantistr_e.use_connect = False
+ fantistr_e.parent = ulimb_e
+
+ if parent is not None:
+ socket1_e.use_connect = False
+ socket1_e.parent = eb[parent]
+
+ socket2_e.use_connect = False
+ socket2_e.parent = None
+
+ ulimb_e.use_connect = False
+ ulimb_e.parent = socket2_e
+
+ # Positioning
+ fantistr_e.length /= 8
+ put_bone(self.obj, fantistr, Vector(ulimb_e.tail))
+ eantistr_e.length /= 8
+ put_bone(self.obj, eantistr, Vector(flimb_e.tail))
+
+ if parent is not None:
+ socket1_e.length /= 4
+ socket2_e.length /= 3
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ ulimb_p = pb[ulimb]
+ flimb_p = pb[flimb]
+ elimb_p = pb[elimb]
+
+ fantistr_p = pb[fantistr]
+ eantistr_p = pb[eantistr]
+
+ if parent is not None:
+ socket2_p = pb[socket2]
+
+ # Lock axes
+ ulimb_p.lock_location = (True, True, True)
+ flimb_p.lock_location = (True, True, True)
+ elimb_p.lock_location = (True, True, True)
+
+ # Set the elbow to only bend on the x-axis.
+ flimb_p.rotation_mode = 'XYZ'
+ if 'X' in self.primary_rotation_axis:
+ flimb_p.lock_rotation = (False, True, True)
+ elif 'Y' in self.primary_rotation_axis:
+ flimb_p.lock_rotation = (True, False, True)
+ else:
+ flimb_p.lock_rotation = (True, True, False)
+
+ # Set up custom properties
+ if parent is not None:
+ prop = rna_idprop_ui_prop_get(ulimb_p, "isolate", create=True)
+ ulimb_p["isolate"] = 0.0
+ prop["soft_min"] = prop["min"] = 0.0
+ prop["soft_max"] = prop["max"] = 1.0
+
+ prop = rna_idprop_ui_prop_get(ulimb_p, "stretch_length", create=True)
+ ulimb_p["stretch_length"] = 1.0
+ prop["min"] = 0.05
+ prop["max"] = 20.0
+ prop["soft_min"] = 0.25
+ prop["soft_max"] = 4.0
+
+ # Stretch drivers
+ def add_stretch_drivers(pose_bone):
+ driver = pose_bone.driver_add("scale", 1).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "stretch_length"
+
+ driver = pose_bone.driver_add("scale", 0).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "1/sqrt(stretch_length)"
+
+ driver = pose_bone.driver_add("scale", 2).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "1/sqrt(stretch_length)"
+
+ def add_antistretch_drivers(pose_bone):
+ driver = pose_bone.driver_add("scale", 1).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "1/stretch_length"
+
+ driver = pose_bone.driver_add("scale", 0).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "sqrt(stretch_length)"
+
+ driver = pose_bone.driver_add("scale", 2).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "sqrt(stretch_length)"
+
+ add_stretch_drivers(ulimb_p)
+ add_stretch_drivers(flimb_p)
+ add_antistretch_drivers(fantistr_p)
+ add_antistretch_drivers(eantistr_p)
+
+ # Hinge constraints / drivers
+ if parent is not None:
+ con = socket2_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = socket1
+
+ con = socket2_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "isolate_off"
+ con.target = self.obj
+ con.subtarget = socket1
+
+ # Driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = ulimb_p.path_from_id() + '["isolate"]'
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1.0
+ mod.coefficients[1] = -1.0
+
+ # Constrain org bones to controls
+ con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+ con.name = "fk"
+ con.target = self.obj
+ con.subtarget = ulimb
+
+ con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+ con.name = "fk"
+ con.target = self.obj
+ con.subtarget = flimb
+
+ con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+ con.name = "fk"
+ con.target = self.obj
+ con.subtarget = elimb_mch
+
+ # Set layers if specified
+ if self.layers:
+ ulimb_p.bone.layers = self.layers
+ flimb_p.bone.layers = self.layers
+ elimb_p.bone.layers = self.layers
+
+ # Create control widgets
+ create_limb_widget(self.obj, ulimb)
+ create_limb_widget(self.obj, flimb)
+
+ ob = create_widget(self.obj, elimb)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [ulimb, flimb, elimb, elimb_mch]
+
+
+class IKLimb:
+ """ An IK limb rig, with an optional ik/fk switch.
+
+ """
+ def __init__(self, obj, bone1, bone2, bone3, pole_parent, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch=False):
+ self.obj = obj
+ self.switch = ikfk_switch
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone1, bone2, bone3]
+
+ # Get (optional) parent
+ if self.obj.data.bones[bone1].parent is None:
+ self.org_parent = None
+ else:
+ self.org_parent = self.obj.data.bones[bone1].parent.name
+
+ self.pole_parent = pole_parent
+
+ # Get the rig parameters
+ self.pole_target_base_name = pole_target_base_name
+ self.layers = layers
+ self.bend_hint = bend_hint
+ self.primary_rotation_axis = primary_rotation_axis
+
+ def generate(self):
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create non-scaling parent bone
+ if self.org_parent is not None:
+ loc = Vector(self.obj.data.edit_bones[self.org_bones[0]].head)
+ parent = make_nonscaling_child(self.obj, self.org_parent, loc, "_ik")
+ if self.pole_parent is None:
+ self.pole_parent = parent
+ else:
+ parent = None
+
+ # Create the bones
+ ulimb = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], ".ik"))))
+ flimb = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".ik"))))
+ elimb = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], ".ik")))
+ elimb_mch = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[2])))
+
+ ulimb_nostr = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], ".nostr.ik"))))
+ flimb_nostr = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".nostr.ik"))))
+
+ ulimb_str = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], ".stretch.ik"))))
+ flimb_str = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".stretch.ik"))))
+
+ pole_target_name = self.pole_target_base_name + "." + insert_before_lr(self.org_bones[0], ".ik").split(".", 1)[1]
+ pole = copy_bone(self.obj, self.org_bones[0], pole_target_name)
+ if self.pole_parent == self.org_bones[2]:
+ self.pole_parent = elimb_mch
+ if self.pole_parent is not None:
+ pole_par = copy_bone(self.obj, self.pole_parent, make_mechanism_name(insert_before_lr(pole_target_name, "_parent")))
+
+ viselimb = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], ".ik")))
+ vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole.ik")))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ if parent is not None:
+ parent_e = eb[parent]
+ ulimb_e = eb[ulimb]
+ flimb_e = eb[flimb]
+ elimb_e = eb[elimb]
+ elimb_mch_e = eb[elimb_mch]
+ ulimb_nostr_e = eb[ulimb_nostr]
+ flimb_nostr_e = eb[flimb_nostr]
+ ulimb_str_e = eb[ulimb_str]
+ flimb_str_e = eb[flimb_str]
+ pole_e = eb[pole]
+ if self.pole_parent is not None:
+ pole_par_e = eb[pole_par]
+ viselimb_e = eb[viselimb]
+ vispole_e = eb[vispole]
+
+ # Parenting
+ ulimb_e.use_connect = False
+ ulimb_nostr_e.use_connect = False
+ if parent is not None:
+ ulimb_e.parent = parent_e
+ ulimb_nostr_e.parent = parent_e
+
+ flimb_e.parent = ulimb_e
+ flimb_nostr_e.parent = ulimb_nostr_e
+
+ elimb_e.use_connect = False
+ elimb_e.parent = None
+
+ elimb_mch_e.use_connect = False
+ elimb_mch_e.parent = elimb_e
+
+ ulimb_str_e.use_connect = False
+ ulimb_str_e.parent = ulimb_e.parent
+
+ flimb_str_e.use_connect = False
+ flimb_str_e.parent = ulimb_e.parent
+
+ pole_e.use_connect = False
+ if self.pole_parent is not None:
+ pole_par_e.parent = None
+ pole_e.parent = pole_par_e
+
+ viselimb_e.use_connect = False
+ viselimb_e.parent = None
+
+ vispole_e.use_connect = False
+ vispole_e.parent = None
+
+ # Misc
+ elimb_e.use_local_location = False
+
+ viselimb_e.hide_select = True
+ vispole_e.hide_select = True
+
+ # Positioning
+ v1 = flimb_e.tail - ulimb_e.head
+ if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis:
+ v2 = v1.cross(flimb_e.x_axis)
+ if (v2 * flimb_e.z_axis) > 0.0:
+ v2 *= -1.0
+ else:
+ v2 = v1.cross(flimb_e.z_axis)
+ if (v2 * flimb_e.x_axis) < 0.0:
+ v2 *= -1.0
+ v2.normalize()
+ v2 *= v1.length
+
+ if '-' in self.primary_rotation_axis:
+ v2 *= -1
+
+ pole_e.head = flimb_e.head + v2
+ pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
+ pole_e.roll = 0.0
+ if parent is not None:
+ pole_par_e.length *= 0.75
+
+ viselimb_e.tail = viselimb_e.head + Vector((0, 0, v1.length / 32))
+ vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))
+
+ # Determine the pole offset value
+ plane = (flimb_e.tail - ulimb_e.head).normalized()
+ vec1 = ulimb_e.x_axis.normalized()
+ vec2 = (pole_e.head - ulimb_e.head).normalized()
+ pole_offset = angle_on_plane(plane, vec1, vec2)
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ ulimb_p = pb[ulimb]
+ flimb_p = pb[flimb]
+ elimb_p = pb[elimb]
+ ulimb_nostr_p = pb[ulimb_nostr]
+ flimb_nostr_p = pb[flimb_nostr]
+ ulimb_str_p = pb[ulimb_str]
+ flimb_str_p = pb[flimb_str]
+ pole_p = pb[pole]
+ if self.pole_parent is not None:
+ pole_par_p = pb[pole_par]
+ viselimb_p = pb[viselimb]
+ vispole_p = pb[vispole]
+
+ # Set the elbow to only bend on the primary axis
+ if 'X' in self.primary_rotation_axis:
+ flimb_p.lock_ik_y = True
+ flimb_p.lock_ik_z = True
+ flimb_nostr_p.lock_ik_y = True
+ flimb_nostr_p.lock_ik_z = True
+ elif 'Y' in self.primary_rotation_axis:
+ flimb_p.lock_ik_x = True
+ flimb_p.lock_ik_z = True
+ flimb_nostr_p.lock_ik_x = True
+ flimb_nostr_p.lock_ik_z = True
+ else:
+ flimb_p.lock_ik_x = True
+ flimb_p.lock_ik_y = True
+ flimb_nostr_p.lock_ik_x = True
+ flimb_nostr_p.lock_ik_y = True
+
+ # Limb stretches
+ ulimb_nostr_p.ik_stretch = 0.0
+ flimb_nostr_p.ik_stretch = 0.0
+
+ # This next bit is weird. The values calculated cause
+ # ulimb and flimb to preserve their relative lengths
+ # while stretching.
+ l1 = ulimb_p.length
+ l2 = flimb_p.length
+ if l1 < l2:
+ ulimb_p.ik_stretch = (l1 ** (1 / 3)) / (l2 ** (1 / 3))
+ flimb_p.ik_stretch = 1.0
+ else:
+ ulimb_p.ik_stretch = 1.0
+ flimb_p.ik_stretch = (l2 ** (1 / 3)) / (l1 ** (1 / 3))
+
+ # Pole target only translates
+ pole_p.lock_location = False, False, False
+ pole_p.lock_rotation = True, True, True
+ pole_p.lock_rotation_w = True
+ pole_p.lock_scale = True, True, True
+
+ # Set up custom properties
+ if self.switch is True:
+ prop = rna_idprop_ui_prop_get(elimb_p, "ikfk_switch", create=True)
+ elimb_p["ikfk_switch"] = 0.0
+ prop["soft_min"] = prop["min"] = 0.0
+ prop["soft_max"] = prop["max"] = 1.0
+
+ if self.pole_parent is not None:
+ prop = rna_idprop_ui_prop_get(pole_p, "follow", create=True)
+ pole_p["follow"] = 1.0
+ prop["soft_min"] = prop["min"] = 0.0
+ prop["soft_max"] = prop["max"] = 1.0
+
+ prop = rna_idprop_ui_prop_get(elimb_p, "stretch_length", create=True)
+ elimb_p["stretch_length"] = 1.0
+ prop["min"] = 0.05
+ prop["max"] = 20.0
+ prop["soft_min"] = 0.25
+ prop["soft_max"] = 4.0
+
+ prop = rna_idprop_ui_prop_get(elimb_p, "auto_stretch", create=True)
+ elimb_p["auto_stretch"] = 1.0
+ prop["soft_min"] = prop["min"] = 0.0
+ prop["soft_max"] = prop["max"] = 1.0
+
+ # Stretch parameter drivers
+ def add_stretch_drivers(pose_bone):
+ driver = pose_bone.driver_add("scale", 1).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "stretch_length"
+
+ driver = pose_bone.driver_add("scale", 0).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "stretch_length"
+
+ driver = pose_bone.driver_add("scale", 2).driver
+ var = driver.variables.new()
+ var.name = "stretch_length"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["stretch_length"]'
+ driver.type = 'SCRIPTED'
+ driver.expression = "stretch_length"
+ add_stretch_drivers(ulimb_nostr_p)
+
+ # Bend direction hint
+ def add_bend_hint(pose_bone, axis):
+ con = pose_bone.constraints.new('LIMIT_ROTATION')
+ con.name = "bend_hint"
+ con.owner_space = 'LOCAL'
+ if axis == 'X':
+ con.use_limit_x = True
+ con.min_x = pi / 10
+ con.max_x = pi / 10
+ elif axis == '-X':
+ con.use_limit_x = True
+ con.min_x = -pi / 10
+ con.max_x = -pi / 10
+ elif axis == 'Y':
+ con.use_limit_y = True
+ con.min_y = pi / 10
+ con.max_y = pi / 10
+ elif axis == '-Y':
+ con.use_limit_y = True
+ con.min_y = -pi / 10
+ con.max_y = -pi / 10
+ elif axis == 'Z':
+ con.use_limit_z = True
+ con.min_z = pi / 10
+ con.max_z = pi / 10
+ elif axis == '-Z':
+ con.use_limit_z = True
+ con.min_z = -pi / 10
+ con.max_z = -pi / 10
+ if self.bend_hint:
+ add_bend_hint(flimb_p, self.primary_rotation_axis)
+ add_bend_hint(flimb_nostr_p, self.primary_rotation_axis)
+
+ # Constrain normal IK chain to no-stretch IK chain
+ con = ulimb_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "pre_stretch"
+ con.target = self.obj
+ con.subtarget = ulimb_nostr
+
+ con = flimb_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "pre_stretch"
+ con.target = self.obj
+ con.subtarget = flimb_nostr
+
+ # IK Constraints
+ con = flimb_nostr_p.constraints.new('IK')
+ con.name = "ik"
+ con.target = self.obj
+ con.subtarget = elimb_mch
+ con.pole_target = self.obj
+ con.pole_subtarget = pole
+ con.pole_angle = pole_offset
+ con.chain_count = 2
+
+ con = flimb_p.constraints.new('IK')
+ con.name = "ik"
+ con.target = self.obj
+ con.subtarget = elimb_mch
+ con.chain_count = 2
+
+ # Driver to enable/disable auto stretching IK chain
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["auto_stretch"]'
+
+ # Stretch bone constraints
+ con = ulimb_str_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = ulimb
+ con = ulimb_str_p.constraints.new('MAINTAIN_VOLUME')
+ con.name = "stretch"
+ con.owner_space = 'LOCAL'
+
+ con = flimb_str_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = flimb
+ con = flimb_str_p.constraints.new('MAINTAIN_VOLUME')
+ con.name = "stretch"
+ con.owner_space = 'LOCAL'
+
+ # Pole target parent
+ if self.pole_parent is not None:
+ con = pole_par_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "parent"
+ con.target = self.obj
+ con.subtarget = self.pole_parent
+
+ driver = con.driver_add("influence").driver
+ var = driver.variables.new()
+ var.name = "follow"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pole_p.path_from_id() + '["follow"]'
+ driver.type = 'SUM'
+
+ # Constrain org bones
+ con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+ con.name = "ik"
+ con.target = self.obj
+ con.subtarget = ulimb_str
+ if self.switch is True:
+ # IK/FK switch driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["ikfk_switch"]'
+
+ con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+ con.name = "ik"
+ con.target = self.obj
+ con.subtarget = flimb_str
+ if self.switch is True:
+ # IK/FK switch driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["ikfk_switch"]'
+
+ con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+ con.name = "ik"
+ con.target = self.obj
+ con.subtarget = elimb_mch
+ if self.switch is True:
+ # IK/FK switch driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = elimb_p.path_from_id() + '["ikfk_switch"]'
+
+ # VIS limb-end constraints
+ con = viselimb_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_loc"
+ con.target = self.obj
+ con.subtarget = self.org_bones[2]
+
+ con = viselimb_p.constraints.new('STRETCH_TO')
+ con.name = "stretch_to"
+ con.target = self.obj
+ con.subtarget = elimb
+ con.volume = 'NO_VOLUME'
+ con.rest_length = viselimb_p.length
+
+ # VIS pole constraints
+ con = vispole_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_loc"
+ con.target = self.obj
+ con.subtarget = self.org_bones[1]
+
+ con = vispole_p.constraints.new('STRETCH_TO')
+ con.name = "stretch_to"
+ con.target = self.obj
+ con.subtarget = pole
+ con.volume = 'NO_VOLUME'
+ con.rest_length = vispole_p.length
+
+ # Set layers if specified
+ if self.layers:
+ elimb_p.bone.layers = self.layers
+ pole_p.bone.layers = self.layers
+ viselimb_p.bone.layers = self.layers
+ vispole_p.bone.layers = self.layers
+
+ # Create widgets
+ create_line_widget(self.obj, vispole)
+ create_line_widget(self.obj, viselimb)
+ create_sphere_widget(self.obj, pole)
+
+ ob = create_widget(self.obj, elimb)
+ if ob is not None:
+ verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ mesh = ob.data
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = ob.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+ return [ulimb, flimb, elimb, elimb_mch, pole, vispole, viselimb]
+
+
+class RubberHoseLimb:
+ def __init__(self, obj, bone1, bone2, bone3, use_complex_limb, junc_base_name, primary_rotation_axis, layers):
+ self.obj = obj
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone1, bone2, bone3]
+
+ # Get (optional) parent
+ if self.obj.data.bones[bone1].parent is None:
+ self.org_parent = None
+ else:
+ self.org_parent = self.obj.data.bones[bone1].parent.name
+
+ # Get rig parameters
+ self.layers = layers
+ self.primary_rotation_axis = primary_rotation_axis
+ self.use_complex_limb = use_complex_limb
+ self.junc_base_name = junc_base_name
+
+ def generate(self):
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create non-scaling parent bone
+ if self.org_parent is not None:
+ loc = Vector(self.obj.data.edit_bones[self.org_bones[0]].head)
+ parent = make_nonscaling_child(self.obj, self.org_parent, loc, "_rh")
+ else:
+ parent = None
+
+ if not self.use_complex_limb:
+ # Simple rig
+
+ # Create bones
+ ulimb = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+ flimb = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))
+ elimb = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ ulimb_e = eb[ulimb]
+ flimb_e = eb[flimb]
+ elimb_e = eb[elimb]
+
+ # Parenting
+ elimb_e.parent = flimb_e
+ elimb_e.use_connect = True
+
+ flimb_e.parent = ulimb_e
+ flimb_e.use_connect = True
+
+ if parent is not None:
+ elimb_e.use_connect = False
+ ulimb_e.parent = eb[parent]
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ ulimb_p = pb[ulimb]
+ flimb_p = pb[flimb]
+ elimb_p = pb[elimb]
+
+ # Constrain def bones to org bones
+ con = ulimb_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "def"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = flimb_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "def"
+ con.target = self.obj
+ con.subtarget = self.org_bones[1]
+
+ con = elimb_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "def"
+ con.target = self.obj
+ con.subtarget = self.org_bones[2]
+
+ return []
+ else:
+ # Complex rig
+
+ # Get the .R or .L off the end of the upper limb name if it exists
+ lr = self.org_bones[0].split(".", 1)
+ if len(lr) == 1:
+ lr = ""
+ else:
+ lr = lr[1]
+
+ # Create bones
+ # Deformation bones
+ ulimb1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(insert_before_lr(self.org_bones[0], ".01"))))
+ ulimb2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(insert_before_lr(self.org_bones[0], ".02"))))
+ flimb1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(insert_before_lr(self.org_bones[1], ".01"))))
+ flimb2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(insert_before_lr(self.org_bones[1], ".02"))))
+ elimb = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+ # Bones for switchable smooth bbone transition at elbow/knee
+ ulimb2_smoother = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_smth.02"))))
+ flimb1_smoother = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_smth.01"))))
+ flimb1_pos = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".01"))))
+
+ # Elbow/knee junction bone
+ junc = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".junc"))))
+
+ # Hose controls
+ uhoseend = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[0], "_hose_end")))
+ uhose = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[0], "_hose")))
+ jhose = new_bone(self.obj, self.junc_base_name + "_hose." + lr)
+ fhose = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[1], "_hose")))
+ fhoseend = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[1], "_hose_end")))
+
+ # Hose control parents
+ uhoseend_par = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(uhoseend, "_p"))))
+ uhose_par = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(uhose, "_p"))))
+ jhose_par = copy_bone(self.obj, junc, make_mechanism_name(strip_org(insert_before_lr(jhose, "_p"))))
+ fhose_par = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(fhose, "_p"))))
+ fhoseend_par = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(fhoseend, "_p"))))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ if parent is not None:
+ parent_e = eb[parent]
+ else:
+ parent_e = None
+
+ ulimb1_e = eb[ulimb1]
+ ulimb2_e = eb[ulimb2]
+ flimb1_e = eb[flimb1]
+ flimb2_e = eb[flimb2]
+ elimb_e = eb[elimb]
+
+ ulimb2_smoother_e = eb[ulimb2_smoother]
+ flimb1_smoother_e = eb[flimb1_smoother]
+ flimb1_pos_e = eb[flimb1_pos]
+
+ junc_e = eb[junc]
+
+ uhoseend_e = eb[uhoseend]
+ uhose_e = eb[uhose]
+ jhose_e = eb[jhose]
+ fhose_e = eb[fhose]
+ fhoseend_e = eb[fhoseend]
+
+ uhoseend_par_e = eb[uhoseend_par]
+ uhose_par_e = eb[uhose_par]
+ jhose_par_e = eb[jhose_par]
+ fhose_par_e = eb[fhose_par]
+ fhoseend_par_e = eb[fhoseend_par]
+
+ # Parenting
+ if parent is not None:
+ ulimb1_e.use_connect = False
+ ulimb1_e.parent = parent_e
+
+ ulimb2_e.use_connect = False
+ ulimb2_e.parent = eb[self.org_bones[0]]
+
+ ulimb2_smoother_e.use_connect = True
+ ulimb2_smoother_e.parent = ulimb2_e
+
+ flimb1_e.use_connect = True
+ flimb1_e.parent = flimb1_smoother_e
+
+ flimb1_smoother_e.use_connect = False
+ flimb1_smoother_e.parent = flimb1_pos_e
+
+ flimb1_pos_e.use_connect = False
+ flimb1_pos_e.parent = eb[self.org_bones[1]]
+
+ flimb2_e.use_connect = False
+ flimb2_e.parent = eb[self.org_bones[1]]
+
+ elimb_e.use_connect = False
+ elimb_e.parent = eb[self.org_bones[2]]
+
+ junc_e.use_connect = False
+ junc_e.parent = eb[self.org_bones[0]]
+
+ uhoseend_e.use_connect = False
+ uhoseend_e.parent = uhoseend_par_e
+
+ uhose_e.use_connect = False
+ uhose_e.parent = uhose_par_e
+
+ jhose_e.use_connect = False
+ jhose_e.parent = jhose_par_e
+
+ fhose_e.use_connect = False
+ fhose_e.parent = fhose_par_e
+
+ fhoseend_e.use_connect = False
+ fhoseend_e.parent = fhoseend_par_e
+
+ uhoseend_par_e.use_connect = False
+ uhoseend_par_e.parent = parent_e
+
+ uhose_par_e.use_connect = False
+ uhose_par_e.parent = parent_e
+
+ jhose_par_e.use_connect = False
+ jhose_par_e.parent = parent_e
+
+ fhose_par_e.use_connect = False
+ fhose_par_e.parent = parent_e
+
+ fhoseend_par_e.use_connect = False
+ fhoseend_par_e.parent = parent_e
+
+ # Positioning
+ ulimb1_e.length *= 0.5
+ ulimb2_e.head = Vector(ulimb1_e.tail)
+ flimb1_e.length *= 0.5
+ flimb2_e.head = Vector(flimb1_e.tail)
+ align_bone_roll(self.obj, flimb2, elimb)
+
+ ulimb2_smoother_e.tail = Vector(flimb1_e.tail)
+ ulimb2_smoother_e.roll = flimb1_e.roll
+
+ flimb1_smoother_e.head = Vector(ulimb1_e.tail)
+ flimb1_pos_e.length *= 0.5
+
+ junc_e.length *= 0.2
+
+ uhoseend_par_e.length *= 0.25
+ uhose_par_e.length *= 0.25
+ jhose_par_e.length *= 0.15
+ fhose_par_e.length *= 0.25
+ fhoseend_par_e.length *= 0.25
+ put_bone(self.obj, uhoseend_par, Vector(ulimb1_e.head))
+ put_bone(self.obj, uhose_par, Vector(ulimb1_e.tail))
+ put_bone(self.obj, jhose_par, Vector(ulimb2_e.tail))
+ put_bone(self.obj, fhose_par, Vector(flimb1_e.tail))
+ put_bone(self.obj, fhoseend_par, Vector(flimb2_e.tail))
+
+ put_bone(self.obj, uhoseend, Vector(ulimb1_e.head))
+ put_bone(self.obj, uhose, Vector(ulimb1_e.tail))
+ put_bone(self.obj, jhose, Vector(ulimb2_e.tail))
+ put_bone(self.obj, fhose, Vector(flimb1_e.tail))
+ put_bone(self.obj, fhoseend, Vector(flimb2_e.tail))
+
+ if 'X' in self.primary_rotation_axis:
+ upoint = Vector(ulimb1_e.z_axis)
+ fpoint = Vector(flimb1_e.z_axis)
+ elif 'Z' in self.primary_rotation_axis:
+ upoint = Vector(ulimb1_e.x_axis)
+ fpoint = Vector(flimb1_e.x_axis)
+ else: # Y
+ upoint = Vector(ulimb1_e.z_axis)
+ fpoint = Vector(flimb1_e.z_axis)
+
+ if '-' not in self.primary_rotation_axis:
+ upoint *= -1
+ fpoint *= -1
+
+ if 'Y' in self.primary_rotation_axis:
+ uside = Vector(ulimb1_e.x_axis)
+ fside = Vector(flimb1_e.x_axis)
+ else:
+ uside = Vector(ulimb1_e.y_axis) * -1
+ fside = Vector(flimb1_e.y_axis) * -1
+
+ uhoseend_e.tail = uhoseend_e.head + upoint
+ uhose_e.tail = uhose_e.head + upoint
+ jhose_e.tail = fhose_e.head + upoint + fpoint
+ fhose_e.tail = fhose_e.head + fpoint
+ fhoseend_e.tail = fhoseend_e.head + fpoint
+
+ align_bone_z_axis(self.obj, uhoseend, uside)
+ align_bone_z_axis(self.obj, uhose, uside)
+ align_bone_z_axis(self.obj, jhose, uside + fside)
+ align_bone_z_axis(self.obj, fhose, fside)
+ align_bone_z_axis(self.obj, fhoseend, fside)
+
+ l = 0.125 * (ulimb1_e.length + ulimb2_e.length + flimb1_e.length + flimb2_e.length)
+ uhoseend_e.length = l
+ uhose_e.length = l
+ jhose_e.length = l
+ fhose_e.length = l
+ fhoseend_e.length = l
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ ulimb1_p = pb[ulimb1]
+ ulimb2_p = pb[ulimb2]
+ flimb1_p = pb[flimb1]
+ flimb2_p = pb[flimb2]
+ elimb_p = pb[elimb]
+
+ ulimb2_smoother_p = pb[ulimb2_smoother]
+ flimb1_smoother_p = pb[flimb1_smoother]
+ flimb1_pos_p = pb[flimb1_pos]
+
+ junc_p = pb[junc]
+
+ uhoseend_p = pb[uhoseend]
+ uhose_p = pb[uhose]
+ jhose_p = pb[jhose]
+ fhose_p = pb[fhose]
+ fhoseend_p = pb[fhoseend]
+
+ #uhoseend_par_p = pb[uhoseend_par]
+ uhose_par_p = pb[uhose_par]
+ jhose_par_p = pb[jhose_par]
+ fhose_par_p = pb[fhose_par]
+ fhoseend_par_p = pb[fhoseend_par]
+
+ # Lock axes
+ uhose_p.lock_rotation = (True, True, True)
+ uhose_p.lock_rotation_w = True
+ uhose_p.lock_scale = (True, True, True)
+
+ jhose_p.lock_rotation = (True, True, True)
+ jhose_p.lock_rotation_w = True
+ jhose_p.lock_scale = (True, True, True)
+
+ fhose_p.lock_rotation = (True, True, True)
+ fhose_p.lock_rotation_w = True
+ fhose_p.lock_scale = (True, True, True)
+
+ # B-bone settings
+ ulimb2_p.bone.bbone_segments = 16
+ ulimb2_p.bone.bbone_in = 0.0
+ ulimb2_p.bone.bbone_out = 1.0
+
+ ulimb2_smoother_p.bone.bbone_segments = 16
+ ulimb2_smoother_p.bone.bbone_in = 1.0
+ ulimb2_smoother_p.bone.bbone_out = 0.0
+
+ flimb1_p.bone.bbone_segments = 16
+ flimb1_p.bone.bbone_in = 1.0
+ flimb1_p.bone.bbone_out = 0.0
+
+ flimb1_smoother_p.bone.bbone_segments = 16
+ flimb1_smoother_p.bone.bbone_in = 0.0
+ flimb1_smoother_p.bone.bbone_out = 1.0
+
+ # Custom properties
+ prop = rna_idprop_ui_prop_get(jhose_p, "smooth_bend", create=True)
+ jhose_p["smooth_bend"] = 0.0
+ prop["soft_min"] = prop["min"] = 0.0
+ prop["soft_max"] = prop["max"] = 1.0
+
+ # Constraints
+ con = ulimb1_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = uhoseend
+ con = ulimb1_p.constraints.new('COPY_SCALE')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+ con = ulimb1_p.constraints.new('DAMPED_TRACK')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = uhose
+ con = ulimb1_p.constraints.new('STRETCH_TO')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = uhose
+ con.volume = 'NO_VOLUME'
+
+ con = ulimb2_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = uhose
+ con = ulimb2_p.constraints.new('DAMPED_TRACK')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = jhose
+ con = ulimb2_p.constraints.new('STRETCH_TO')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = jhose
+ con.volume = 'NO_VOLUME'
+
+ con = ulimb2_smoother_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "smoother"
+ con.target = self.obj
+ con.subtarget = flimb1_pos
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SUM'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = jhose_p.path_from_id() + '["smooth_bend"]'
+
+ con = flimb1_pos_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = jhose
+ con = flimb1_pos_p.constraints.new('DAMPED_TRACK')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = fhose
+ con = flimb1_pos_p.constraints.new('STRETCH_TO')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = fhose
+ con.volume = 'NO_VOLUME'
+
+ con = flimb1_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "position"
+ con.target = self.obj
+ con.subtarget = flimb1_pos
+
+ con = flimb1_smoother_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "smoother"
+ con.target = self.obj
+ con.subtarget = ulimb2
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SUM'
+ var.name = "var"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = jhose_p.path_from_id() + '["smooth_bend"]'
+ con = flimb1_smoother_p.constraints.new('STRETCH_TO')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = jhose
+ con.volume = 'NO_VOLUME'
+
+ con = flimb2_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = fhose
+ con = flimb2_p.constraints.new('COPY_ROTATION')
+ con.name = "twist"
+ con.target = self.obj
+ con.subtarget = elimb
+ con = flimb2_p.constraints.new('DAMPED_TRACK')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = fhoseend
+ con = flimb2_p.constraints.new('STRETCH_TO')
+ con.name = "track"
+ con.target = self.obj
+ con.subtarget = fhoseend
+ con.volume = 'NO_VOLUME'
+
+ con = junc_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "bend"
+ con.target = self.obj
+ con.subtarget = self.org_bones[1]
+ con.influence = 0.5
+
+ con = uhose_par_p.constraints.new('COPY_ROTATION')
+ con.name = "follow"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+ con.influence = 1.0
+ con = uhose_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+ con.influence = 1.0
+ con = uhose_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = jhose
+ con.influence = 0.5
+
+ con = jhose_par_p.constraints.new('COPY_ROTATION')
+ con.name = "follow"
+ con.target = self.obj
+ con.subtarget = junc
+ con.influence = 1.0
+ con = jhose_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = junc
+ con.influence = 1.0
+
+ con = fhose_par_p.constraints.new('COPY_ROTATION')
+ con.name = "follow"
+ con.target = self.obj
+ con.subtarget = self.org_bones[1]
+ con.influence = 1.0
+ con = fhose_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = jhose
+ con.influence = 1.0
+ con = fhose_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = self.org_bones[2]
+ con.influence = 0.5
+
+ con = fhoseend_par_p.constraints.new('COPY_ROTATION')
+ con.name = "follow"
+ con.target = self.obj
+ con.subtarget = self.org_bones[1]
+ con.influence = 1.0
+ con = fhoseend_par_p.constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ con.subtarget = self.org_bones[2]
+ con.influence = 1.0
+
+ # Layers
+ if self.layers:
+ uhoseend_p.bone.layers = self.layers
+ uhose_p.bone.layers = self.layers
+ jhose_p.bone.layers = self.layers
+ fhose_p.bone.layers = self.layers
+ fhoseend_p.bone.layers = self.layers
+ else:
+ layers = list(pb[self.org_bones[0]].bone.layers)
+ uhoseend_p.bone.layers = layers
+ uhose_p.bone.layers = layers
+ jhose_p.bone.layers = layers
+ fhose_p.bone.layers = layers
+ fhoseend_p.bone.layers = layers
+
+ # Create widgets
+ create_sphere_widget(self.obj, uhoseend)
+ create_sphere_widget(self.obj, uhose)
+ create_sphere_widget(self.obj, jhose)
+ create_sphere_widget(self.obj, fhose)
+ create_sphere_widget(self.obj, fhoseend)
+
+ return [uhoseend, uhose, jhose, fhose, fhoseend]
diff --git a/rigify/legacy/rigs/finger.py b/rigify/legacy/rigs/finger.py
new file mode 100644
index 00000000..70bbc112
--- /dev/null
+++ b/rigify/legacy/rigs/finger.py
@@ -0,0 +1,411 @@
+#====================== 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 re
+
+import bpy
+from rna_prop_ui import rna_idprop_ui_prop_get
+from mathutils import Vector
+
+from ..utils import MetarigError
+from ..utils import copy_bone
+from ..utils import connected_children_names
+from ..utils import strip_org, make_mechanism_name, make_deformer_name
+from ..utils import create_widget, create_limb_widget
+
+
+class Rig:
+ """ A finger rig. It takes a single chain of bones.
+ This is a control and deformation rig.
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ """
+ self.obj = obj
+ self.org_bones = [bone] + connected_children_names(obj, bone)
+ self.params = params
+
+ 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)))
+
+ # Get user-specified layers, if they exist
+ if params.separate_extra_layers:
+ self.ex_layers = list(params.extra_layers)
+ else:
+ self.ex_layers = None
+
+ # Get other rig parameters
+ self.primary_rotation_axis = params.primary_rotation_axis
+ self.use_digit_twist = params.use_digit_twist
+
+ def deform(self):
+ """ Generate the deformation rig.
+ Just a copy of the original bones, except the first digit which is a twist bone.
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create the bones
+ # First bone is a twist bone
+ if self.use_digit_twist:
+ b1a = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+ b1b = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
+ b1tip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
+ else:
+ b1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+ # The rest are normal
+ bones = []
+ for bone in self.org_bones[1:]:
+ bones += [copy_bone(self.obj, bone, make_deformer_name(strip_org(bone)))]
+
+ # Position bones
+ eb = self.obj.data.edit_bones
+ if self.use_digit_twist:
+ b1a_e = eb[b1a]
+ b1b_e = eb[b1b]
+ b1tip_e = eb[b1tip]
+
+ b1tip_e.use_connect = False
+ b1tip_e.tail += Vector((0.1, 0, 0))
+ b1tip_e.head = b1b_e.tail
+ b1tip_e.length = b1a_e.length / 4
+
+ center = (b1a_e.head + b1a_e.tail) / 2
+ b1a_e.tail = center
+ b1b_e.use_connect = False
+ b1b_e.head = center
+
+ # Parenting
+ if self.use_digit_twist:
+ b1b_e.parent = eb[self.org_bones[0]]
+ b1tip_e.parent = eb[self.org_bones[0]]
+ else:
+ eb[b1].use_connect = False
+ eb[b1].parent = eb[self.org_bones[0]]
+
+ for (ba, bb) in zip(bones, self.org_bones[1:]):
+ eb[ba].use_connect = False
+ eb[ba].parent = eb[bb]
+
+ # Constraints
+ if self.use_digit_twist:
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ b1a_p = pb[b1a]
+
+ con = b1a_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = b1a_p.constraints.new('COPY_SCALE')
+ con.name = "copy_scale"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = b1a_p.constraints.new('DAMPED_TRACK')
+ con.name = "track_to"
+ con.target = self.obj
+ con.subtarget = b1tip
+
+ def control(self):
+ """ Generate the control rig.
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Figure out the name for the control bone (remove the last .##)
+ ctrl_name = re.sub("([0-9]+\.)", "", strip_org(self.org_bones[0])[::-1], count=1)[::-1]
+
+ # Create the bones
+ ctrl = copy_bone(self.obj, self.org_bones[0], ctrl_name)
+
+ helpers = []
+ bones = []
+ for bone in self.org_bones:
+ bones += [copy_bone(self.obj, bone, strip_org(bone))]
+ helpers += [copy_bone(self.obj, bone, make_mechanism_name(strip_org(bone)))]
+
+ # Position bones
+ eb = self.obj.data.edit_bones
+
+ length = 0.0
+ for bone in helpers:
+ length += eb[bone].length
+ eb[bone].length /= 2
+
+ eb[ctrl].length = length * 1.5
+
+ # Parent bones
+ prev = eb[self.org_bones[0]].parent
+ for (b, h) in zip(bones, helpers):
+ b_e = eb[b]
+ h_e = eb[h]
+ b_e.use_connect = False
+ h_e.use_connect = False
+
+ b_e.parent = h_e
+ h_e.parent = prev
+
+ prev = b_e
+
+ # Transform locks and rotation mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ for bone in bones[1:]:
+ pb[bone].lock_location = True, True, True
+
+ if pb[self.org_bones[0]].bone.use_connect is True:
+ pb[bones[0]].lock_location = True, True, True
+
+ pb[ctrl].lock_scale = True, False, True
+
+ for bone in helpers:
+ pb[bone].rotation_mode = 'XYZ'
+
+ # Drivers
+ i = 1
+ val = 1.2 / (len(self.org_bones) - 1)
+ for bone in helpers:
+ # Add custom prop
+ prop_name = "bend_%02d" % i
+ prop = rna_idprop_ui_prop_get(pb[ctrl], prop_name, create=True)
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ if i == 1:
+ pb[ctrl][prop_name] = 0.0
+ else:
+ pb[ctrl][prop_name] = val
+
+ # Add driver
+ if 'X' in self.primary_rotation_axis:
+ fcurve = pb[bone].driver_add("rotation_euler", 0)
+ elif 'Y' in self.primary_rotation_axis:
+ fcurve = pb[bone].driver_add("rotation_euler", 1)
+ else:
+ fcurve = pb[bone].driver_add("rotation_euler", 2)
+
+ driver = fcurve.driver
+ driver.type = 'SCRIPTED'
+
+ var = driver.variables.new()
+ var.name = "ctrl_y"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[ctrl].path_from_id() + '.scale[1]'
+
+ var = driver.variables.new()
+ var.name = "bend"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[ctrl].path_from_id() + '["' + prop_name + '"]'
+
+ if '-' in self.primary_rotation_axis:
+ driver.expression = "-(1.0-ctrl_y) * bend * 3.14159 * 2"
+ else:
+ driver.expression = "(1.0-ctrl_y) * bend * 3.14159 * 2"
+
+ i += 1
+
+ # Constraints
+ con = pb[helpers[0]].constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = ctrl
+
+ con = pb[helpers[0]].constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = ctrl
+
+ # Constrain org bones to the control bones
+ for (bone, org) in zip(bones, self.org_bones):
+ con = pb[org].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = bone
+
+ # Set layers for extra control bones
+ if self.ex_layers:
+ for bone in bones:
+ pb[bone].bone.layers = self.ex_layers
+
+ # Create control widgets
+ w = create_widget(self.obj, ctrl)
+ if w is not None:
+ mesh = w.data
+ verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)]
+ if 'Z' in self.primary_rotation_axis:
+ # Flip x/z coordinates
+ temp = []
+ for v in verts:
+ temp += [(v[2], v[1], v[0])]
+ verts = temp
+ edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)]
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ for bone in bones:
+ create_limb_widget(self.obj, bone)
+
+ 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.deform()
+ self.control()
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+ params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+ params.separate_extra_layers = bpy.props.BoolProperty(name="Separate Secondary Control Layers:", default=False, description="Enable putting the secondary controls on a separate layer from the primary controls")
+ params.extra_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the secondary controls to be on")
+
+ params.use_digit_twist = bpy.props.BoolProperty(name="Digit Twist", default=True, description="Generate the dual-bone twist setup for the first finger digit")
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+ """
+ r = layout.row()
+ r.prop(params, "separate_extra_layers")
+
+ r = layout.row()
+ r.active = params.separate_extra_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "extra_layers", index=0, toggle=True, text="")
+ row.prop(params, "extra_layers", index=1, toggle=True, text="")
+ row.prop(params, "extra_layers", index=2, toggle=True, text="")
+ row.prop(params, "extra_layers", index=3, toggle=True, text="")
+ row.prop(params, "extra_layers", index=4, toggle=True, text="")
+ row.prop(params, "extra_layers", index=5, toggle=True, text="")
+ row.prop(params, "extra_layers", index=6, toggle=True, text="")
+ row.prop(params, "extra_layers", index=7, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "extra_layers", index=16, toggle=True, text="")
+ row.prop(params, "extra_layers", index=17, toggle=True, text="")
+ row.prop(params, "extra_layers", index=18, toggle=True, text="")
+ row.prop(params, "extra_layers", index=19, toggle=True, text="")
+ row.prop(params, "extra_layers", index=20, toggle=True, text="")
+ row.prop(params, "extra_layers", index=21, toggle=True, text="")
+ row.prop(params, "extra_layers", index=22, toggle=True, text="")
+ row.prop(params, "extra_layers", index=23, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ row.prop(params, "extra_layers", index=8, toggle=True, text="")
+ row.prop(params, "extra_layers", index=9, toggle=True, text="")
+ row.prop(params, "extra_layers", index=10, toggle=True, text="")
+ row.prop(params, "extra_layers", index=11, toggle=True, text="")
+ row.prop(params, "extra_layers", index=12, toggle=True, text="")
+ row.prop(params, "extra_layers", index=13, toggle=True, text="")
+ row.prop(params, "extra_layers", index=14, toggle=True, text="")
+ row.prop(params, "extra_layers", index=15, toggle=True, text="")
+ row = col.row(align=True)
+ row.prop(params, "extra_layers", index=24, toggle=True, text="")
+ row.prop(params, "extra_layers", index=25, toggle=True, text="")
+ row.prop(params, "extra_layers", index=26, toggle=True, text="")
+ row.prop(params, "extra_layers", index=27, toggle=True, text="")
+ row.prop(params, "extra_layers", index=28, toggle=True, text="")
+ row.prop(params, "extra_layers", index=29, toggle=True, text="")
+ row.prop(params, "extra_layers", index=30, toggle=True, text="")
+ row.prop(params, "extra_layers", index=31, toggle=True, text="")
+
+ r = layout.row()
+ r.label(text="Bend rotation axis:")
+ r.prop(params, "primary_rotation_axis", text="")
+
+ col = layout.column()
+ col.prop(params, "use_digit_twist")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('finger.01')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.2529, 0.0000, 0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bones['finger.01'] = bone.name
+ bone = arm.edit_bones.new('finger.02')
+ bone.head[:] = 0.2529, 0.0000, 0.0000
+ bone.tail[:] = 0.4024, 0.0000, -0.0264
+ bone.roll = -2.9671
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['finger.01']]
+ bones['finger.02'] = bone.name
+ bone = arm.edit_bones.new('finger.03')
+ bone.head[:] = 0.4024, 0.0000, -0.0264
+ bone.tail[:] = 0.4975, -0.0000, -0.0610
+ bone.roll = -2.7925
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['finger.02']]
+ bones['finger.03'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['finger.01']]
+ pbone.rigify_type = 'finger'
+ pbone.lock_location = (True, True, True)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YZX'
+ pbone = obj.pose.bones[bones['finger.02']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YZX'
+ pbone = obj.pose.bones[bones['finger.03']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YZX'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/misc/__init__.py b/rigify/legacy/rigs/misc/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/misc/__init__.py
diff --git a/rigify/legacy/rigs/misc/delta.py b/rigify/legacy/rigs/misc/delta.py
new file mode 100644
index 00000000..84f3612b
--- /dev/null
+++ b/rigify/legacy/rigs/misc/delta.py
@@ -0,0 +1,165 @@
+#====================== 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>
+
+if False:
+ # This rig type is disabled due to its obscurity.
+ # However, some of the code may be useful in the future, so
+ # I'm leaving it here.
+ from math import acos
+
+ import bpy
+
+ from ...utils import MetarigError
+ from ...utils import copy_bone
+ from ...utils import org_name, make_mechanism_name
+
+
+ class Rig:
+ """ A delta rig.
+ Creates a setup that will place its child at its position in pose mode,
+ but will not modifying its child's position in edit mode.
+ This is a mechanism-only rig (no control or deformation bones).
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ bb = obj.data.bones
+
+ if bb[bone].children is None:
+ raise MetarigError("RIGIFY ERROR: bone '%s': rig type requires one child" % org_name(bone.name))
+ if bb[bone].use_connect is True:
+ raise MetarigError("RIGIFY ERROR: bone '%s': rig type cannot be connected to parent" % org_name(bone.name))
+
+ self.obj = obj
+ self.org_bones = {"delta": bone, "child": bb[bone].children[0].name}
+ self.org_names = [org_name(bone), org_name(bb[bone].children[0].name)]
+
+ 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.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ org_delta = self.org_bones["delta"]
+ org_delta_e = eb[self.org_bones["delta"]]
+ # org_child = self.org_bones["child"] # UNUSED
+ org_child_e = eb[self.org_bones["child"]]
+
+ # Calculate the matrix for achieving the delta
+ child_mat = org_delta_e.matrix.invert() * org_child_e.matrix
+ mat = org_delta_e.matrix * child_mat.invert()
+
+ # Create the delta bones.
+ delta_e = eb[copy_bone(self.obj, self.org_bones["delta"])]
+ delta_e.name = make_mechanism_name(self.org_names[0])
+ delta = delta_e.name
+
+ # Set the delta to the matrix's transforms
+ set_mat(self.obj, delta, mat)
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Constrain org_delta to delta
+ con = self.obj.pose.bones[org_delta].constraints.new('COPY_TRANSFORMS')
+ con.name = "delta"
+ con.target = self.obj
+ con.subtarget = delta
+
+ def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('delta')
+ bone.head[:] = 0.0000, -0.1198, 0.1253
+ bone.tail[:] = -0.0000, -0.2483, 0.2785
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bones['delta'] = bone.name
+ bone = arm.edit_bones.new('Bone')
+ bone.head[:] = -0.0000, 0.0000, 0.0000
+ bone.tail[:] = -0.0000, 0.0000, 0.2000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['delta']]
+ bones['Bone'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['delta']]
+ pbone.rigify_type = 'misc.delta'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['Bone']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
+
+ def set_mat(obj, bone_name, matrix):
+ """ Sets the bone to have the given transform matrix.
+ """
+ a = obj.data.edit_bones[bone_name]
+
+ a.head = (0, 0, 0)
+ a.tail = (0, 1, 0)
+
+ a.transform(matrix)
+
+ d = acos(a.matrix.to_quaternion().dot(matrix.to_quaternion())) * 2.0
+
+ roll_1 = a.roll + d
+ roll_2 = a.roll - d
+
+ a.roll = roll_1
+ d1 = a.matrix.to_quaternion().dot(matrix.to_quaternion())
+ a.roll = roll_2
+ d2 = a.matrix.to_quaternion().dot(matrix.to_quaternion())
+
+ if d1 > d2:
+ a.roll = roll_1
+ else:
+ a.roll = roll_2
diff --git a/rigify/legacy/rigs/neck_short.py b/rigify/legacy/rigs/neck_short.py
new file mode 100644
index 00000000..63174d40
--- /dev/null
+++ b/rigify/legacy/rigs/neck_short.py
@@ -0,0 +1,388 @@
+#====================== 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 rna_prop_ui import rna_idprop_ui_prop_get
+
+from ..utils import MetarigError
+from ..utils import copy_bone, new_bone, put_bone
+from ..utils import connected_children_names
+from ..utils import strip_org, make_mechanism_name, make_deformer_name
+from ..utils import create_circle_widget
+
+
+script1 = """
+head_neck = ["%s", "%s"]
+"""
+
+script2 = """
+if is_selected(head_neck[0]):
+ layout.prop(pose_bones[head_neck[0]], '["isolate"]', text="Isolate (" + head_neck[0] + ")", slider=True)
+"""
+
+script3 = """
+if is_selected(head_neck):
+ layout.prop(pose_bones[head_neck[0]], '["neck_follow"]', text="Neck Follow Head (" + head_neck[0] + ")", slider=True)
+"""
+
+
+class Rig:
+ """ A "neck" rig. It turns a chain of bones into a rig with two controls:
+ One for the head, and one for the neck.
+
+ """
+ def __init__(self, obj, bone_name, params):
+ """ Gather and validate data about the rig.
+
+ """
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+
+ 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)))
+
+ self.isolate = False
+ if self.obj.data.bones[bone_name].parent:
+ self.isolate = True
+
+ def gen_deform(self):
+ """ Generate the deformation rig.
+
+ """
+ for name in self.org_bones:
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create deform bone
+ bone_e = eb[copy_bone(self.obj, name)]
+
+ # Change its name
+ bone_e.name = make_deformer_name(strip_org(name))
+ bone_name = bone_e.name
+
+ # Leave edit mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Get the pose bone
+ bone = self.obj.pose.bones[bone_name]
+
+ # Constrain to the original bone
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name
+
+ def gen_control(self):
+ """ Generate the control rig.
+
+ """
+ #---------------------------------
+ # Create the neck and head controls
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create bones
+ neck_ctrl = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
+ neck_follow = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[0] + ".follow")))
+ neck_child = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[0] + ".child")))
+
+ head_ctrl = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1]))
+ head_mch = new_bone(self.obj, make_mechanism_name(strip_org(self.org_bones[-1])))
+ if self.isolate:
+ head_socket1 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket1")))
+ head_socket2 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket2")))
+
+ # Create neck chain bones
+ neck = []
+ helpers = []
+ for name in self.org_bones:
+ neck += [copy_bone(self.obj, name, make_mechanism_name(strip_org(name)))]
+ helpers += [copy_bone(self.obj, neck_child, make_mechanism_name(strip_org(name + ".02")))]
+
+ # Fetch edit bones
+ eb = self.obj.data.edit_bones
+
+ neck_ctrl_e = eb[neck_ctrl]
+ neck_follow_e = eb[neck_follow]
+ neck_child_e = eb[neck_child]
+ head_ctrl_e = eb[head_ctrl]
+ head_mch_e = eb[head_mch]
+ if self.isolate:
+ head_socket1_e = eb[head_socket1]
+ head_socket2_e = eb[head_socket2]
+
+ # Parenting
+ head_ctrl_e.use_connect = False
+ head_ctrl_e.parent = neck_ctrl_e.parent
+ head_mch_e.use_connect = False
+ head_mch_e.parent = head_ctrl_e
+
+ if self.isolate:
+ head_socket1_e.use_connect = False
+ head_socket1_e.parent = neck_ctrl_e.parent
+
+ head_socket2_e.use_connect = False
+ head_socket2_e.parent = None
+
+ head_ctrl_e.parent = head_socket2_e
+
+ for (name1, name2) in zip(neck, helpers):
+ eb[name1].use_connect = False
+ eb[name1].parent = eb[name2]
+ eb[name2].use_connect = False
+ eb[name2].parent = neck_ctrl_e.parent
+
+ neck_follow_e.use_connect = False
+ neck_follow_e.parent = neck_ctrl_e.parent
+ neck_child_e.use_connect = False
+ neck_child_e.parent = neck_ctrl_e
+ neck_ctrl_e.parent = neck_follow_e
+
+ # Position
+ put_bone(self.obj, neck_follow, neck_ctrl_e.head)
+ put_bone(self.obj, neck_child, neck_ctrl_e.head)
+ put_bone(self.obj, head_ctrl, neck_ctrl_e.head)
+ put_bone(self.obj, head_mch, neck_ctrl_e.head)
+ head_mch_e.length = head_ctrl_e.length / 2
+ neck_child_e.length = neck_ctrl_e.length / 2
+
+ if self.isolate:
+ put_bone(self.obj, head_socket1, neck_ctrl_e.head)
+ head_mch_e.length /= 2
+
+ put_bone(self.obj, head_socket2, neck_ctrl_e.head)
+ head_mch_e.length /= 3
+
+ for (name1, name2) in zip(neck, helpers):
+ put_bone(self.obj, name2, eb[name1].head)
+ eb[name2].length = eb[name1].length / 2
+
+ # Switch to object mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+ neck_ctrl_p = pb[neck_ctrl]
+ neck_follow_p = pb[neck_follow]
+ # neck_child_p = pb[neck_child] # UNUSED
+ head_ctrl_p = pb[head_ctrl]
+ if self.isolate:
+ # head_socket1_p = pb[head_socket1] # UNUSED
+ head_socket2_p = pb[head_socket2]
+
+ # Custom bone appearance
+ neck_ctrl_p.custom_shape_transform = pb[self.org_bones[(len(self.org_bones) - 1) // 2]]
+ head_ctrl_p.custom_shape_transform = pb[self.org_bones[-1]]
+
+ # Custom properties
+ prop = rna_idprop_ui_prop_get(head_ctrl_p, "inf_extent", create=True)
+ head_ctrl_p["inf_extent"] = 0.5
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ prop = rna_idprop_ui_prop_get(head_ctrl_p, "neck_follow", create=True)
+ head_ctrl_p["neck_follow"] = 1.0
+ prop["min"] = 0.0
+ prop["max"] = 2.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ if self.isolate:
+ prop = rna_idprop_ui_prop_get(head_ctrl_p, "isolate", create=True)
+ head_ctrl_p["isolate"] = 0.0
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ # Constraints
+
+ # Neck follow
+ con = neck_follow_p.constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = head_ctrl
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ var.name = "follow"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = head_ctrl_p.path_from_id() + '["neck_follow"]'
+ driver.expression = "follow / 2"
+
+ # Isolate
+ if self.isolate:
+ con = head_socket2_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = head_socket1
+
+ con = head_socket2_p.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = head_socket1
+
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ var.name = "isolate"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = head_ctrl_p.path_from_id() + '["isolate"]'
+ driver.expression = "1.0 - isolate"
+
+ # Neck chain
+ first = True
+ prev = None
+ i = 0
+ l = len(neck)
+ for (name1, name2, org_name) in zip(neck, helpers, self.org_bones):
+ con = pb[org_name].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name1
+
+ n_con = pb[name2].constraints.new('COPY_TRANSFORMS')
+ n_con.name = "neck"
+ n_con.target = self.obj
+ n_con.subtarget = neck_child
+
+ h_con = pb[name2].constraints.new('COPY_TRANSFORMS')
+ h_con.name = "head"
+ h_con.target = self.obj
+ h_con.subtarget = head_mch
+
+ con = pb[name2].constraints.new('COPY_LOCATION')
+ con.name = "anchor"
+ con.target = self.obj
+ if first:
+ con.subtarget = neck_ctrl
+ else:
+ con.subtarget = prev
+ con.head_tail = 1.0
+
+ # Drivers
+ n = (i + 1) / l
+
+ # Neck influence
+ fcurve = n_con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ var.name = "ext"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
+ driver.expression = "1.0 if (%.4f > (1.0-ext) or (1.0-ext) == 0.0) else (%.4f / (1.0-ext))" % (n, n)
+
+ # Head influence
+ if (i + 1) == l:
+ h_con.influence = 1.0
+ else:
+ fcurve = h_con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'SCRIPTED'
+ var.name = "ext"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
+ driver.expression = "0.0 if (%.4f <= (1.0-ext)) else ((%.4f - (1.0-ext)) / ext)" % (n, n)
+
+ first = False
+ prev = name1
+ i += 1
+
+ # Create control widgets
+ create_circle_widget(self.obj, neck_ctrl, radius=1.0, head_tail=0.5, bone_transform_name=self.org_bones[(len(self.org_bones) - 1) // 2])
+ create_circle_widget(self.obj, head_ctrl, radius=1.0, head_tail=0.5, bone_transform_name=self.org_bones[-1])
+
+ # Return control bones
+ return (head_ctrl, neck_ctrl)
+
+ 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.gen_deform()
+ (head, neck) = self.gen_control()
+
+ script = script1 % (head, neck)
+ if self.isolate:
+ script += script2
+ script += script3
+
+ return [script]
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('neck')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, -0.0500, 0.1500
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['neck'] = bone.name
+ bone = arm.edit_bones.new('head')
+ bone.head[:] = 0.0000, -0.0500, 0.1500
+ bone.tail[:] = 0.0000, -0.0500, 0.4000
+ bone.roll = 3.1416
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['neck']]
+ bones['head'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['neck']]
+ pbone.rigify_type = 'neck_short'
+ pbone.lock_location = (True, True, True)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['head']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/palm.py b/rigify/legacy/rigs/palm.py
new file mode 100644
index 00000000..6bcaad11
--- /dev/null
+++ b/rigify/legacy/rigs/palm.py
@@ -0,0 +1,273 @@
+#====================== 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 re
+from math import cos, pi
+
+import bpy
+
+from ..utils import MetarigError
+from ..utils import copy_bone
+from ..utils import strip_org, deformer
+from ..utils import create_widget
+
+
+def bone_siblings(obj, bone):
+ """ Returns a list of the siblings of the given bone.
+ This requires that the bones has a parent.
+
+ """
+ parent = obj.data.bones[bone].parent
+
+ if parent is None:
+ return []
+
+ bones = []
+
+ for b in parent.children:
+ if b.name != bone:
+ bones += [b.name]
+
+ return bones
+
+
+def bone_distance(obj, bone1, bone2):
+ """ Returns the distance between two bones.
+
+ """
+ vec = obj.data.bones[bone1].head - obj.data.bones[bone2].head
+ return vec.length
+
+
+class Rig:
+ """ A "palm" rig. A set of sibling bones that bend with each other.
+ This is a control and deformation rig.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ """
+ self.obj = obj
+ self.params = params
+
+ siblings = bone_siblings(obj, bone)
+
+ if len(siblings) == 0:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': must have a parent and at least one sibling" % (strip_org(bone)))
+
+ # Sort list by name and distance
+ siblings.sort()
+ siblings.sort(key=lambda b: bone_distance(obj, bone, b))
+
+ self.org_bones = [bone] + siblings
+
+ # Get rig parameters
+ self.palm_rotation_axis = params.palm_rotation_axis
+
+ 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.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Figure out the name for the control bone (remove the last .##)
+ last_bone = self.org_bones[-1:][0]
+ ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1]
+
+ # Make control bone
+ ctrl = copy_bone(self.obj, last_bone, ctrl_name)
+
+ # Make deformation bones
+ def_bones = []
+ for bone in self.org_bones:
+ b = copy_bone(self.obj, bone, deformer(strip_org(bone)))
+ def_bones += [b]
+
+ # Parenting
+ eb = self.obj.data.edit_bones
+
+ for d, b in zip(def_bones, self.org_bones):
+ eb[d].use_connect = False
+ eb[d].parent = eb[b]
+
+ # Constraints
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ i = 0
+ div = len(self.org_bones) - 1
+ for b in self.org_bones:
+ con = pb[b].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = ctrl
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+ con.influence = i / div
+
+ con = pb[b].constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = ctrl
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+ if 'X' in self.palm_rotation_axis:
+ con.invert_x = True
+ con.use_x = True
+ con.use_z = False
+ else:
+ con.invert_z = True
+ con.use_x = False
+ con.use_z = True
+ con.use_y = False
+
+ con.influence = (i / div) - (1 - cos((i * pi / 2) / div))
+
+ i += 1
+
+ # Create control widget
+ w = create_widget(self.obj, ctrl)
+ if w is not None:
+ mesh = w.data
+ verts = [(0.15780271589756012, 2.086162567138672e-07, -0.30000004172325134), (0.15780259668827057, 1.0, -0.2000001072883606), (-0.15780280530452728, 0.9999999403953552, -0.20000004768371582), (-0.15780259668827057, -2.086162567138672e-07, -0.29999998211860657), (-0.15780256688594818, -2.7089754439657554e-07, 0.30000004172325134), (-0.1578027755022049, 0.9999998807907104, 0.19999995827674866), (0.15780262649059296, 0.9999999403953552, 0.19999989867210388), (0.1578027456998825, 1.4633496903115883e-07, 0.29999998211860657), (0.15780268609523773, 0.2500001788139343, -0.27500003576278687), (-0.15780264139175415, 0.24999985098838806, -0.2749999761581421), (0.15780262649059296, 0.7500000596046448, -0.22500008344650269), (-0.1578027606010437, 0.7499998807907104, -0.2250000238418579), (0.15780265629291534, 0.75, 0.22499991953372955), (0.15780271589756012, 0.2500000596046448, 0.2749999761581421), (-0.15780261158943176, 0.2499997615814209, 0.27500003576278687), (-0.1578027307987213, 0.7499998807907104, 0.22499997913837433)]
+ if 'Z' in self.palm_rotation_axis:
+ # Flip x/z coordinates
+ temp = []
+ for v in verts:
+ temp += [(v[2], v[1], v[0])]
+ verts = temp
+ edges = [(1, 2), (0, 3), (4, 7), (5, 6), (8, 0), (9, 3), (10, 1), (11, 2), (12, 6), (13, 7), (4, 14), (15, 5), (10, 8), (11, 9), (15, 14), (12, 13)]
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = w.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+
+ """
+ items = [('X', 'X', ''), ('Z', 'Z', '')]
+ params.palm_rotation_axis = bpy.props.EnumProperty(items=items, name="Palm Rotation Axis", default='X')
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+
+ """
+ r = layout.row()
+ r.label(text="Primary rotation axis:")
+ r.prop(params, "palm_rotation_axis", text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('palm.parent')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0577, 0.0000, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bones['palm.parent'] = bone.name
+ bone = arm.edit_bones.new('palm.04')
+ bone.head[:] = 0.0577, 0.0315, -0.0000
+ bone.tail[:] = 0.1627, 0.0315, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.04'] = bone.name
+ bone = arm.edit_bones.new('palm.03')
+ bone.head[:] = 0.0577, 0.0105, -0.0000
+ bone.tail[:] = 0.1627, 0.0105, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.03'] = bone.name
+ bone = arm.edit_bones.new('palm.02')
+ bone.head[:] = 0.0577, -0.0105, -0.0000
+ bone.tail[:] = 0.1627, -0.0105, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.02'] = bone.name
+ bone = arm.edit_bones.new('palm.01')
+ bone.head[:] = 0.0577, -0.0315, -0.0000
+ bone.tail[:] = 0.1627, -0.0315, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.01'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['palm.parent']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['palm.04']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.03']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.02']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.01']]
+ pbone.rigify_type = 'palm'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/__init__.py b/rigify/legacy/rigs/pitchipoy/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/__init__.py
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/__init__.py b/rigify/legacy/rigs/pitchipoy/limbs/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/__init__.py
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/arm.py b/rigify/legacy/rigs/pitchipoy/limbs/arm.py
new file mode 100644
index 00000000..43327ec8
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/arm.py
@@ -0,0 +1,116 @@
+#====================== 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 ....utils import MetarigError
+from ....utils import create_widget, copy_bone
+from ....utils import strip_org
+from .limb_utils import *
+from ..super_widgets import create_hand_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+def create_arm( cls, bones ):
+ org_bones = cls.org_bones
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = cls.obj.data.edit_bones
+
+ ctrl = get_bone_name( org_bones[2], 'ctrl', 'ik' )
+
+ # Create IK arm control
+ ctrl = copy_bone( cls.obj, org_bones[2], ctrl )
+
+ # clear parent (so that rigify will parent to root)
+ eb[ ctrl ].parent = None
+ eb[ ctrl ].use_connect = False
+
+ # Parent
+ eb[ bones['ik']['mch_target'] ].parent = eb[ ctrl ]
+ eb[ bones['ik']['mch_target'] ].use_connect = False
+
+ # Set up constraints
+ # Constrain mch target bone to the ik control and mch stretch
+
+ make_constraint( cls, bones['ik']['mch_target'], {
+ 'constraint' : 'COPY_LOCATION',
+ 'subtarget' : bones['ik']['mch_str'],
+ 'head_tail' : 1.0
+ })
+
+ # Constrain mch ik stretch bone to the ik control
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : ctrl,
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : ctrl,
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'LIMIT_SCALE',
+ 'use_min_y' : True,
+ 'use_max_y' : True,
+ 'max_y' : 1.05,
+ 'owner_space' : 'LOCAL'
+ })
+
+ pb = cls.obj.pose.bones
+
+ # Modify rotation mode for ik and tweak controls
+ pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
+
+ for b in bones['tweak']['ctrl']:
+ pb[b].rotation_mode = 'ZXY'
+
+ # Create ik/fk switch property
+ pb_parent = pb[ bones['parent'] ]
+
+ pb_parent['IK_Strertch'] = 1.0
+ prop = rna_idprop_ui_prop_get( pb_parent, 'IK_Strertch', create=True )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = 'IK Stretch'
+
+ # Add driver to limit scale constraint influence
+ b = bones['ik']['mch_str']
+ drv = pb[b].constraints[-1].driver_add("influence").driver
+ drv.type = 'SUM'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = cls.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ drv_modifier = cls.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+ # Create hand widget
+ create_hand_widget(cls.obj, ctrl, bone_transform_name=None)
+
+ bones['ik']['ctrl']['terminal'] = [ ctrl ]
+
+ return bones
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/leg.py b/rigify/legacy/rigs/pitchipoy/limbs/leg.py
new file mode 100644
index 00000000..9176bd92
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/leg.py
@@ -0,0 +1,333 @@
+#====================== 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, math
+from ....utils import MetarigError, connected_children_names
+from ....utils import create_widget, copy_bone, create_circle_widget
+from ....utils import strip_org, flip_bone, put_bone
+from rna_prop_ui import rna_idprop_ui_prop_get
+from ..super_widgets import create_foot_widget, create_ballsocket_widget
+from .limb_utils import *
+
+def create_leg( cls, bones ):
+ org_bones = list(
+ [cls.org_bones[0]] + connected_children_names(cls.obj, cls.org_bones[0])
+ )
+
+ bones['ik']['ctrl']['terminal'] = []
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = cls.obj.data.edit_bones
+
+ # Create toes def bone
+ toes_def = get_bone_name( org_bones[-1], 'def' )
+ toes_def = copy_bone( cls.obj, org_bones[-1], toes_def )
+
+ eb[ toes_def ].use_connect = False
+ eb[ toes_def ].parent = eb[ bones['def'][-1] ]
+ eb[ toes_def ].use_connect = True
+
+ bones['def'] += [ toes_def ]
+
+ # Create IK leg control
+ ctrl = get_bone_name( org_bones[2], 'ctrl', 'ik' )
+ ctrl = copy_bone( cls.obj, org_bones[2], ctrl )
+
+ # clear parent (so that rigify will parent to root)
+ eb[ ctrl ].parent = None
+ eb[ ctrl ].use_connect = False
+
+ # Create heel ctrl bone
+ heel = get_bone_name( org_bones[2], 'ctrl', 'heel_ik' )
+ heel = copy_bone( cls.obj, org_bones[2], heel )
+ orient_bone( cls, eb[ heel ], 'y', 0.5 )
+ eb[ heel ].length = eb[ org_bones[2] ].length / 2
+
+ # Reset control position and orientation
+ l = eb[ ctrl ].length
+ orient_bone( cls, eb[ ctrl ], 'y', reverse = True )
+ eb[ ctrl ].length = l
+
+ # Parent
+ eb[ heel ].use_connect = False
+ eb[ heel ].parent = eb[ ctrl ]
+
+ eb[ bones['ik']['mch_target'] ].parent = eb[ heel ]
+ eb[ bones['ik']['mch_target'] ].use_connect = False
+
+ # Create foot mch rock and roll bones
+
+ # Get the tmp heel (floating unconnected without children)
+ tmp_heel = ""
+ for b in cls.obj.data.bones[ org_bones[2] ].children:
+ if not b.use_connect and not b.children:
+ tmp_heel = b.name
+
+ # roll1 MCH bone
+ roll1_mch = get_bone_name( tmp_heel, 'mch', 'roll' )
+ roll1_mch = copy_bone( cls.obj, org_bones[2], roll1_mch )
+
+ # clear parent
+ eb[ roll1_mch ].use_connect = False
+ eb[ roll1_mch ].parent = None
+
+ flip_bone( cls.obj, roll1_mch )
+
+ # Create 2nd roll mch, and two rock mch bones
+ roll2_mch = get_bone_name( tmp_heel, 'mch', 'roll' )
+ roll2_mch = copy_bone( cls.obj, org_bones[3], roll2_mch )
+
+ eb[ roll2_mch ].use_connect = False
+ eb[ roll2_mch ].parent = None
+
+ put_bone(
+ cls.obj,
+ roll2_mch,
+ ( eb[ tmp_heel ].head + eb[ tmp_heel ].tail ) / 2
+ )
+
+ eb[ roll2_mch ].length /= 4
+
+ # Rock MCH bones
+ rock1_mch = get_bone_name( tmp_heel, 'mch', 'rock' )
+ rock1_mch = copy_bone( cls.obj, tmp_heel, rock1_mch )
+
+ eb[ rock1_mch ].use_connect = False
+ eb[ rock1_mch ].parent = None
+
+ orient_bone( cls, eb[ rock1_mch ], 'y', 1.0, reverse = True )
+ eb[ rock1_mch ].length = eb[ tmp_heel ].length / 2
+
+ rock2_mch = get_bone_name( tmp_heel, 'mch', 'rock' )
+ rock2_mch = copy_bone( cls.obj, tmp_heel, rock2_mch )
+
+ eb[ rock2_mch ].use_connect = False
+ eb[ rock2_mch ].parent = None
+
+ orient_bone( cls, eb[ rock2_mch ], 'y', 1.0 )
+ eb[ rock2_mch ].length = eb[ tmp_heel ].length / 2
+
+ # Parent rock and roll MCH bones
+ eb[ roll1_mch ].parent = eb[ roll2_mch ]
+ eb[ roll2_mch ].parent = eb[ rock1_mch ]
+ eb[ rock1_mch ].parent = eb[ rock2_mch ]
+ eb[ rock2_mch ].parent = eb[ ctrl ]
+
+ # Constrain rock and roll MCH bones
+ make_constraint( cls, roll1_mch, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( cls, roll1_mch, {
+ 'constraint' : 'LIMIT_ROTATION',
+ 'use_limit_x' : True,
+ 'max_x' : math.radians(360),
+ 'owner_space' : 'LOCAL'
+ })
+ make_constraint( cls, roll2_mch, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'use_y' : False,
+ 'use_z' : False,
+ 'invert_x' : True,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( cls, roll2_mch, {
+ 'constraint' : 'LIMIT_ROTATION',
+ 'use_limit_x' : True,
+ 'max_x' : math.radians(360),
+ 'owner_space' : 'LOCAL'
+ })
+
+ pb = cls.obj.pose.bones
+ for i,b in enumerate([ rock1_mch, rock2_mch ]):
+ head_tail = pb[b].head - pb[tmp_heel].head
+ if '.L' in b:
+ if not i:
+ min_y = 0
+ max_y = math.radians(360)
+ else:
+ min_y = math.radians(-360)
+ max_y = 0
+ else:
+ if not i:
+ min_y = math.radians(-360)
+ max_y = 0
+ else:
+ min_y = 0
+ max_y = math.radians(360)
+
+
+ make_constraint( cls, b, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'use_x' : False,
+ 'use_z' : False,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( cls, b, {
+ 'constraint' : 'LIMIT_ROTATION',
+ 'use_limit_y' : True,
+ 'min_y' : min_y,
+ 'max_y' : max_y,
+ 'owner_space' : 'LOCAL'
+ })
+
+ # Constrain 4th ORG to roll2 MCH bone
+ make_constraint( cls, org_bones[3], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : roll2_mch
+ })
+
+ # Set up constraints
+ # Constrain mch target bone to the ik control and mch stretch
+
+ make_constraint( cls, bones['ik']['mch_target'], {
+ 'constraint' : 'COPY_LOCATION',
+ 'subtarget' : bones['ik']['mch_str'],
+ 'head_tail' : 1.0
+ })
+
+ # Constrain mch ik stretch bone to the ik control
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : roll1_mch,
+ 'head_tail' : 1.0
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : roll1_mch,
+ 'head_tail' : 1.0
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'LIMIT_SCALE',
+ 'use_min_y' : True,
+ 'use_max_y' : True,
+ 'max_y' : 1.05,
+ 'owner_space' : 'LOCAL'
+ })
+
+ # Modify rotation mode for ik and tweak controls
+ pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
+
+ for b in bones['tweak']['ctrl']:
+ pb[b].rotation_mode = 'ZXY'
+
+ # Create ik/fk switch property
+ pb_parent = pb[ bones['parent'] ]
+
+ pb_parent['IK_Strertch'] = 1.0
+ prop = rna_idprop_ui_prop_get( pb_parent, 'IK_Strertch', create=True )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = 'IK Stretch'
+
+ # Add driver to limit scale constraint influence
+ b = bones['ik']['mch_str']
+ drv = pb[b].constraints[-1].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = cls.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ drv_modifier = cls.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+ # Create leg widget
+ create_foot_widget(cls.obj, ctrl, bone_transform_name=None)
+
+ # Create heel ctrl locks
+ pb[ heel ].lock_location = True, True, True
+ pb[ heel ].lock_rotation = False, False, True
+ pb[ heel ].lock_scale = True, True, True
+
+ # Add ballsocket widget to heel
+ create_ballsocket_widget(cls.obj, heel, bone_transform_name=None)
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = cls.obj.data.edit_bones
+
+ if len( org_bones ) >= 4:
+ # Create toes control bone
+ toes = get_bone_name( org_bones[3], 'ctrl' )
+ toes = copy_bone( cls.obj, org_bones[3], toes )
+
+ eb[ toes ].use_connect = False
+ eb[ toes ].parent = eb[ org_bones[3] ]
+
+ # Constrain toes def bones
+ make_constraint( cls, bones['def'][-2], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : toes
+ })
+ make_constraint( cls, bones['def'][-2], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : toes
+ })
+
+ make_constraint( cls, bones['def'][-1], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : toes
+ })
+
+ # Find IK/FK switch property
+ pb = cls.obj.pose.bones
+ prop = rna_idprop_ui_prop_get( pb[ bones['parent'] ], 'IK/FK' )
+
+ # Add driver to limit scale constraint influence
+ b = org_bones[3]
+ drv = pb[b].constraints[-1].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = cls.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ drv_modifier = cls.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+ # Create toe circle widget
+ create_circle_widget(cls.obj, toes, radius=0.4, head_tail=0.5)
+
+ bones['ik']['ctrl']['terminal'] += [ toes ]
+
+ bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
+
+ return bones
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py b/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py
new file mode 100644
index 00000000..73e4f472
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py
@@ -0,0 +1,70 @@
+import bpy, re
+from mathutils import Vector
+from ....utils import org, strip_org, make_mechanism_name, make_deformer_name
+from ....utils import MetarigError
+
+bilateral_suffixes = ['.L','.R']
+
+def orient_bone( cls, eb, axis, scale = 1.0, reverse = False ):
+ v = Vector((0,0,0))
+
+ setattr(v,axis,scale)
+
+ if reverse:
+ tail_vec = v * cls.obj.matrix_world
+ eb.head[:] = eb.tail
+ eb.tail[:] = eb.head + tail_vec
+ else:
+ tail_vec = v * cls.obj.matrix_world
+ eb.tail[:] = eb.head + tail_vec
+
+ eb.roll = 0.0
+
+def make_constraint( cls, bone, constraint ):
+ bpy.ops.object.mode_set(mode = 'OBJECT')
+ pb = cls.obj.pose.bones
+
+ owner_pb = pb[bone]
+ const = owner_pb.constraints.new( constraint['constraint'] )
+
+ constraint['target'] = cls.obj
+
+ # filter contraint props to those that actually exist in the currnet
+ # type of constraint, then assign values to each
+ for p in [ k for k in constraint.keys() if k in dir(const) ]:
+ if p in dir( const ):
+ setattr( const, p, constraint[p] )
+ else:
+ raise MetarigError(
+ "RIGIFY ERROR: property %s does not exist in %s constraint" % (
+ p, constraint['constraint']
+ ))
+
+def get_bone_name( name, btype, suffix = '' ):
+ # RE pattern match right or left parts
+ # match the letter "L" (or "R"), followed by an optional dot (".")
+ # and 0 or more digits at the end of the the string
+ pattern = r'^(\S+)(\.\S+)$'
+
+ name = strip_org( name )
+
+ types = {
+ 'mch' : make_mechanism_name( name ),
+ 'org' : org( name ),
+ 'def' : make_deformer_name( name ),
+ 'ctrl' : name
+ }
+
+ name = types[btype]
+
+ if suffix:
+ results = re.match( pattern, name )
+ bname, addition = ('','')
+
+ if results:
+ bname, addition = results.groups()
+ name = bname + "_" + suffix + addition
+ else:
+ name = name + "_" + suffix
+
+ return name
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/paw.py b/rigify/legacy/rigs/pitchipoy/limbs/paw.py
new file mode 100644
index 00000000..89de5e90
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/paw.py
@@ -0,0 +1,214 @@
+#====================== 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 ....utils import MetarigError, connected_children_names
+from ....utils import create_widget, copy_bone, create_circle_widget
+from ....utils import strip_org, flip_bone
+from rna_prop_ui import rna_idprop_ui_prop_get
+from ..super_widgets import create_foot_widget, create_ballsocket_widget
+from .limb_utils import *
+
+def create_paw( cls, bones ):
+ org_bones = list(
+ [cls.org_bones[0]] + connected_children_names(cls.obj, cls.org_bones[0])
+ )
+
+
+ bones['ik']['ctrl']['terminal'] = []
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = cls.obj.data.edit_bones
+
+ # Create IK paw control
+ ctrl = get_bone_name( org_bones[2], 'ctrl', 'ik' )
+ ctrl = copy_bone( cls.obj, org_bones[2], ctrl )
+
+ # clear parent (so that rigify will parent to root)
+ eb[ ctrl ].parent = None
+ eb[ ctrl ].use_connect = False
+
+ # Create heel control bone
+ heel = get_bone_name( org_bones[2], 'ctrl', 'heel_ik' )
+ heel = copy_bone( cls.obj, org_bones[2], heel )
+
+ # clear parent
+ eb[ heel ].parent = None
+ eb[ heel ].use_connect = False
+
+ # Parent
+ eb[ heel ].parent = eb[ ctrl ]
+ eb[ heel ].use_connect = False
+
+ flip_bone( cls.obj, heel )
+
+ eb[ bones['ik']['mch_target'] ].parent = eb[ heel ]
+ eb[ bones['ik']['mch_target'] ].use_connect = False
+
+ # Reset control position and orientation
+ l = eb[ ctrl ].length
+ orient_bone( cls, eb[ ctrl ], 'y', reverse = True )
+ eb[ ctrl ].length = l
+
+ # Set up constraints
+ # Constrain mch target bone to the ik control and mch stretch
+
+ make_constraint( cls, bones['ik']['mch_target'], {
+ 'constraint' : 'COPY_LOCATION',
+ 'subtarget' : bones['ik']['mch_str'],
+ 'head_tail' : 1.0
+ })
+
+ # Constrain mch ik stretch bone to the ik control
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : heel,
+ 'head_tail' : 1.0
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : heel,
+ 'head_tail' : 1.0
+ })
+ make_constraint( cls, bones['ik']['mch_str'], {
+ 'constraint' : 'LIMIT_SCALE',
+ 'use_min_y' : True,
+ 'use_max_y' : True,
+ 'max_y' : 1.05,
+ 'owner_space' : 'LOCAL'
+ })
+
+ pb = cls.obj.pose.bones
+
+ # Modify rotation mode for ik and tweak controls
+ pb[bones['ik']['ctrl']['limb']].rotation_mode = 'ZXY'
+
+ for b in bones['tweak']['ctrl']:
+ pb[b].rotation_mode = 'ZXY'
+
+ # Create ik/fk switch property
+ pb_parent = pb[ bones['parent'] ]
+
+ pb_parent['IK_Strertch'] = 1.0
+ prop = rna_idprop_ui_prop_get( pb_parent, 'IK_Strertch', create=True )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = 'IK Stretch'
+
+ # Add driver to limit scale constraint influence
+ b = bones['ik']['mch_str']
+ drv = pb[b].constraints[-1].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = cls.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ drv_modifier = cls.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+ # Create paw widget
+ create_foot_widget(cls.obj, ctrl, bone_transform_name=None)
+
+ # Create heel ctrl locks
+ pb[ heel ].lock_location = True, True, True
+
+ # Add ballsocket widget to heel
+ create_ballsocket_widget(cls.obj, heel, bone_transform_name=None)
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = cls.obj.data.edit_bones
+
+ if len( org_bones ) >= 4:
+ # Create toes control bone
+ toes = get_bone_name( org_bones[3], 'ctrl' )
+ toes = copy_bone( cls.obj, org_bones[3], toes )
+
+ eb[ toes ].use_connect = False
+ eb[ toes ].parent = eb[ org_bones[3] ]
+
+ # Create toes mch bone
+ toes_mch = get_bone_name( org_bones[3], 'mch' )
+ toes_mch = copy_bone( cls.obj, org_bones[3], toes_mch )
+
+ eb[ toes_mch ].use_connect = False
+ eb[ toes_mch ].parent = eb[ ctrl ]
+
+ eb[ toes_mch ].length /= 4
+
+ # Constrain 4th ORG to toes MCH bone
+ make_constraint( cls, org_bones[3], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : toes_mch
+ })
+
+ # Constrain toes def bones
+
+ make_constraint( cls, bones['def'][-1], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : toes,
+ 'head_tail' : 1
+ })
+ make_constraint( cls, bones['def'][-1], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : toes,
+ 'head_tail' : 1
+ })
+
+
+ # Find IK/FK switch property
+ pb = cls.obj.pose.bones
+ prop = rna_idprop_ui_prop_get( pb[ bones['parent'] ], 'IK/FK' )
+
+ # Add driver to limit scale constraint influence
+ b = org_bones[3]
+ drv = pb[b].constraints[-1].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = cls.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ drv_modifier = cls.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+ # Create toe circle widget
+ create_circle_widget(cls.obj, toes, radius=0.4, head_tail=0.5)
+
+ bones['ik']['ctrl']['terminal'] += [ toes ]
+
+ bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
+
+ return bones
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/super_limb.py b/rigify/legacy/rigs/pitchipoy/limbs/super_limb.py
new file mode 100644
index 00000000..91efdb48
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/super_limb.py
@@ -0,0 +1,785 @@
+import bpy, re
+from .arm import create_arm
+from .leg import create_leg
+from .paw import create_paw
+from .ui import create_script
+from .limb_utils import *
+from mathutils import Vector
+from ....utils import copy_bone, flip_bone, put_bone, create_cube_widget
+from ....utils import strip_org, make_deformer_name, create_widget
+from ....utils import create_circle_widget, create_sphere_widget
+from ....utils import MetarigError, make_mechanism_name, org
+from ....utils import create_limb_widget, connected_children_names
+from rna_prop_ui import rna_idprop_ui_prop_get
+from ..super_widgets import create_ikarrow_widget
+from math import trunc
+
+
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ """ Initialize super_limb rig and key rig properties """
+ self.obj = obj
+ self.params = params
+
+ if params.limb_type != 'paw':
+ self.org_bones = list(
+ [bone_name] + connected_children_names(obj, bone_name)
+ )[:3] # The basic limb is the first 3 bones
+ else:
+ self.org_bones = list(
+ [bone_name] + connected_children_names(obj, bone_name)
+ )[:4] # The basic limb is the first 4 bones for a paw
+
+ self.segments = params.segments
+ self.bbones = params.bbones
+ self.limb_type = params.limb_type
+ self.rot_axis = params.rotation_axis
+
+ # Assign values to tweak/FK layers props if opted by user
+ if params.tweak_extra_layers:
+ self.tweak_layers = list(params.tweak_layers)
+ else:
+ self.tweak_layers = None
+
+ if params.fk_extra_layers:
+ self.fk_layers = list(params.fk_layers)
+ else:
+ self.fk_layers = None
+
+ def create_parent(self):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ name = get_bone_name( strip_org( org_bones[0] ), 'mch', 'parent' )
+
+ mch = copy_bone( self.obj, org_bones[0], name )
+ orient_bone( self, eb[mch], 'y' )
+ eb[ mch ].length = eb[ org_bones[0] ].length / 4
+
+ eb[ mch ].parent = eb[ org_bones[0] ].parent
+
+ eb[ mch ].roll = 0.0
+
+ # Constraints
+ make_constraint( self, mch, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : 'root'
+ })
+
+ make_constraint( self, mch, {
+ 'constraint' : 'COPY_SCALE',
+ 'subtarget' : 'root'
+ })
+
+ # Limb Follow Driver
+ pb = self.obj.pose.bones
+
+ name = 'FK_limb_follow'
+
+ pb[ mch ][ name ] = 0.0
+ prop = rna_idprop_ui_prop_get( pb[ mch ], name, create = True )
+
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = name
+
+ drv = pb[ mch ].constraints[ 0 ].driver_add("influence").driver
+
+ drv.type = 'AVERAGE'
+ var = drv.variables.new()
+ var.name = name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[ mch ].path_from_id() + \
+ '[' + '"' + name + '"' + ']'
+
+ return mch
+
+ def create_tweak( self ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ tweaks = {}
+ tweaks['ctrl'] = []
+ tweaks['mch' ] = []
+
+ # Create and parent mch and ctrl tweaks
+ for i,org in enumerate(org_bones):
+ if i < len(org_bones) - 1:
+ # Create segments if specified
+ for j in range( self.segments ):
+ # MCH
+ name = get_bone_name( strip_org(org), 'mch', 'tweak' )
+ mch = copy_bone( self.obj, org, name )
+
+ # CTRL
+ name = get_bone_name( strip_org(org), 'ctrl', 'tweak' )
+ ctrl = copy_bone( self.obj, org, name )
+
+ eb[ mch ].length /= self.segments
+ eb[ ctrl ].length /= self.segments
+
+ # If we have more than one segments, place the head of the
+ # 2nd and onwards at the correct position
+ if j > 0:
+ put_bone(self.obj, mch, eb[ tweaks['mch' ][-1] ].tail)
+ put_bone(self.obj, ctrl, eb[ tweaks['ctrl'][-1] ].tail)
+
+ tweaks['ctrl'] += [ ctrl ]
+ tweaks['mch' ] += [ mch ]
+
+ # Parenting the tweak ctrls to mchs
+ eb[ mch ].parent = eb[ org ]
+ eb[ ctrl ].parent = eb[ mch ]
+
+ else: # Last limb bone - is not subdivided
+ name = get_bone_name( strip_org(org), 'mch', 'tweak' )
+ mch = copy_bone( self.obj, org_bones[i-1], name )
+ eb[ mch ].length = eb[org].length / 4
+ put_bone(
+ self.obj,
+ mch,
+ eb[org_bones[i-1]].tail
+ )
+
+ ctrl = get_bone_name( strip_org(org), 'ctrl', 'tweak' )
+ ctrl = copy_bone( self.obj, org, ctrl )
+ eb[ ctrl ].length = eb[org].length / 2
+
+ tweaks['mch'] += [ mch ]
+ tweaks['ctrl'] += [ ctrl ]
+
+ # Parenting the tweak ctrls to mchs
+ eb[ mch ].parent = eb[ org ]
+ eb[ ctrl ].parent = eb[ mch ]
+
+ # Scale to reduce widget size and maintain conventions!
+ for mch, ctrl in zip( tweaks['mch'], tweaks['ctrl'] ):
+ eb[ mch ].length /= 4
+ eb[ ctrl ].length /= 2
+
+ # Contraints
+ if self.limb_type == 'paw':
+
+ for i,b in enumerate( tweaks['mch'] ):
+ first = 0
+ middle = trunc( len( tweaks['mch'] ) / 3 )
+ middle1 = middle + self.segments
+ last = len( tweaks['mch'] ) - 1
+
+ if i == first or i == middle or i == middle1:
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_SCALE',
+ 'subtarget' : 'root'
+ })
+ elif i != last:
+ targets = []
+ factor = 0
+ if i < middle:
+ dt_target_idx = middle
+ targets = [first,middle]
+ elif i > middle and i < middle1:
+ targets = [middle,middle1]
+ factor = self.segments
+ dt_target_idx = middle1
+ else:
+ targets = [middle1,last]
+ factor = self.segments * 2
+ dt_target_idx = last
+
+
+ # Use copy transforms constraints to position each bone
+ # exactly in the location respective to its index (between
+ # the two edges)
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : tweaks['ctrl'][targets[0]],
+ })
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : tweaks['ctrl'][targets[1]],
+ 'influence' : (i - factor) / self.segments
+ })
+ make_constraint( self, b, {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : tweaks['ctrl'][ dt_target_idx ],
+ })
+
+ else:
+ for i,b in enumerate( tweaks['mch'] ):
+ first = 0
+ middle = trunc( len( tweaks['mch'] ) / 2 )
+ last = len( tweaks['mch'] ) - 1
+
+ if i == first or i == middle:
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_SCALE',
+ 'subtarget' : 'root'
+ })
+ elif i != last:
+ targets = []
+ dt_target_idx = middle
+ factor = 0
+ if i < middle:
+ targets = [first,middle]
+ else:
+ targets = [middle,last]
+ factor = self.segments
+ dt_target_idx = last
+
+ # Use copy transforms constraints to position each bone
+ # exactly in the location respective to its index (between
+ # the two edges)
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : tweaks['ctrl'][targets[0]],
+ })
+ make_constraint( self, b, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : tweaks['ctrl'][targets[1]],
+ 'influence' : (i - factor) / self.segments
+ })
+ make_constraint( self, b, {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : tweaks['ctrl'][ dt_target_idx ],
+ })
+
+ # Ctrl bones Locks and Widgets
+ pb = self.obj.pose.bones
+ for t in tweaks['ctrl']:
+ pb[t].lock_rotation = True, False, True
+ pb[t].lock_scale = False, True, False
+
+ create_sphere_widget(self.obj, t, bone_transform_name=None)
+
+ if self.tweak_layers:
+ pb[t].bone.layers = self.tweak_layers
+
+ return tweaks
+
+
+ def create_def( self, tweaks ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ def_bones = []
+ for i,org in enumerate(org_bones):
+ if i < len(org_bones) - 1:
+ # Create segments if specified
+ for j in range( self.segments ):
+ name = get_bone_name( strip_org(org), 'def' )
+ def_name = copy_bone( self.obj, org, name )
+
+ eb[ def_name ].length /= self.segments
+
+ # If we have more than one segments, place the 2nd and
+ # onwards on the tail of the previous bone
+ if j > 0:
+ put_bone(self.obj, def_name, eb[ def_bones[-1] ].tail)
+
+ def_bones += [ def_name ]
+ else:
+ name = get_bone_name( strip_org(org), 'def' )
+ def_name = copy_bone( self.obj, org, name )
+ def_bones.append( def_name )
+
+ # Parent deform bones
+ for i,b in enumerate( def_bones ):
+ if i > 0: # For all bones but the first (which has no parent)
+ eb[b].parent = eb[ def_bones[i-1] ] # to previous
+ eb[b].use_connect = True
+
+ # Constraint def to tweaks
+ for d,t in zip(def_bones, tweaks):
+ tidx = tweaks.index(t)
+
+ make_constraint( self, d, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : t
+ })
+
+ if tidx != len(tweaks) - 1:
+ make_constraint( self, d, {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : tweaks[ tidx + 1 ],
+ })
+
+ make_constraint( self, d, {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : tweaks[ tidx + 1 ],
+ })
+
+ # Create bbone segments
+ for bone in def_bones[:-1]:
+ self.obj.data.bones[bone].bbone_segments = self.bbones
+
+ self.obj.data.bones[ def_bones[0] ].bbone_in = 0.0
+ self.obj.data.bones[ def_bones[-2] ].bbone_out = 0.0
+ self.obj.data.bones[ def_bones[-1] ].bbone_in = 0.0
+ self.obj.data.bones[ def_bones[-1] ].bbone_out = 0.0
+
+
+ # Rubber hose drivers
+ pb = self.obj.pose.bones
+ for i,t in enumerate( tweaks[1:-1] ):
+ # Create custom property on tweak bone to control rubber hose
+ name = 'rubber_tweak'
+
+ if i == trunc( len( tweaks[1:-1] ) / 2 ):
+ pb[t][name] = 0.0
+ else:
+ pb[t][name] = 1.0
+
+ prop = rna_idprop_ui_prop_get( pb[t], name, create=True )
+
+ prop["min"] = 0.0
+ prop["max"] = 2.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = name
+
+ for j,d in enumerate(def_bones[:-1]):
+ drvs = {}
+ if j != 0:
+ tidx = j
+ drvs[tidx] = self.obj.data.bones[d].driver_add("bbone_in").driver
+
+ if j != len( def_bones[:-1] ) - 1:
+ tidx = j + 1
+ drvs[tidx] = self.obj.data.bones[d].driver_add("bbone_out").driver
+
+ for d in drvs:
+ drv = drvs[d]
+ name = 'rubber_tweak'
+ drv.type = 'AVERAGE'
+ var = drv.variables.new()
+ var.name = name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[tweaks[d]].path_from_id() + \
+ '[' + '"' + name + '"' + ']'
+
+ return def_bones
+
+
+ def create_ik( self, parent ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ ctrl = get_bone_name( org_bones[0], 'ctrl', 'ik' )
+ mch_ik = get_bone_name( org_bones[0], 'mch', 'ik' )
+ mch_target = get_bone_name( org_bones[0], 'mch', 'ik_target' )
+
+ for o, ik in zip( org_bones, [ ctrl, mch_ik, mch_target ] ):
+ bone = copy_bone( self.obj, o, ik )
+
+ if org_bones.index(o) == len( org_bones ) - 1:
+ eb[ bone ].length /= 4
+
+ # Create MCH Stretch
+ mch_str = copy_bone(
+ self.obj,
+ org_bones[0],
+ get_bone_name( org_bones[0], 'mch', 'ik_stretch' )
+ )
+
+ if self.limb_type != 'paw':
+ eb[ mch_str ].tail = eb[ org_bones[-1] ].head
+ else:
+ eb[ mch_str ].tail = eb[ org_bones[-2] ].head
+
+ # Parenting
+ eb[ ctrl ].parent = eb[ parent ]
+ eb[ mch_str ].parent = eb[ parent ]
+ eb[ mch_ik ].parent = eb[ ctrl ]
+
+
+ make_constraint( self, mch_ik, {
+ 'constraint' : 'IK',
+ 'subtarget' : mch_target,
+ 'chain_count' : 2,
+ })
+
+ pb = self.obj.pose.bones
+ pb[ mch_ik ].ik_stretch = 0.1
+ pb[ ctrl ].ik_stretch = 0.1
+
+ # IK constraint Rotation locks
+ for axis in ['x','y','z']:
+ if axis != self.rot_axis:
+ setattr( pb[ mch_ik ], 'lock_ik_' + axis, True )
+
+ # Locks and Widget
+ pb[ ctrl ].lock_rotation = True, False, True
+ create_ikarrow_widget( self.obj, ctrl, bone_transform_name=None )
+
+ return { 'ctrl' : { 'limb' : ctrl },
+ 'mch_ik' : mch_ik,
+ 'mch_target' : mch_target,
+ 'mch_str' : mch_str
+ }
+
+
+ def create_fk( self, parent ):
+ org_bones = self.org_bones.copy()
+
+ if self.limb_type == 'paw': # Paw base chain is one bone longer
+ org_bones.pop()
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ ctrls = []
+
+ for o in org_bones:
+ bone = copy_bone( self.obj, o, get_bone_name( o, 'ctrl', 'fk' ) )
+ ctrls.append( bone )
+
+ # MCH
+ mch = copy_bone(
+ self.obj, org_bones[-1], get_bone_name( o, 'mch', 'fk' )
+ )
+
+ eb[ mch ].length /= 4
+
+ # Parenting
+ eb[ ctrls[0] ].parent = eb[ parent ]
+ eb[ ctrls[1] ].parent = eb[ ctrls[0] ]
+ eb[ ctrls[1] ].use_connect = True
+ eb[ ctrls[2] ].parent = eb[ mch ]
+ eb[ mch ].parent = eb[ ctrls[1] ]
+ eb[ mch ].use_connect = True
+
+ # Constrain MCH's scale to root
+ make_constraint( self, mch, {
+ 'constraint' : 'COPY_SCALE',
+ 'subtarget' : 'root'
+ })
+
+ # Locks and widgets
+ pb = self.obj.pose.bones
+ pb[ ctrls[2] ].lock_location = True, True, True
+
+ create_limb_widget( self.obj, ctrls[0] )
+ create_limb_widget( self.obj, ctrls[1] )
+
+ create_circle_widget(self.obj, ctrls[2], radius=0.4, head_tail=0.0)
+
+ for c in ctrls:
+ if self.fk_layers:
+ pb[c].bone.layers = self.fk_layers
+
+ return { 'ctrl' : ctrls, 'mch' : mch }
+
+
+ def org_parenting_and_switch( self, org, ik, fk, parent ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+ # re-parent ORGs in a connected chain
+ for i,o in enumerate(org):
+ if i > 0:
+ eb[o].parent = eb[ org[i-1] ]
+ if i <= len(org)-1:
+ eb[o].use_connect = True
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+ pb_parent = pb[ parent ]
+
+ # Create ik/fk switch property
+ pb_parent['IK/FK'] = 0.0
+ prop = rna_idprop_ui_prop_get( pb_parent, 'IK/FK', create=True )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = 'IK/FK Switch'
+
+ # Constrain org to IK and FK bones
+ iks = [ ik['ctrl']['limb'] ]
+ iks += [ ik[k] for k in [ 'mch_ik', 'mch_target'] ]
+
+ for o, i, f in zip( org, iks, fk ):
+ make_constraint( self, o, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : i
+ })
+ make_constraint( self, o, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : f
+ })
+
+ # Add driver to relevant constraint
+ drv = pb[o].constraints[-1].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop.name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+
+ def create_terminal( self, limb_type, bones ):
+ if limb_type == 'arm':
+ return create_arm( self, bones )
+ elif limb_type == 'leg':
+ return create_leg( self, bones )
+ elif limb_type == 'paw':
+ return create_paw( self, bones )
+
+
+ def generate( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Clear parents for org bones
+ for bone in self.org_bones[1:]:
+ eb[bone].use_connect = False
+ eb[bone].parent = None
+
+ bones = {}
+
+ # Create mch limb parent
+ bones['parent'] = self.create_parent()
+ bones['tweak'] = self.create_tweak()
+ bones['def'] = self.create_def( bones['tweak']['ctrl'] )
+ bones['ik'] = self.create_ik( bones['parent'] )
+ bones['fk'] = self.create_fk( bones['parent'] )
+
+ self.org_parenting_and_switch(
+ self.org_bones, bones['ik'], bones['fk']['ctrl'], bones['parent']
+ )
+
+ bones = self.create_terminal( self.limb_type, bones )
+
+ return [ create_script( bones, self.limb_type ) ]
+
+def add_parameters( params ):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+
+ items = [
+ ('arm', 'Arm', ''),
+ ('leg', 'Leg', ''),
+ ('paw', 'Paw', '')
+ ]
+ params.limb_type = bpy.props.EnumProperty(
+ items = items,
+ name = "Limb Type",
+ default = 'arm'
+ )
+
+ items = [
+ ('x', 'X', ''),
+ ('y', 'Y', ''),
+ ('z', 'Z', '')
+ ]
+ params.rotation_axis = bpy.props.EnumProperty(
+ items = items,
+ name = "Rotation Axis",
+ default = 'x'
+ )
+
+ params.segments = bpy.props.IntProperty(
+ name = 'limb segments',
+ default = 2,
+ min = 1,
+ description = 'Number of segments'
+ )
+
+ params.bbones = bpy.props.IntProperty(
+ name = 'bbone segments',
+ default = 10,
+ min = 1,
+ description = 'Number of segments'
+ )
+
+ # Setting up extra layers for the FK and tweak
+ params.tweak_extra_layers = bpy.props.BoolProperty(
+ name = "tweak_extra_layers",
+ default = True,
+ description = ""
+ )
+
+ params.tweak_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+ # Setting up extra layers for the FK and tweak
+ params.fk_extra_layers = bpy.props.BoolProperty(
+ name = "fk_extra_layers",
+ default = True,
+ description = ""
+ )
+
+ params.fk_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the FK controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters."""
+
+ r = layout.row()
+ r.prop(params, "limb_type")
+
+ r = layout.row()
+ r.prop(params, "rotation_axis")
+
+ r = layout.row()
+ r.prop(params, "segments")
+
+ r = layout.row()
+ r.prop(params, "bbones")
+
+ for layer in [ 'fk', 'tweak' ]:
+ r = layout.row()
+ r.prop(params, layer + "_extra_layers")
+ r.active = params.tweak_extra_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range(8):
+ row.prop(params, layer + "_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range(16,24):
+ row.prop(params, layer + "_layers", index=i, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range(8,16):
+ row.prop(params, layer + "_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range(24,32):
+ row.prop(params, layer + "_layers", index=i, toggle=True, text="")
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('upper_arm.L')
+ bone.head[:] = -0.0016, 0.0060, -0.0012
+ bone.tail[:] = 0.2455, 0.0678, -0.1367
+ bone.roll = 2.0724
+ bone.use_connect = False
+ bones['upper_arm.L'] = bone.name
+ bone = arm.edit_bones.new('forearm.L')
+ bone.head[:] = 0.2455, 0.0678, -0.1367
+ bone.tail[:] = 0.4625, 0.0285, -0.2797
+ bone.roll = 2.1535
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['upper_arm.L']]
+ bones['forearm.L'] = bone.name
+ bone = arm.edit_bones.new('hand.L')
+ bone.head[:] = 0.4625, 0.0285, -0.2797
+ bone.tail[:] = 0.5265, 0.0205, -0.3273
+ bone.roll = 2.2103
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['forearm.L']]
+ bones['hand.L'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['upper_arm.L']]
+ pbone.rigify_type = 'pitchipoy.limbs.super_limb'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ try:
+ pbone.rigify_parameters.separate_ik_layers = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.ik_layers = [
+ False, False, False, 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
+ ]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.separate_hose_layers = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.hose_layers = [
+ False, False, False, False, 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
+ ]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [
+ False, False, False, False, 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
+ ]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.fk_layers = [
+ False, False, False, 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
+ ]
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['forearm.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['hand.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/limbs/ui.py b/rigify/legacy/rigs/pitchipoy/limbs/ui.py
new file mode 100644
index 00000000..37921dc0
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/limbs/ui.py
@@ -0,0 +1,143 @@
+script_arm = """
+controls = [%s]
+tweaks = [%s]
+ik_ctrl = [%s]
+fk_ctrl = '%s'
+parent = '%s'
+
+# IK/FK Switch on all Control Bones
+if is_selected( controls ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+ props = layout.operator("pose.rigify_arm_fk2ik_" + rig_id, text="Snap FK->IK (" + fk_ctrl + ")")
+ props.uarm_fk = controls[1]
+ props.farm_fk = controls[2]
+ props.hand_fk = controls[3]
+ props.uarm_ik = controls[0]
+ props.farm_ik = ik_ctrl[1]
+ props.hand_ik = controls[4]
+ props = layout.operator("pose.rigify_arm_ik2fk_" + rig_id, text="Snap IK->FK (" + fk_ctrl + ")")
+ props.uarm_fk = controls[1]
+ props.farm_fk = controls[2]
+ props.hand_fk = controls[3]
+ props.uarm_ik = controls[0]
+ props.farm_ik = ik_ctrl[1]
+ props.hand_ik = controls[4]
+ props.pole = ""
+
+
+# BBone rubber hose on each Respective Tweak
+for t in tweaks:
+ if is_selected( t ):
+ layout.prop( pose_bones[ t ], '["%s"]', slider = True )
+
+# IK Stretch on IK Control bone
+if is_selected( ik_ctrl ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+
+# FK limb follow
+if is_selected( fk_ctrl ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+"""
+
+script_leg = """
+controls = [%s]
+tweaks = [%s]
+ik_ctrl = [%s]
+fk_ctrl = '%s'
+parent = '%s'
+
+# IK/FK Switch on all Control Bones
+if is_selected( controls ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+ props = layout.operator("pose.rigify_leg_fk2ik_" + rig_id, text="Snap FK->IK (" + fk_ctrl + ")")
+ props.thigh_fk = controls[1]
+ props.shin_fk = controls[2]
+ props.foot_fk = controls[3]
+ props.mfoot_fk = controls[7]
+ props.thigh_ik = controls[0]
+ props.shin_ik = ik_ctrl[1]
+ props.foot_ik = ik_ctrl[2]
+ props.mfoot_ik = ik_ctrl[2]
+ props = layout.operator("pose.rigify_leg_ik2fk_" + rig_id, text="Snap IK->FK (" + fk_ctrl + ")")
+ props.thigh_fk = controls[1]
+ props.shin_fk = controls[2]
+ props.foot_fk = controls[3]
+ props.mfoot_fk = controls[7]
+ props.thigh_ik = controls[0]
+ props.shin_ik = ik_ctrl[1]
+ props.foot_ik = controls[6]
+ props.pole = ""
+ props.footroll = controls[5]
+ props.mfoot_ik = ik_ctrl[2]
+
+# BBone rubber hose on each Respective Tweak
+for t in tweaks:
+ if is_selected( t ):
+ layout.prop( pose_bones[ t ], '["%s"]', slider = True )
+
+# IK Stretch on IK Control bone
+if is_selected( ik_ctrl ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+
+# FK limb follow
+if is_selected( fk_ctrl ):
+ layout.prop( pose_bones[ parent ], '["%s"]', slider = True )
+"""
+
+def create_script( bones, limb_type=None):
+ # All ctrls have IK/FK switch
+ controls = [ bones['ik']['ctrl']['limb'] ] + bones['fk']['ctrl']
+ controls += bones['ik']['ctrl']['terminal']
+ controls += [ bones['fk']['mch'] ]
+
+ controls_string = ", ".join(["'" + x + "'" for x in controls])
+
+ # All tweaks have their own bbone prop
+ tweaks = bones['tweak']['ctrl'][1:-1]
+ tweaks_string = ", ".join(["'" + x + "'" for x in tweaks])
+
+ # IK ctrl has IK stretch
+ ik_ctrl = [ bones['ik']['ctrl']['terminal'][-1] ]
+ ik_ctrl += [ bones['ik']['mch_ik'] ]
+ ik_ctrl += [ bones['ik']['mch_target'] ]
+
+ ik_ctrl_string = ", ".join(["'" + x + "'" for x in ik_ctrl])
+
+ if limb_type == 'arm':
+ return script_arm % (
+ controls_string,
+ tweaks_string,
+ ik_ctrl_string,
+ bones['fk']['ctrl'][0],
+ bones['parent'],
+ 'IK/FK',
+ 'rubber_tweak',
+ 'IK_Strertch',
+ 'FK_limb_follow'
+ )
+
+ elif limb_type == 'leg':
+ return script_leg % (
+ controls_string,
+ tweaks_string,
+ ik_ctrl_string,
+ bones['fk']['ctrl'][0],
+ bones['parent'],
+ 'IK/FK',
+ 'rubber_tweak',
+ 'IK_Strertch',
+ 'FK_limb_follow'
+ )
+
+ elif limb_type == 'paw':
+ return script_leg % (
+ controls_string,
+ tweaks_string,
+ ik_ctrl_string,
+ bones['fk']['ctrl'][0],
+ bones['parent'],
+ 'IK/FK',
+ 'rubber_tweak',
+ 'IK_Strertch',
+ 'FK_limb_follow'
+ )
diff --git a/rigify/legacy/rigs/pitchipoy/simple_tentacle.py b/rigify/legacy/rigs/pitchipoy/simple_tentacle.py
new file mode 100644
index 00000000..4edb15e6
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/simple_tentacle.py
@@ -0,0 +1,350 @@
+import bpy
+from ...utils import copy_bone
+from ...utils import strip_org, make_deformer_name, connected_children_names
+from ...utils import make_mechanism_name, put_bone, create_sphere_widget
+from ...utils import create_widget, create_circle_widget
+from ...utils import MetarigError
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+
+ self.copy_rotaion_axes = params.copy_rotaion_axes
+
+ if params.tweak_extra_layers:
+ self.tweak_layers = list( params.tweak_layers )
+ else:
+ self.tweak_layers = None
+
+ if len(self.org_bones) <= 1:
+ raise MetarigError(
+ "RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
+ )
+
+
+ def make_controls( self ):
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ org_bones = self.org_bones
+
+ ctrl_chain = []
+ for i in range( len( org_bones ) ):
+ name = org_bones[i]
+
+ ctrl_bone = copy_bone(
+ self.obj,
+ name,
+ strip_org(name)
+ )
+
+ ctrl_chain.append( ctrl_bone )
+
+ # Make widgets
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ for ctrl in ctrl_chain:
+ create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
+
+ return ctrl_chain
+
+
+ def make_tweaks( self ):
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+ org_bones = self.org_bones
+
+ tweak_chain = []
+ for i in range( len( org_bones ) + 1 ):
+ if i == len( org_bones ):
+ # Make final tweak at the tip of the tentacle
+ name = org_bones[i-1]
+ else:
+ name = org_bones[i]
+
+ tweak_bone = copy_bone(
+ self.obj,
+ name,
+ "tweak_" + strip_org(name)
+ )
+
+ tweak_e = eb[ tweak_bone ]
+
+ tweak_e.length /= 2 # Set size to half
+
+ if i == len( org_bones ):
+ # Position final tweak at the tip
+ put_bone( self.obj, tweak_bone, eb[ org_bones[-1]].tail )
+
+ tweak_chain.append( tweak_bone )
+
+ # Make widgets
+ bpy.ops.object.mode_set(mode = 'OBJECT')
+
+ for tweak in tweak_chain:
+ create_sphere_widget( self.obj, tweak )
+
+ tweak_pb = self.obj.pose.bones[ tweak ]
+
+ # Set locks
+ if tweak_chain.index( tweak ) != len( tweak_chain ) - 1:
+ tweak_pb.lock_rotation = (True, False, True)
+ tweak_pb.lock_scale = (False, True, False)
+ else:
+ tweak_pb.lock_rotation_w = True
+ tweak_pb.lock_rotation = (True, True, True)
+ tweak_pb.lock_scale = (True, True, True)
+
+ # Set up tweak bone layers
+ if self.tweak_layers:
+ tweak_pb.bone.layers = self.tweak_layers
+
+ return tweak_chain
+
+
+ def make_deform( self ):
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ org_bones = self.org_bones
+
+ def_chain = []
+ for i in range( len( org_bones ) ):
+ name = org_bones[i]
+
+ def_bone = copy_bone(
+ self.obj,
+ name,
+ make_deformer_name(strip_org(name))
+ )
+
+ def_chain.append( def_bone )
+
+ return def_chain
+
+
+ def parent_bones( self, all_bones ):
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ org_bones = self.org_bones
+ eb = self.obj.data.edit_bones
+
+ # Parent control bones
+ for bone in all_bones['control'][1:]:
+ previous_index = all_bones['control'].index( bone ) - 1
+ eb[ bone ].parent = eb[ all_bones['control'][previous_index] ]
+
+ # Parent tweak bones
+ tweaks = all_bones['tweak']
+ for tweak in all_bones['tweak']:
+ parent = ''
+ if tweaks.index( tweak ) == len( tweaks ) - 1:
+ parent = all_bones['control'][ -1 ]
+ else:
+ parent = all_bones['control'][ tweaks.index( tweak ) ]
+
+ eb[ tweak ].parent = eb[ parent ]
+
+ # Parent deform bones
+ for bone in all_bones['deform'][1:]:
+ previous_index = all_bones['deform'].index( bone ) - 1
+
+ eb[ bone ].parent = eb[ all_bones['deform'][previous_index] ]
+ eb[ bone ].use_connect = True
+
+ # Parent org bones ( to tweaks by default, or to the controls )
+ for org, tweak in zip( org_bones, all_bones['tweak'] ):
+ eb[ org ].parent = eb[ tweak ]
+
+
+ def make_constraints( self, all_bones ):
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ org_bones = self.org_bones
+ pb = self.obj.pose.bones
+
+ # Deform bones' constraints
+ ctrls = all_bones['control']
+ tweaks = all_bones['tweak' ]
+ deforms = all_bones['deform' ]
+
+ for deform, tweak, ctrl in zip( deforms, tweaks, ctrls ):
+ con = pb[deform].constraints.new('COPY_TRANSFORMS')
+ con.target = self.obj
+ con.subtarget = tweak
+
+ con = pb[deform].constraints.new('DAMPED_TRACK')
+ con.target = self.obj
+ con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
+
+ con = pb[deform].constraints.new('STRETCH_TO')
+ con.target = self.obj
+ con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
+
+ # Control bones' constraints
+ if ctrl != ctrls[0]:
+ con = pb[ctrl].constraints.new('COPY_ROTATION')
+ con.target = self.obj
+ con.subtarget = ctrls[ ctrls.index(ctrl) - 1 ]
+ for i, prop in enumerate( [ 'use_x', 'use_y', 'use_z' ] ):
+ if self.copy_rotaion_axes[i]:
+ setattr( con, prop, True )
+ else:
+ setattr( con, prop, False )
+ con.use_offset = True
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+
+
+
+ def generate(self):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Clear all initial parenting
+ for bone in self.org_bones:
+ # eb[ bone ].parent = None
+ eb[ bone ].use_connect = False
+
+ # Creating all bones
+ ctrl_chain = self.make_controls()
+ tweak_chain = self.make_tweaks()
+ def_chain = self.make_deform()
+
+ all_bones = {
+ 'control' : ctrl_chain,
+ 'tweak' : tweak_chain,
+ 'deform' : def_chain
+ }
+
+ self.make_constraints( all_bones )
+ self.parent_bones( all_bones )
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.copy_rotaion_axes = bpy.props.BoolVectorProperty(
+ size = 3,
+ description = "Layers for the tweak controls to be on",
+ default = tuple( [ i == 0 for i in range(0, 3) ] )
+ )
+
+ # Setting up extra tweak layers
+ params.tweak_extra_layers = bpy.props.BoolProperty(
+ name = "tweak_extra_layers",
+ default = True,
+ description = ""
+ )
+
+ params.tweak_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+ """
+
+ r = layout.row()
+ col = r.column(align=True)
+ row = col.row(align=True)
+ for i,axis in enumerate( [ 'x', 'y', 'z' ] ):
+ row.prop(params, "copy_rotaion_axes", index=i, toggle=True, text=axis)
+
+ r = layout.row()
+ r.prop(params, "tweak_extra_layers")
+ r.active = params.tweak_extra_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range( 8 ): # Layers 0-7
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range( 16, 24 ): # Layers 16-23
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range( 8, 16 ): # Layers 8-15
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range( 24, 32 ): # Layers 24-31
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('Bone')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.0000, 0.3333
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['Bone'] = bone.name
+
+ bone = arm.edit_bones.new('Bone.002')
+ bone.head[:] = 0.0000, 0.0000, 0.3333
+ bone.tail[:] = 0.0000, 0.0000, 0.6667
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['Bone']]
+ bones['Bone.002'] = bone.name
+
+ bone = arm.edit_bones.new('Bone.001')
+ bone.head[:] = 0.0000, 0.0000, 0.6667
+ bone.tail[:] = 0.0000, 0.0000, 1.0000
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['Bone.002']]
+ bones['Bone.001'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['Bone']]
+ pbone.rigify_type = 'pitchipoy.simple_tentacle'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['Bone.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['Bone.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/super_copy.py b/rigify/legacy/rigs/pitchipoy/super_copy.py
new file mode 100644
index 00000000..d05d68c4
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_copy.py
@@ -0,0 +1,159 @@
+#====================== 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 ...utils import copy_bone
+from ...utils import strip_org, make_deformer_name
+from ...utils import create_bone_widget, create_circle_widget
+
+
+class Rig:
+ """ 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):
+ """ 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.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Make a control bone (copy of original).
+ if self.make_control:
+ bone = copy_bone(self.obj, self.org_bone, self.org_name)
+
+ # 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))
+
+ # 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
+ if self.make_deform:
+ def_bone_e.use_connect = False
+ def_bone_e.parent = eb[self.org_bone]
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.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
+
+ # Create control widget
+ if self.make_widget:
+ create_circle_widget(self.obj, bone, radius = 0.5 )
+ else:
+ create_bone_widget(self.obj, bone, radius = 0.5 )
+
+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 = layout.row()
+ r.prop(params, "make_deform")
+
+
+def create_sample(obj):
+ """ Create a sample metarig for this rig type.
+ """
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('Bone')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.0000, 0.2000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['Bone'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['Bone']]
+ pbone.rigify_type = 'basic.copy'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/super_face.py b/rigify/legacy/rigs/pitchipoy/super_face.py
new file mode 100644
index 00000000..9928864f
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_face.py
@@ -0,0 +1,2400 @@
+import bpy, re
+from mathutils import Vector
+from ...utils import copy_bone, flip_bone
+from ...utils import org, strip_org, make_deformer_name, connected_children_names, make_mechanism_name
+from ...utils import create_circle_widget, create_sphere_widget, create_widget, create_cube_widget
+from ...utils import MetarigError
+from rna_prop_ui import rna_idprop_ui_prop_get
+from .super_widgets import create_face_widget, create_eye_widget, create_eyes_widget, create_ear_widget, create_jaw_widget, create_teeth_widget
+
+
+script = """
+all_controls = [%s]
+jaw_ctrl_name = '%s'
+eyes_ctrl_name = '%s'
+
+if is_selected(all_controls):
+ layout.prop(pose_bones[jaw_ctrl_name], '["%s"]', slider=True)
+ layout.prop(pose_bones[eyes_ctrl_name], '["%s"]', slider=True)
+"""
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ self.obj = obj
+
+ b = self.obj.data.bones
+
+ children = [
+ "nose", "lip.T.L", "lip.B.L", "jaw", "ear.L", "ear.R", "lip.T.R",
+ "lip.B.R", "brow.B.L", "lid.T.L", "brow.B.R", "lid.T.R",
+ "forehead.L", "forehead.R", "forehead.L.001", "forehead.R.001",
+ "forehead.L.002", "forehead.R.002", "eye.L", "eye.R", "cheek.T.L",
+ "cheek.T.R", "teeth.T", "teeth.B", "tongue", "temple.L",
+ "temple.R"
+ ]
+
+ #create_pose_lib( self.obj )
+
+ children = [ org(b) for b in children ]
+ grand_children = []
+
+ for child in children:
+ 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.params = params
+
+ if params.primary_layers_extra:
+ self.primary_layers = list(params.primary_layers)
+ else:
+ self.primary_layers = None
+
+ if params.secondary_layers_extra:
+ self.secondary_layers = list(params.secondary_layers)
+ else:
+ self.secondary_layers = None
+
+ def symmetrical_split( self, bones ):
+
+ # RE pattern match right or left parts
+ # match the letter "L" (or "R"), followed by an optional dot (".")
+ # and 0 or more digits at the end of the the string
+ left_pattern = 'L\.?\d*$'
+ right_pattern = 'R\.?\d*$'
+
+ left = sorted( [ name for name in bones if re.search( left_pattern, name ) ] )
+ right = sorted( [ name for name in bones if re.search( right_pattern, name ) ] )
+
+ return left, right
+
+ def create_deformation( self ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ def_bones = []
+ for org in org_bones:
+ if 'face' in org or 'teeth' in org or 'eye' in org:
+ continue
+
+ def_name = make_deformer_name( strip_org( org ) )
+ def_name = copy_bone( self.obj, org, def_name )
+ def_bones.append( def_name )
+
+ eb[def_name].use_connect = False
+ eb[def_name].parent = None
+
+ brow_top_names = [ bone for bone in def_bones if 'brow.T' in bone ]
+ forehead_names = [ bone for bone in def_bones if 'forehead' in bone ]
+
+ brow_left, brow_right = self.symmetrical_split( brow_top_names )
+ forehead_left, forehead_right = self.symmetrical_split( forehead_names )
+
+ brow_left = brow_left[1:]
+ brow_right = brow_right[1:]
+ brow_left.reverse()
+ brow_right.reverse()
+
+ for browL, browR, foreheadL, foreheadR in zip(
+ brow_left, brow_right, forehead_left, forehead_right ):
+
+ eb[foreheadL].tail = eb[browL].head
+ eb[foreheadR].tail = eb[browR].head
+
+ return { 'all' : def_bones }
+
+
+ def create_ctrl( self, bones ):
+ org_bones = self.org_bones
+
+ ## create control bones
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # eyes ctrls
+ eyeL_e = eb[ bones['eyes'][0] ]
+ eyeR_e = eb[ bones['eyes'][1] ]
+
+ distance = ( eyeL_e.head - eyeR_e.head ) * 3
+ distance = distance.cross( (0, 0, 1) )
+ eye_length = eyeL_e.length
+
+ eyeL_ctrl_name = strip_org( bones['eyes'][0] )
+ eyeR_ctrl_name = strip_org( bones['eyes'][1] )
+
+ eyeL_ctrl_name = copy_bone( self.obj, bones['eyes'][0], eyeL_ctrl_name )
+ eyeR_ctrl_name = copy_bone( self.obj, bones['eyes'][1], eyeR_ctrl_name )
+ eyes_ctrl_name = copy_bone( self.obj, bones['eyes'][0], 'eyes' )
+
+ eyeL_ctrl_e = eb[ eyeL_ctrl_name ]
+ eyeR_ctrl_e = eb[ eyeR_ctrl_name ]
+ eyes_ctrl_e = eb[ 'eyes' ]
+
+ eyeL_ctrl_e.head += distance
+ eyeR_ctrl_e.head += distance
+ eyes_ctrl_e.head[:] = ( eyeL_ctrl_e.head + eyeR_ctrl_e.head ) / 2
+
+ for bone in [ eyeL_ctrl_e, eyeR_ctrl_e, eyes_ctrl_e ]:
+ bone.tail[:] = bone.head + Vector( [ 0, 0, eye_length * 0.75 ] )
+
+ ## Widget for transforming the both eyes
+ eye_master_names = []
+ for bone in bones['eyes']:
+ eye_master = copy_bone(
+ self.obj,
+ bone,
+ 'master_' + strip_org(bone)
+ )
+
+ eye_master_names.append( eye_master )
+
+ ## turbo: adding a master nose for transforming the whole nose
+ master_nose = copy_bone(self.obj, 'ORG-nose.004', 'nose_master')
+ eb[master_nose].tail[:] = \
+ eb[master_nose].head + Vector([0, self.face_length / -4, 0])
+
+ # ears ctrls
+ earL_name = strip_org( bones['ears'][0] )
+ earR_name = strip_org( bones['ears'][1] )
+
+ earL_ctrl_name = copy_bone( self.obj, org( bones['ears'][0] ), earL_name )
+ earR_ctrl_name = copy_bone( self.obj, org( bones['ears'][1] ), earR_name )
+
+ # jaw ctrl
+ jaw_ctrl_name = strip_org( bones['jaw'][2] ) + '_master'
+ jaw_ctrl_name = copy_bone( self.obj, bones['jaw'][2], jaw_ctrl_name )
+
+ jawL_org_e = eb[ bones['jaw'][0] ]
+ jawR_org_e = eb[ bones['jaw'][1] ]
+ jaw_org_e = eb[ bones['jaw'][2] ]
+
+ eb[ jaw_ctrl_name ].head[:] = ( jawL_org_e.head + jawR_org_e.head ) / 2
+
+ # teeth ctrls
+ teethT_name = strip_org( bones['teeth'][0] )
+ teethB_name = strip_org( bones['teeth'][1] )
+
+ teethT_ctrl_name = copy_bone( self.obj, org( bones['teeth'][0] ), teethT_name )
+ teethB_ctrl_name = copy_bone( self.obj, org( bones['teeth'][1] ), teethB_name )
+
+ # tongue ctrl
+ tongue_org = bones['tongue'].pop()
+ tongue_name = strip_org( tongue_org ) + '_master'
+
+ tongue_ctrl_name = copy_bone( self.obj, tongue_org, tongue_name )
+
+ flip_bone( self.obj, tongue_ctrl_name )
+
+ ## Assign widgets
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ # Assign each eye widgets
+ create_eye_widget( self.obj, eyeL_ctrl_name )
+ create_eye_widget( self.obj, eyeR_ctrl_name )
+
+ # Assign eyes widgets
+ create_eyes_widget( self.obj, eyes_ctrl_name )
+
+ # Assign each eye_master widgets
+ for master in eye_master_names:
+ create_square_widget(self.obj, master)
+
+ # Assign nose_master widget
+ create_square_widget( self.obj, master_nose, size = 1 )
+
+ # Assign ears widget
+ create_ear_widget( self.obj, earL_ctrl_name )
+ create_ear_widget( self.obj, earR_ctrl_name )
+
+ # Assign jaw widget
+ create_jaw_widget( self.obj, jaw_ctrl_name )
+
+ # Assign teeth widget
+ create_teeth_widget( self.obj, teethT_ctrl_name )
+ create_teeth_widget( self.obj, teethB_ctrl_name )
+
+ # Assign tongue widget ( using the jaw widget )
+ create_jaw_widget( self.obj, tongue_ctrl_name )
+
+ return {
+ 'eyes' : [
+ eyeL_ctrl_name,
+ eyeR_ctrl_name,
+ eyes_ctrl_name,
+ ] + eye_master_names,
+ 'ears' : [ earL_ctrl_name, earR_ctrl_name ],
+ 'jaw' : [ jaw_ctrl_name ],
+ 'teeth' : [ teethT_ctrl_name, teethB_ctrl_name ],
+ 'tongue' : [ tongue_ctrl_name ],
+ 'nose' : [ master_nose ]
+ }
+
+
+ def create_tweak( self, bones, uniques, tails ):
+ org_bones = self.org_bones
+
+ ## create tweak bones
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ tweaks = []
+
+ for bone in bones + list( uniques.keys() ):
+
+ tweak_name = strip_org( bone )
+
+ # pick name for unique bone from the uniques dictionary
+ if bone in list( uniques.keys() ):
+ tweak_name = uniques[bone]
+
+ tweak_name = copy_bone( self.obj, bone, tweak_name )
+ eb[ tweak_name ].use_connect = False
+ eb[ tweak_name ].parent = None
+
+ tweaks.append( tweak_name )
+
+ eb[ tweak_name ].tail[:] = \
+ eb[ tweak_name ].head + Vector(( 0, 0, self.face_length / 7 ))
+
+ # create tail bone
+ if bone in tails:
+ if 'lip.T.L.001' in bone:
+ tweak_name = copy_bone( self.obj, bone, 'lips.L' )
+ elif 'lip.T.R.001' in bone:
+ tweak_name = copy_bone( self.obj, bone, 'lips.R' )
+ else:
+ tweak_name = copy_bone( self.obj, bone, tweak_name )
+
+ eb[ tweak_name ].use_connect = False
+ eb[ tweak_name ].parent = None
+
+ eb[ tweak_name ].head = eb[ bone ].tail
+ eb[ tweak_name ].tail[:] = \
+ eb[ tweak_name ].head + Vector(( 0, 0, self.face_length / 7 ))
+
+ tweaks.append( tweak_name )
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ primary_tweaks = [
+ "lid.B.L.002", "lid.T.L.002", "lid.B.R.002", "lid.T.R.002",
+ "chin", "brow.T.L.001", "brow.T.L.002", "brow.T.L.003",
+ "brow.T.R.001", "brow.T.R.002", "brow.T.R.003", "lip.B",
+ "lip.B.L.001", "lip.B.R.001", "cheek.B.L.001", "cheek.B.R.001",
+ "lips.L", "lips.R", "lip.T.L.001", "lip.T.R.001", "lip.T",
+ "nose.002", "nose.L.001", "nose.R.001"
+ ]
+
+ for bone in tweaks:
+ if bone in primary_tweaks:
+ if self.primary_layers:
+ pb[bone].bone.layers = self.primary_layers
+ create_face_widget( self.obj, bone, size = 1.5 )
+ else:
+ if self.secondary_layers:
+ pb[bone].bone.layers = self.secondary_layers
+ create_face_widget( self.obj, bone )
+
+ return { 'all' : tweaks }
+
+
+ def all_controls( self ):
+ org_bones = self.org_bones
+
+ org_tongue_bones = sorted([ bone for bone in org_bones if 'tongue' in bone ])
+
+ org_to_ctrls = {
+ 'eyes' : [ 'eye.L', 'eye.R' ],
+ 'ears' : [ 'ear.L', 'ear.R' ],
+ 'jaw' : [ 'jaw.L', 'jaw.R', 'jaw' ],
+ 'teeth' : [ 'teeth.T', 'teeth.B' ],
+ 'tongue' : [ org_tongue_bones[0] ]
+ }
+
+ tweak_unique = { 'lip.T.L' : 'lip.T',
+ 'lip.B.L' : 'lip.B' }
+
+ org_to_ctrls = { key : [ org( bone ) for bone in org_to_ctrls[key] ] for key in org_to_ctrls.keys() }
+ tweak_unique = { org( key ) : tweak_unique[key] for key in tweak_unique.keys() }
+
+ tweak_exceptions = [] # bones not used to create tweaks
+ tweak_exceptions += [ bone for bone in org_bones if 'forehead' in bone or 'temple' in bone ]
+
+ tweak_tail = [ 'brow.B.L.003', 'brow.B.R.003', 'nose.004', 'chin.001' ]
+ tweak_tail += [ 'lip.T.L.001', 'lip.T.R.001', 'tongue.002' ]
+
+ tweak_exceptions += [ 'lip.T.R', 'lip.B.R', 'ear.L.001', 'ear.R.001' ] + list(tweak_unique.keys())
+ tweak_exceptions += [ 'face', 'cheek.T.L', 'cheek.T.R', 'cheek.B.L', 'cheek.B.R' ]
+ tweak_exceptions += [ 'ear.L', 'ear.R', 'eye.L', 'eye.R' ]
+
+ tweak_exceptions += org_to_ctrls.keys()
+ tweak_exceptions += org_to_ctrls['teeth']
+
+ tweak_exceptions.pop( tweak_exceptions.index('tongue') )
+ tweak_exceptions.pop( tweak_exceptions.index('jaw') )
+
+ tweak_exceptions = [ org( bone ) for bone in tweak_exceptions ]
+ tweak_tail = [ org( bone ) for bone in tweak_tail ]
+
+ org_to_tweak = sorted( [ bone for bone in org_bones if bone not in tweak_exceptions ] )
+
+ ctrls = self.create_ctrl( org_to_ctrls )
+ tweaks = self.create_tweak( org_to_tweak, tweak_unique, tweak_tail )
+
+ return { 'ctrls' : ctrls, 'tweaks' : tweaks }, tweak_unique
+
+ def create_mch( self, jaw_ctrl, tongue_ctrl ):
+ org_bones = self.org_bones
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create eyes mch bones
+ eyes = [ bone for bone in org_bones if 'eye' in bone ]
+
+ mch_bones = { strip_org( eye ) : [] for eye in eyes }
+
+ for eye in eyes:
+ mch_name = make_mechanism_name( strip_org( eye ) )
+ mch_name = copy_bone( self.obj, eye, mch_name )
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ mch_bones[ strip_org( eye ) ].append( mch_name )
+
+ mch_name = copy_bone( self.obj, eye, mch_name )
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ mch_bones[ strip_org( eye ) ].append( mch_name )
+
+ eb[ mch_name ].head[:] = eb[ mch_name ].tail
+ eb[ mch_name ].tail[:] = eb[ mch_name ].head + Vector( ( 0, 0, 0.005 ) )
+
+ # Create the eyes' parent mch
+ face = [ bone for bone in org_bones if 'face' in bone ].pop()
+
+ mch_name = 'eyes_parent'
+ mch_name = make_mechanism_name( mch_name )
+ mch_name = copy_bone( self.obj, face, mch_name )
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ eb[ mch_name ].length /= 4
+
+ mch_bones['eyes_parent'] = [ mch_name ]
+
+ # Create the lids' mch bones
+ all_lids = [ bone for bone in org_bones if 'lid' in bone ]
+ lids_L, lids_R = self.symmetrical_split( all_lids )
+
+ all_lids = [ lids_L, lids_R ]
+
+ mch_bones['lids'] = []
+
+ for i in range( 2 ):
+ for bone in all_lids[i]:
+ mch_name = make_mechanism_name( strip_org( bone ) )
+ mch_name = copy_bone( self.obj, eyes[i], mch_name )
+
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ eb[ mch_name ].tail[:] = eb[ bone ].head
+
+ mch_bones['lids'].append( mch_name )
+
+ mch_bones['jaw'] = []
+
+ length_subtractor = eb[ jaw_ctrl ].length / 6
+ # Create the jaw mch bones
+ for i in range( 6 ):
+ if i == 0:
+ mch_name = make_mechanism_name( 'mouth_lock' )
+ else:
+ mch_name = make_mechanism_name( jaw_ctrl )
+
+ mch_name = copy_bone( self.obj, jaw_ctrl, mch_name )
+
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ eb[ mch_name ].length = eb[ jaw_ctrl ].length - length_subtractor * i
+
+ mch_bones['jaw'].append( mch_name )
+
+ # Tongue mch bones
+
+ mch_bones['tongue'] = []
+
+ # create mch bones for all tongue org_bones except the first one
+ for bone in sorted([ org for org in org_bones if 'tongue' in org ])[1:]:
+ mch_name = make_mechanism_name( strip_org( bone ) )
+ mch_name = copy_bone( self.obj, tongue_ctrl, mch_name )
+
+ eb[ mch_name ].use_connect = False
+ eb[ mch_name ].parent = None
+
+ mch_bones['tongue'].append( mch_name )
+
+ return mch_bones
+
+ def parent_bones( self, all_bones, tweak_unique ):
+ org_bones = self.org_bones
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ face_name = [ bone for bone in org_bones if 'face' in bone ].pop()
+
+ # Initially parenting all bones to the face org bone.
+ for category in list( all_bones.keys() ):
+ for area in list( all_bones[category] ):
+ for bone in all_bones[category][area]:
+ eb[ bone ].parent = eb[ face_name ]
+
+ ## Parenting all deformation bones and org bones
+
+ # Parent all the deformation bones that have respective tweaks
+ def_tweaks = [ bone for bone in all_bones['deform']['all'] if bone[4:] in all_bones['tweaks']['all'] ]
+
+ # Parent all org bones to the ORG-face
+ for bone in [ bone for bone in org_bones if 'face' not in bone ]:
+ eb[ bone ].parent = eb[ org('face') ]
+
+ for bone in def_tweaks:
+ # the def and the matching org bone are parented to their corresponding tweak,
+ # whose name is the same as that of the def bone, without the "DEF-" (first 4 chars)
+ eb[ bone ].parent = eb[ bone[4:] ]
+ eb[ org( bone[4:] ) ].parent = eb[ bone[4:] ]
+
+ # Parent ORG eyes to corresponding mch bones
+ for bone in [ bone for bone in org_bones if 'eye' in bone ]:
+ eb[ bone ].parent = eb[ make_mechanism_name( strip_org( bone ) ) ]
+
+ for lip_tweak in list( tweak_unique.values() ):
+ # find the def bones that match unique lip_tweaks by slicing [4:-2]
+ # example: 'lip.B' matches 'DEF-lip.B.R' and 'DEF-lip.B.L' if
+ # you cut off the "DEF-" [4:] and the ".L" or ".R" [:-2]
+ lip_defs = [ bone for bone in all_bones['deform']['all'] if bone[4:-2] == lip_tweak ]
+
+ for bone in lip_defs:
+ eb[bone].parent = eb[ lip_tweak ]
+
+ # parent cheek bones top respetive tweaks
+ lips = [ 'lips.L', 'lips.R' ]
+ brows = [ 'brow.T.L', 'brow.T.R' ]
+ cheekB_defs = [ 'DEF-cheek.B.L', 'DEF-cheek.B.R' ]
+ cheekT_defs = [ 'DEF-cheek.T.L', 'DEF-cheek.T.R' ]
+
+ for lip, brow, cheekB, cheekT in zip( lips, brows, cheekB_defs, cheekT_defs ):
+ eb[ cheekB ].parent = eb[ lip ]
+ eb[ cheekT ].parent = eb[ brow ]
+
+ # parent ear deform bones to their controls
+ ear_defs = [ 'DEF-ear.L', 'DEF-ear.L.001', 'DEF-ear.R', 'DEF-ear.R.001' ]
+ ear_ctrls = [ 'ear.L', 'ear.R' ]
+
+ eb[ 'DEF-jaw' ].parent = eb[ 'jaw' ] # Parent jaw def bone to jaw tweak
+
+ for ear_ctrl in ear_ctrls:
+ for ear_def in ear_defs:
+ if ear_ctrl in ear_def:
+ eb[ ear_def ].parent = eb[ ear_ctrl ]
+
+ # Parent eyelid deform bones (each lid def bone is parented to its respective MCH bone)
+ def_lids = [ bone for bone in all_bones['deform']['all'] if 'lid' in bone ]
+
+ for bone in def_lids:
+ mch = make_mechanism_name( bone[4:] )
+ eb[ bone ].parent = eb[ mch ]
+
+ ## Parenting all mch bones
+
+ eb[ 'MCH-eyes_parent' ].parent = None # eyes_parent will be parented to root
+
+ # parent all mch tongue bones to the jaw master control bone
+ for bone in all_bones['mch']['tongue']:
+ eb[ bone ].parent = eb[ all_bones['ctrls']['jaw'][0] ]
+
+ ## Parenting the control bones
+
+ # parent teeth.B and tongue master controls to the jaw master control bone
+ for bone in [ 'teeth.B', 'tongue_master' ]:
+ eb[ bone ].parent = eb[ all_bones['ctrls']['jaw'][0] ]
+
+ # eyes
+ eb[ 'eyes' ].parent = eb[ 'MCH-eyes_parent' ]
+
+ eyes = [
+ bone for bone in all_bones['ctrls']['eyes'] if 'eyes' not in bone
+ ][0:2]
+
+ for eye in eyes:
+ eb[ eye ].parent = eb[ 'eyes' ]
+
+ ## turbo: parent eye master bones to face
+ for eye_master in eyes[2:]:
+ eb[ eye_master ].parent = eb[ 'ORG-face' ]
+
+ # Parent brow.b, eyes mch and lid tweaks and mch bones to masters
+ tweaks = [
+ b for b in all_bones['tweaks']['all'] if 'lid' in b or 'brow.B' in b
+ ]
+ mch = all_bones['mch']['lids'] + \
+ all_bones['mch']['eye.R'] + \
+ all_bones['mch']['eye.L']
+
+ everyone = tweaks + mch
+
+ left, right = self.symmetrical_split( everyone )
+
+ for l in left:
+ eb[ l ].parent = eb[ 'master_eye.L' ]
+
+ for r in right:
+ eb[ r ].parent = eb[ 'master_eye.R' ]
+
+ ## turbo: nose to mch jaw.004
+ eb[ all_bones['ctrls']['nose'].pop() ].parent = eb['MCH-jaw_master.004']
+
+ ## Parenting the tweak bones
+
+ # Jaw children (values) groups and their parents (keys)
+ groups = {
+ 'jaw_master' : [
+ 'jaw',
+ 'jaw.R.001',
+ 'jaw.L.001',
+ 'chin.L',
+ 'chin.R',
+ 'chin',
+ 'tongue.003'
+ ],
+ 'MCH-jaw_master' : [
+ 'lip.B'
+ ],
+ 'MCH-jaw_master.001' : [
+ 'lip.B.L.001',
+ 'lip.B.R.001'
+ ],
+ 'MCH-jaw_master.002' : [
+ 'lips.L',
+ 'lips.R',
+ 'cheek.B.L.001',
+ 'cheek.B.R.001'
+ ],
+ 'MCH-jaw_master.003' : [
+ 'lip.T',
+ 'lip.T.L.001',
+ 'lip.T.R.001'
+ ],
+ 'MCH-jaw_master.004' : [
+ 'cheek.T.L.001',
+ 'cheek.T.R.001'
+ ],
+ 'nose_master' : [
+ 'nose.002',
+ 'nose.004',
+ 'nose.L.001',
+ 'nose.R.001'
+ ]
+ }
+
+ for parent in list( groups.keys() ):
+ for bone in groups[parent]:
+ eb[ bone ].parent = eb[ parent ]
+
+ # Remaining arbitrary relatioships for tweak bone parenting
+ eb[ 'chin.001' ].parent = eb[ 'chin' ]
+ eb[ 'chin.002' ].parent = eb[ 'lip.B' ]
+ eb[ 'nose.001' ].parent = eb[ 'nose.002' ]
+ eb[ 'nose.003' ].parent = eb[ 'nose.002' ]
+ eb[ 'nose.005' ].parent = eb[ 'lip.T' ]
+ eb[ 'tongue' ].parent = eb[ 'tongue_master' ]
+ eb[ 'tongue.001' ].parent = eb[ 'MCH-tongue.001' ]
+ eb[ 'tongue.002' ].parent = eb[ 'MCH-tongue.002' ]
+
+ for bone in [ 'ear.L.002', 'ear.L.003', 'ear.L.004' ]:
+ eb[ bone ].parent = eb[ 'ear.L' ]
+ eb[ bone.replace( '.L', '.R' ) ].parent = eb[ 'ear.R' ]
+
+
+ def make_constraits( self, constraint_type, bone, subtarget, influence = 1 ):
+ org_bones = self.org_bones
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ owner_pb = pb[bone]
+
+ if constraint_type == 'def_tweak':
+
+ const = owner_pb.constraints.new( 'DAMPED_TRACK' )
+ const.target = self.obj
+ const.subtarget = subtarget
+
+ const = owner_pb.constraints.new( 'STRETCH_TO' )
+ const.target = self.obj
+ const.subtarget = subtarget
+
+ elif constraint_type == 'def_lids':
+
+ const = owner_pb.constraints.new( 'DAMPED_TRACK' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.head_tail = 1.0
+
+ const = owner_pb.constraints.new( 'STRETCH_TO' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.head_tail = 1.0
+
+ elif constraint_type == 'mch_eyes':
+
+ const = owner_pb.constraints.new( 'DAMPED_TRACK' )
+ const.target = self.obj
+ const.subtarget = subtarget
+
+ elif constraint_type == 'mch_eyes_lids_follow':
+
+ const = owner_pb.constraints.new( 'COPY_LOCATION' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.head_tail = 1.0
+
+ elif constraint_type == 'mch_eyes_parent':
+
+ const = owner_pb.constraints.new( 'COPY_TRANSFORMS' )
+ const.target = self.obj
+ const.subtarget = subtarget
+
+ elif constraint_type == 'mch_jaw_master':
+
+ const = owner_pb.constraints.new( 'COPY_TRANSFORMS' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.influence = influence
+
+ elif constraint_type == 'teeth':
+
+ const = owner_pb.constraints.new( 'COPY_TRANSFORMS' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.influence = influence
+
+ elif constraint_type == 'tweak_copyloc':
+
+ const = owner_pb.constraints.new( 'COPY_LOCATION' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.influence = influence
+ const.use_offset = True
+ const.target_space = 'LOCAL'
+ const.owner_space = 'LOCAL'
+
+ elif constraint_type == 'tweak_copy_rot_scl':
+
+ const = owner_pb.constraints.new( 'COPY_ROTATION' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.use_offset = True
+ const.target_space = 'LOCAL'
+ const.owner_space = 'LOCAL'
+
+ const = owner_pb.constraints.new( 'COPY_SCALE' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.use_offset = True
+ const.target_space = 'LOCAL'
+ const.owner_space = 'LOCAL'
+
+ elif constraint_type == 'tweak_copyloc_inv':
+
+ const = owner_pb.constraints.new( 'COPY_LOCATION' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.influence = influence
+ const.target_space = 'LOCAL'
+ const.owner_space = 'LOCAL'
+ const.use_offset = True
+ const.invert_x = True
+ const.invert_y = True
+ const.invert_z = True
+
+ elif constraint_type == 'mch_tongue_copy_trans':
+
+ const = owner_pb.constraints.new( 'COPY_TRANSFORMS' )
+ const.target = self.obj
+ const.subtarget = subtarget
+ const.influence = influence
+
+
+ def constraints( self, all_bones ):
+ ## Def bone constraints
+
+ def_specials = {
+ # 'bone' : 'target'
+ 'DEF-jaw' : 'chin',
+ 'DEF-chin.L' : 'lips.L',
+ 'DEF-jaw.L.001' : 'chin.L',
+ 'DEF-chin.R' : 'lips.R',
+ 'DEF-jaw.R.001' : 'chin.R',
+ 'DEF-brow.T.L.003' : 'nose',
+ 'DEF-ear.L.003' : 'ear.L.004',
+ 'DEF-ear.L.004' : 'ear.L',
+ 'DEF-ear.R.003' : 'ear.R.004',
+ 'DEF-ear.R.004' : 'ear.R',
+ 'DEF-lip.B.L.001' : 'lips.L',
+ 'DEF-lip.B.R.001' : 'lips.R',
+ 'DEF-cheek.B.L.001' : 'brow.T.L',
+ 'DEF-cheek.B.R.001' : 'brow.T.R',
+ 'DEF-lip.T.L.001' : 'lips.L',
+ 'DEF-lip.T.R.001' : 'lips.R',
+ 'DEF-cheek.T.L.001' : 'nose.L',
+ 'DEF-nose.L.001' : 'nose.002',
+ 'DEF-cheek.T.R.001' : 'nose.R',
+ 'DEF-nose.R.001' : 'nose.002',
+ 'DEF-forehead.L' : 'brow.T.L.003',
+ 'DEF-forehead.L.001' : 'brow.T.L.002',
+ 'DEF-forehead.L.002' : 'brow.T.L.001',
+ 'DEF-temple.L' : 'jaw.L',
+ 'DEF-brow.T.R.003' : 'nose',
+ 'DEF-forehead.R' : 'brow.T.R.003',
+ 'DEF-forehead.R.001' : 'brow.T.R.002',
+ 'DEF-forehead.R.002' : 'brow.T.R.001',
+ 'DEF-temple.R' : 'jaw.R'
+ }
+
+ pattern = r'^DEF-(\w+\.?\w?\.?\w?)(\.?)(\d*?)(\d?)$'
+
+ for bone in [ bone for bone in all_bones['deform']['all'] if 'lid' not in bone ]:
+ if bone in list( def_specials.keys() ):
+ self.make_constraits('def_tweak', bone, def_specials[bone] )
+ else:
+ matches = re.match( pattern, bone ).groups()
+ if len( matches ) > 1 and matches[-1]:
+ num = int( matches[-1] ) + 1
+ str_list = list( matches )[:-1] + [ str( num ) ]
+ tweak = "".join( str_list )
+ else:
+ tweak = "".join( matches ) + ".001"
+ self.make_constraits('def_tweak', bone, tweak )
+
+ def_lids = sorted( [ bone for bone in all_bones['deform']['all'] if 'lid' in bone ] )
+ mch_lids = sorted( [ bone for bone in all_bones['mch']['lids'] ] )
+
+ def_lidsL, def_lidsR = self.symmetrical_split( def_lids )
+ mch_lidsL, mch_lidsR = self.symmetrical_split( mch_lids )
+
+ # Take the last mch_lid bone and place it at the end
+ mch_lidsL = mch_lidsL[1:] + [ mch_lidsL[0] ]
+ mch_lidsR = mch_lidsR[1:] + [ mch_lidsR[0] ]
+
+ for boneL, boneR, mchL, mchR in zip( def_lidsL, def_lidsR, mch_lidsL, mch_lidsR ):
+ self.make_constraits('def_lids', boneL, mchL )
+ self.make_constraits('def_lids', boneR, mchR )
+
+ ## MCH constraints
+
+ # mch lids constraints
+ for bone in all_bones['mch']['lids']:
+ tweak = bone[4:] # remove "MCH-" from bone name
+ self.make_constraits('mch_eyes', bone, tweak )
+
+ # mch eyes constraints
+ for bone in [ 'MCH-eye.L', 'MCH-eye.R' ]:
+ ctrl = bone[4:] # remove "MCH-" from bone name
+ self.make_constraits('mch_eyes', bone, ctrl )
+
+ for bone in [ 'MCH-eye.L.001', 'MCH-eye.R.001' ]:
+ target = bone[:-4] # remove number from the end of the name
+ self.make_constraits('mch_eyes_lids_follow', bone, target )
+
+ # mch eyes parent constraints
+ self.make_constraits('mch_eyes_parent', 'MCH-eyes_parent', 'ORG-face' )
+
+ ## Jaw constraints
+
+ # jaw master mch bones
+ self.make_constraits( 'mch_jaw_master', 'MCH-mouth_lock', 'jaw_master', 0.20 )
+ self.make_constraits( 'mch_jaw_master', 'MCH-jaw_master', 'jaw_master', 1.00 )
+ self.make_constraits( 'mch_jaw_master', 'MCH-jaw_master.001', 'jaw_master', 0.75 )
+ self.make_constraits( 'mch_jaw_master', 'MCH-jaw_master.002', 'jaw_master', 0.35 )
+ self.make_constraits( 'mch_jaw_master', 'MCH-jaw_master.003', 'jaw_master', 0.10 )
+ self.make_constraits( 'mch_jaw_master', 'MCH-jaw_master.004', 'jaw_master', 0.025 )
+
+ self.make_constraits( 'teeth', 'ORG-teeth.T', 'teeth.T', 1.00 )
+ self.make_constraits( 'teeth', 'ORG-teeth.B', 'teeth.B', 1.00 )
+
+ for bone in all_bones['mch']['jaw'][1:-1]:
+ self.make_constraits( 'mch_jaw_master', bone, 'MCH-mouth_lock' )
+
+ ## Tweak bones constraints
+
+ # copy location constraints for tweak bones of both sides
+ tweak_copyloc_L = {
+ 'brow.T.L.002' : [ [ 'brow.T.L.001', 'brow.T.L.003' ], [ 0.5, 0.5 ] ],
+ 'ear.L.003' : [ [ 'ear.L.004', 'ear.L.002' ], [ 0.5, 0.5 ] ],
+ 'brow.B.L.001' : [ [ 'brow.B.L.002' ], [ 0.6 ] ],
+ 'brow.B.L.003' : [ [ 'brow.B.L.002' ], [ 0.6 ] ],
+ 'brow.B.L.002' : [ [ 'lid.T.L.001', ], [ 0.25 ] ],
+ 'brow.B.L.002' : [ [ 'brow.T.L.002', ], [ 0.25 ] ],
+ 'lid.T.L.001' : [ [ 'lid.T.L.002' ], [ 0.6 ] ],
+ 'lid.T.L.003' : [ [ 'lid.T.L.002', ], [ 0.6 ] ],
+ 'lid.T.L.002' : [ [ 'MCH-eye.L.001', ], [ 0.5 ] ],
+ 'lid.B.L.001' : [ [ 'lid.B.L.002', ], [ 0.6 ] ],
+ 'lid.B.L.003' : [ [ 'lid.B.L.002', ], [ 0.6 ] ],
+ 'lid.B.L.002' : [ [ 'MCH-eye.L.001', 'cheek.T.L.001' ], [ 0.5, 0.1 ] ],
+ 'cheek.T.L.001' : [ [ 'cheek.B.L.001', ], [ 0.5 ] ],
+ 'nose.L' : [ [ 'nose.L.001', ], [ 0.25 ] ],
+ 'nose.L.001' : [ [ 'lip.T.L.001', ], [ 0.2 ] ],
+ 'cheek.B.L.001' : [ [ 'lips.L', ], [ 0.5 ] ],
+ 'lip.T.L.001' : [ [ 'lips.L', 'lip.T' ], [ 0.25, 0.5 ] ],
+ 'lip.B.L.001' : [ [ 'lips.L', 'lip.B' ], [ 0.25, 0.5 ] ]
+ }
+
+ for owner in list( tweak_copyloc_L.keys() ):
+
+ targets, influences = tweak_copyloc_L[owner]
+ for target, influence in zip( targets, influences ):
+
+ # Left side constraints
+ self.make_constraits( 'tweak_copyloc', owner, target, influence )
+
+ # create constraints for the right side too
+ ownerR = owner.replace( '.L', '.R' )
+ targetR = target.replace( '.L', '.R' )
+ self.make_constraits( 'tweak_copyloc', ownerR, targetR, influence )
+
+ # copy rotation & scale constraints for tweak bones of both sides
+ tweak_copy_rot_scl_L = {
+ 'lip.T.L.001' : 'lip.T',
+ 'lip.B.L.001' : 'lip.B'
+ }
+
+ for owner in list( tweak_copy_rot_scl_L.keys() ):
+ target = tweak_copy_rot_scl_L[owner]
+ influence = tweak_copy_rot_scl_L[owner]
+ self.make_constraits( 'tweak_copy_rot_scl', owner, target )
+
+ # create constraints for the right side too
+ owner = owner.replace( '.L', '.R' )
+ self.make_constraits( 'tweak_copy_rot_scl', owner, target )
+
+ # inverted tweak bones constraints
+ tweak_nose = {
+ 'nose.001' : [ 'nose.002', 0.35 ],
+ 'nose.003' : [ 'nose.002', 0.5 ],
+ 'nose.005' : [ 'lip.T', 0.5 ],
+ 'chin.002' : [ 'lip.B', 0.5 ]
+ }
+
+ for owner in list( tweak_nose.keys() ):
+ target = tweak_nose[owner][0]
+ influence = tweak_nose[owner][1]
+ self.make_constraits( 'tweak_copyloc_inv', owner, target, influence )
+
+ # MCH tongue constraints
+ divider = len( all_bones['mch']['tongue'] ) + 1
+ factor = len( all_bones['mch']['tongue'] )
+
+ for owner in all_bones['mch']['tongue']:
+ self.make_constraits( 'mch_tongue_copy_trans', owner, 'tongue_master', ( 1 / divider ) * factor )
+ factor -= 1
+
+
+ def drivers_and_props( self, all_bones ):
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ jaw_ctrl = all_bones['ctrls']['jaw'][0]
+ eyes_ctrl = all_bones['ctrls']['eyes'][2]
+
+ jaw_prop = 'mouth_lock'
+ eyes_prop = 'eyes_follow'
+
+ for bone, prop_name in zip( [ jaw_ctrl, eyes_ctrl ], [ jaw_prop, eyes_prop ] ):
+ if bone == jaw_ctrl:
+ pb[ bone ][ prop_name ] = 0.0
+ else:
+ pb[ bone ][ prop_name ] = 1.0
+
+ prop = rna_idprop_ui_prop_get( pb[ bone ], prop_name )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = prop_name
+
+ # Jaw drivers
+ mch_jaws = all_bones['mch']['jaw'][1:-1]
+
+ for bone in mch_jaws:
+ drv = pb[ bone ].constraints[1].driver_add("influence").driver
+ drv.type='SUM'
+
+ var = drv.variables.new()
+ var.name = jaw_prop
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[ jaw_ctrl ].path_from_id() + '['+ '"' + jaw_prop + '"' + ']'
+
+
+ # Eyes driver
+ mch_eyes_parent = all_bones['mch']['eyes_parent'][0]
+
+ drv = pb[ mch_eyes_parent ].constraints[0].driver_add("influence").driver
+ drv.type='SUM'
+
+ var = drv.variables.new()
+ var.name = eyes_prop
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[ eyes_ctrl ].path_from_id() + '['+ '"' + eyes_prop + '"' + ']'
+
+ return jaw_prop, eyes_prop
+
+ def create_bones(self):
+ org_bones = self.org_bones
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Clear parents for org bones
+ for bone in [ bone for bone in org_bones if 'face' not in bone ]:
+ eb[bone].use_connect = False
+ eb[bone].parent = None
+
+ all_bones = {}
+
+ def_names = self.create_deformation()
+ ctrls, tweak_unique = self.all_controls()
+ mchs = self.create_mch(
+ ctrls['ctrls']['jaw'][0],
+ ctrls['ctrls']['tongue'][0]
+ )
+ return {
+ 'deform' : def_names,
+ 'ctrls' : ctrls['ctrls'],
+ 'tweaks' : ctrls['tweaks'],
+ 'mch' : mchs
+ }, tweak_unique
+
+
+ def generate(self):
+
+ all_bones, tweak_unique = self.create_bones()
+ self.parent_bones( all_bones, tweak_unique )
+ self.constraints( all_bones )
+ jaw_prop, eyes_prop = self.drivers_and_props( all_bones )
+
+
+ # Create UI
+ all_controls = []
+ all_controls += [ bone for bone in [ bgroup for bgroup in [ all_bones['ctrls'][group] for group in list( all_bones['ctrls'].keys() ) ] ] ]
+ all_controls += [ bone for bone in [ bgroup for bgroup in [ all_bones['tweaks'][group] for group in list( all_bones['tweaks'].keys() ) ] ] ]
+
+ all_ctrls = []
+ for group in all_controls:
+ for bone in group:
+ all_ctrls.append( bone )
+
+ controls_string = ", ".join(["'" + x + "'" for x in all_ctrls])
+ return [ script % (
+ controls_string,
+ all_bones['ctrls']['jaw'][0],
+ all_bones['ctrls']['eyes'][2],
+ jaw_prop,
+ eyes_prop )
+ ]
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+
+ #Setting up extra layers for the tweak bones
+ params.primary_layers_extra = bpy.props.BoolProperty(
+ name = "primary_layers_extra",
+ default = True,
+ description = ""
+ )
+ params.primary_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the 1st tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+ params.secondary_layers_extra = bpy.props.BoolProperty(
+ name = "secondary_layers_extra",
+ default = True,
+ description = ""
+ )
+ params.secondary_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the 2nd tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters."""
+ layers = ["primary_layers", "secondary_layers"]
+
+ for layer in layers:
+ r = layout.row()
+ r.prop( params, layer + "_extra" )
+ r.active = getattr( params, layer + "_extra" )
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+ for i in range(8):
+ row.prop(params, layer, index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+ for i in range(16,24):
+ row.prop(params, layer, index=i, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range(8,16):
+ row.prop(params, layer, index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+ for i in range(24,32):
+ row.prop(params, layer, index=i, toggle=True, text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('face')
+ bone.head[:] = -0.0000, -0.0013, 0.0437
+ bone.tail[:] = -0.0000, -0.0013, 0.1048
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['face'] = bone.name
+ bone = arm.edit_bones.new('nose')
+ bone.head[:] = 0.0000, -0.0905, 0.1125
+ bone.tail[:] = 0.0000, -0.1105, 0.0864
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['nose'] = bone.name
+ bone = arm.edit_bones.new('lip.T.L')
+ bone.head[:] = 0.0000, -0.1022, 0.0563
+ bone.tail[:] = 0.0131, -0.0986, 0.0567
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lip.T.L'] = bone.name
+ bone = arm.edit_bones.new('lip.B.L')
+ bone.head[:] = 0.0000, -0.0993, 0.0455
+ bone.tail[:] = 0.0124, -0.0938, 0.0488
+ bone.roll = -0.0789
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lip.B.L'] = bone.name
+ bone = arm.edit_bones.new('jaw')
+ bone.head[:] = 0.0000, -0.0389, 0.0222
+ bone.tail[:] = 0.0000, -0.0923, 0.0044
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['jaw'] = bone.name
+ bone = arm.edit_bones.new('ear.L')
+ bone.head[:] = 0.0616, -0.0083, 0.0886
+ bone.tail[:] = 0.0663, -0.0101, 0.1151
+ bone.roll = -0.0324
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['ear.L'] = bone.name
+ bone = arm.edit_bones.new('ear.R')
+ bone.head[:] = -0.0616, -0.0083, 0.0886
+ bone.tail[:] = -0.0663, -0.0101, 0.1151
+ bone.roll = 0.0324
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['ear.R'] = bone.name
+ bone = arm.edit_bones.new('lip.T.R')
+ bone.head[:] = -0.0000, -0.1022, 0.0563
+ bone.tail[:] = -0.0131, -0.0986, 0.0567
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lip.T.R'] = bone.name
+ bone = arm.edit_bones.new('lip.B.R')
+ bone.head[:] = -0.0000, -0.0993, 0.0455
+ bone.tail[:] = -0.0124, -0.0938, 0.0488
+ bone.roll = 0.0789
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lip.B.R'] = bone.name
+ bone = arm.edit_bones.new('brow.B.L')
+ bone.head[:] = 0.0530, -0.0705, 0.1153
+ bone.tail[:] = 0.0472, -0.0780, 0.1192
+ bone.roll = 0.0412
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['brow.B.L'] = bone.name
+ bone = arm.edit_bones.new('lid.T.L')
+ bone.head[:] = 0.0515, -0.0692, 0.1104
+ bone.tail[:] = 0.0474, -0.0785, 0.1136
+ bone.roll = 0.1166
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lid.T.L'] = bone.name
+ bone = arm.edit_bones.new('brow.B.R')
+ bone.head[:] = -0.0530, -0.0705, 0.1153
+ bone.tail[:] = -0.0472, -0.0780, 0.1192
+ bone.roll = -0.0412
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['brow.B.R'] = bone.name
+ bone = arm.edit_bones.new('lid.T.R')
+ bone.head[:] = -0.0515, -0.0692, 0.1104
+ bone.tail[:] = -0.0474, -0.0785, 0.1136
+ bone.roll = -0.1166
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['lid.T.R'] = bone.name
+ bone = arm.edit_bones.new('forehead.L')
+ bone.head[:] = 0.0113, -0.0764, 0.1611
+ bone.tail[:] = 0.0144, -0.0912, 0.1236
+ bone.roll = 1.4313
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['forehead.L'] = bone.name
+ bone = arm.edit_bones.new('forehead.R')
+ bone.head[:] = -0.0113, -0.0764, 0.1611
+ bone.tail[:] = -0.0144, -0.0912, 0.1236
+ bone.roll = -1.4313
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['forehead.R'] = bone.name
+ bone = arm.edit_bones.new('eye.L')
+ bone.head[:] = 0.0360, -0.0686, 0.1107
+ bone.tail[:] = 0.0360, -0.0848, 0.1107
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['eye.L'] = bone.name
+ bone = arm.edit_bones.new('eye.R')
+ bone.head[:] = -0.0360, -0.0686, 0.1107
+ bone.tail[:] = -0.0360, -0.0848, 0.1107
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['eye.R'] = bone.name
+ bone = arm.edit_bones.new('cheek.T.L')
+ bone.head[:] = 0.0568, -0.0506, 0.1052
+ bone.tail[:] = 0.0379, -0.0834, 0.0816
+ bone.roll = -0.0096
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['cheek.T.L'] = bone.name
+ bone = arm.edit_bones.new('cheek.T.R')
+ bone.head[:] = -0.0568, -0.0506, 0.1052
+ bone.tail[:] = -0.0379, -0.0834, 0.0816
+ bone.roll = 0.0096
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['cheek.T.R'] = bone.name
+ bone = arm.edit_bones.new('teeth.T')
+ bone.head[:] = 0.0000, -0.0927, 0.0613
+ bone.tail[:] = 0.0000, -0.0621, 0.0613
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['teeth.T'] = bone.name
+ bone = arm.edit_bones.new('teeth.B')
+ bone.head[:] = 0.0000, -0.0881, 0.0397
+ bone.tail[:] = 0.0000, -0.0575, 0.0397
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['teeth.B'] = bone.name
+ bone = arm.edit_bones.new('tongue')
+ bone.head[:] = 0.0000, -0.0781, 0.0493
+ bone.tail[:] = 0.0000, -0.0620, 0.0567
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['face']]
+ bones['tongue'] = bone.name
+ bone = arm.edit_bones.new('nose.001')
+ bone.head[:] = 0.0000, -0.1105, 0.0864
+ bone.tail[:] = 0.0000, -0.1193, 0.0771
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose']]
+ bones['nose.001'] = bone.name
+ bone = arm.edit_bones.new('lip.T.L.001')
+ bone.head[:] = 0.0131, -0.0986, 0.0567
+ bone.tail[:] = 0.0236, -0.0877, 0.0519
+ bone.roll = 0.0236
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lip.T.L']]
+ bones['lip.T.L.001'] = bone.name
+ bone = arm.edit_bones.new('lip.B.L.001')
+ bone.head[:] = 0.0124, -0.0938, 0.0488
+ bone.tail[:] = 0.0236, -0.0877, 0.0519
+ bone.roll = 0.0731
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lip.B.L']]
+ bones['lip.B.L.001'] = bone.name
+ bone = arm.edit_bones.new('chin')
+ bone.head[:] = 0.0000, -0.0923, 0.0044
+ bone.tail[:] = 0.0000, -0.0921, 0.0158
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['jaw']]
+ bones['chin'] = bone.name
+ bone = arm.edit_bones.new('ear.L.001')
+ bone.head[:] = 0.0663, -0.0101, 0.1151
+ bone.tail[:] = 0.0804, 0.0065, 0.1189
+ bone.roll = 0.0656
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.L']]
+ bones['ear.L.001'] = bone.name
+ bone = arm.edit_bones.new('ear.R.001')
+ bone.head[:] = -0.0663, -0.0101, 0.1151
+ bone.tail[:] = -0.0804, 0.0065, 0.1189
+ bone.roll = -0.0656
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.R']]
+ bones['ear.R.001'] = bone.name
+ bone = arm.edit_bones.new('lip.T.R.001')
+ bone.head[:] = -0.0131, -0.0986, 0.0567
+ bone.tail[:] = -0.0236, -0.0877, 0.0519
+ bone.roll = -0.0236
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lip.T.R']]
+ bones['lip.T.R.001'] = bone.name
+ bone = arm.edit_bones.new('lip.B.R.001')
+ bone.head[:] = -0.0124, -0.0938, 0.0488
+ bone.tail[:] = -0.0236, -0.0877, 0.0519
+ bone.roll = -0.0731
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lip.B.R']]
+ bones['lip.B.R.001'] = bone.name
+ bone = arm.edit_bones.new('brow.B.L.001')
+ bone.head[:] = 0.0472, -0.0780, 0.1192
+ bone.tail[:] = 0.0387, -0.0832, 0.1202
+ bone.roll = 0.0192
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.L']]
+ bones['brow.B.L.001'] = bone.name
+ bone = arm.edit_bones.new('lid.T.L.001')
+ bone.head[:] = 0.0474, -0.0785, 0.1136
+ bone.tail[:] = 0.0394, -0.0838, 0.1147
+ bone.roll = 0.0791
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.L']]
+ bones['lid.T.L.001'] = bone.name
+ bone = arm.edit_bones.new('brow.B.R.001')
+ bone.head[:] = -0.0472, -0.0780, 0.1192
+ bone.tail[:] = -0.0387, -0.0832, 0.1202
+ bone.roll = -0.0192
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.R']]
+ bones['brow.B.R.001'] = bone.name
+ bone = arm.edit_bones.new('lid.T.R.001')
+ bone.head[:] = -0.0474, -0.0785, 0.1136
+ bone.tail[:] = -0.0394, -0.0838, 0.1147
+ bone.roll = -0.0791
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.R']]
+ bones['lid.T.R.001'] = bone.name
+ bone = arm.edit_bones.new('forehead.L.001')
+ bone.head[:] = 0.0321, -0.0663, 0.1646
+ bone.tail[:] = 0.0394, -0.0828, 0.1310
+ bone.roll = 0.9928
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.L']]
+ bones['forehead.L.001'] = bone.name
+ bone = arm.edit_bones.new('forehead.R.001')
+ bone.head[:] = -0.0321, -0.0663, 0.1646
+ bone.tail[:] = -0.0394, -0.0828, 0.1310
+ bone.roll = -0.9928
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.R']]
+ bones['forehead.R.001'] = bone.name
+ bone = arm.edit_bones.new('cheek.T.L.001')
+ bone.head[:] = 0.0379, -0.0834, 0.0816
+ bone.tail[:] = 0.0093, -0.0846, 0.1002
+ bone.roll = 0.0320
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.T.L']]
+ bones['cheek.T.L.001'] = bone.name
+ bone = arm.edit_bones.new('cheek.T.R.001')
+ bone.head[:] = -0.0379, -0.0834, 0.0816
+ bone.tail[:] = -0.0093, -0.0846, 0.1002
+ bone.roll = -0.0320
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.T.R']]
+ bones['cheek.T.R.001'] = bone.name
+ bone = arm.edit_bones.new('tongue.001')
+ bone.head[:] = 0.0000, -0.0620, 0.0567
+ bone.tail[:] = 0.0000, -0.0406, 0.0584
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tongue']]
+ bones['tongue.001'] = bone.name
+ bone = arm.edit_bones.new('nose.002')
+ bone.head[:] = 0.0000, -0.1193, 0.0771
+ bone.tail[:] = 0.0000, -0.1118, 0.0739
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose.001']]
+ bones['nose.002'] = bone.name
+ bone = arm.edit_bones.new('chin.001')
+ bone.head[:] = 0.0000, -0.0921, 0.0158
+ bone.tail[:] = 0.0000, -0.0914, 0.0404
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['chin']]
+ bones['chin.001'] = bone.name
+ bone = arm.edit_bones.new('ear.L.002')
+ bone.head[:] = 0.0804, 0.0065, 0.1189
+ bone.tail[:] = 0.0808, 0.0056, 0.0935
+ bone.roll = -0.0265
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.L.001']]
+ bones['ear.L.002'] = bone.name
+ bone = arm.edit_bones.new('ear.R.002')
+ bone.head[:] = -0.0804, 0.0065, 0.1189
+ bone.tail[:] = -0.0808, 0.0056, 0.0935
+ bone.roll = 0.0265
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.R.001']]
+ bones['ear.R.002'] = bone.name
+ bone = arm.edit_bones.new('brow.B.L.002')
+ bone.head[:] = 0.0387, -0.0832, 0.1202
+ bone.tail[:] = 0.0295, -0.0826, 0.1179
+ bone.roll = -0.0278
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.L.001']]
+ bones['brow.B.L.002'] = bone.name
+ bone = arm.edit_bones.new('lid.T.L.002')
+ bone.head[:] = 0.0394, -0.0838, 0.1147
+ bone.tail[:] = 0.0317, -0.0832, 0.1131
+ bone.roll = -0.0356
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.L.001']]
+ bones['lid.T.L.002'] = bone.name
+ bone = arm.edit_bones.new('brow.B.R.002')
+ bone.head[:] = -0.0387, -0.0832, 0.1202
+ bone.tail[:] = -0.0295, -0.0826, 0.1179
+ bone.roll = 0.0278
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.R.001']]
+ bones['brow.B.R.002'] = bone.name
+ bone = arm.edit_bones.new('lid.T.R.002')
+ bone.head[:] = -0.0394, -0.0838, 0.1147
+ bone.tail[:] = -0.0317, -0.0832, 0.1131
+ bone.roll = 0.0356
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.R.001']]
+ bones['lid.T.R.002'] = bone.name
+ bone = arm.edit_bones.new('forehead.L.002')
+ bone.head[:] = 0.0482, -0.0506, 0.1620
+ bone.tail[:] = 0.0556, -0.0689, 0.1249
+ bone.roll = 0.4509
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.L.001']]
+ bones['forehead.L.002'] = bone.name
+ bone = arm.edit_bones.new('forehead.R.002')
+ bone.head[:] = -0.0482, -0.0506, 0.1620
+ bone.tail[:] = -0.0556, -0.0689, 0.1249
+ bone.roll = -0.4509
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.R.001']]
+ bones['forehead.R.002'] = bone.name
+ bone = arm.edit_bones.new('nose.L')
+ bone.head[:] = 0.0093, -0.0846, 0.1002
+ bone.tail[:] = 0.0118, -0.0966, 0.0757
+ bone.roll = -0.0909
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.T.L.001']]
+ bones['nose.L'] = bone.name
+ bone = arm.edit_bones.new('nose.R')
+ bone.head[:] = -0.0093, -0.0846, 0.1002
+ bone.tail[:] = -0.0118, -0.0966, 0.0757
+ bone.roll = 0.0909
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.T.R.001']]
+ bones['nose.R'] = bone.name
+ bone = arm.edit_bones.new('tongue.002')
+ bone.head[:] = 0.0000, -0.0406, 0.0584
+ bone.tail[:] = 0.0000, -0.0178, 0.0464
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tongue.001']]
+ bones['tongue.002'] = bone.name
+ bone = arm.edit_bones.new('nose.003')
+ bone.head[:] = 0.0000, -0.1118, 0.0739
+ bone.tail[:] = 0.0000, -0.1019, 0.0733
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose.002']]
+ bones['nose.003'] = bone.name
+ bone = arm.edit_bones.new('ear.L.003')
+ bone.head[:] = 0.0808, 0.0056, 0.0935
+ bone.tail[:] = 0.0677, -0.0109, 0.0752
+ bone.roll = 0.3033
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.L.002']]
+ bones['ear.L.003'] = bone.name
+ bone = arm.edit_bones.new('ear.R.003')
+ bone.head[:] = -0.0808, 0.0056, 0.0935
+ bone.tail[:] = -0.0677, -0.0109, 0.0752
+ bone.roll = -0.3033
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.R.002']]
+ bones['ear.R.003'] = bone.name
+ bone = arm.edit_bones.new('brow.B.L.003')
+ bone.head[:] = 0.0295, -0.0826, 0.1179
+ bone.tail[:] = 0.0201, -0.0812, 0.1095
+ bone.roll = 0.0417
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.L.002']]
+ bones['brow.B.L.003'] = bone.name
+ bone = arm.edit_bones.new('lid.T.L.003')
+ bone.head[:] = 0.0317, -0.0832, 0.1131
+ bone.tail[:] = 0.0237, -0.0826, 0.1058
+ bone.roll = 0.0245
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.L.002']]
+ bones['lid.T.L.003'] = bone.name
+ bone = arm.edit_bones.new('brow.B.R.003')
+ bone.head[:] = -0.0295, -0.0826, 0.1179
+ bone.tail[:] = -0.0201, -0.0812, 0.1095
+ bone.roll = -0.0417
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.B.R.002']]
+ bones['brow.B.R.003'] = bone.name
+ bone = arm.edit_bones.new('lid.T.R.003')
+ bone.head[:] = -0.0317, -0.0832, 0.1131
+ bone.tail[:] = -0.0237, -0.0826, 0.1058
+ bone.roll = -0.0245
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.R.002']]
+ bones['lid.T.R.003'] = bone.name
+ bone = arm.edit_bones.new('temple.L')
+ bone.head[:] = 0.0585, -0.0276, 0.1490
+ bone.tail[:] = 0.0607, -0.0295, 0.0962
+ bone.roll = -0.0650
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.L.002']]
+ bones['temple.L'] = bone.name
+ bone = arm.edit_bones.new('temple.R')
+ bone.head[:] = -0.0585, -0.0276, 0.1490
+ bone.tail[:] = -0.0607, -0.0295, 0.0962
+ bone.roll = 0.0650
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['forehead.R.002']]
+ bones['temple.R'] = bone.name
+ bone = arm.edit_bones.new('nose.L.001')
+ bone.head[:] = 0.0118, -0.0966, 0.0757
+ bone.tail[:] = 0.0000, -0.1193, 0.0771
+ bone.roll = 0.1070
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose.L']]
+ bones['nose.L.001'] = bone.name
+ bone = arm.edit_bones.new('nose.R.001')
+ bone.head[:] = -0.0118, -0.0966, 0.0757
+ bone.tail[:] = -0.0000, -0.1193, 0.0771
+ bone.roll = -0.1070
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose.R']]
+ bones['nose.R.001'] = bone.name
+ bone = arm.edit_bones.new('nose.004')
+ bone.head[:] = 0.0000, -0.1019, 0.0733
+ bone.tail[:] = 0.0000, -0.1014, 0.0633
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['nose.003']]
+ bones['nose.004'] = bone.name
+ bone = arm.edit_bones.new('ear.L.004')
+ bone.head[:] = 0.0677, -0.0109, 0.0752
+ bone.tail[:] = 0.0616, -0.0083, 0.0886
+ bone.roll = 0.1518
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.L.003']]
+ bones['ear.L.004'] = bone.name
+ bone = arm.edit_bones.new('ear.R.004')
+ bone.head[:] = -0.0677, -0.0109, 0.0752
+ bone.tail[:] = -0.0616, -0.0083, 0.0886
+ bone.roll = -0.1518
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['ear.R.003']]
+ bones['ear.R.004'] = bone.name
+ bone = arm.edit_bones.new('lid.B.L')
+ bone.head[:] = 0.0237, -0.0826, 0.1058
+ bone.tail[:] = 0.0319, -0.0831, 0.1050
+ bone.roll = -0.1108
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.L.003']]
+ bones['lid.B.L'] = bone.name
+ bone = arm.edit_bones.new('lid.B.R')
+ bone.head[:] = -0.0237, -0.0826, 0.1058
+ bone.tail[:] = -0.0319, -0.0831, 0.1050
+ bone.roll = 0.1108
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.T.R.003']]
+ bones['lid.B.R'] = bone.name
+ bone = arm.edit_bones.new('jaw.L')
+ bone.head[:] = 0.0607, -0.0295, 0.0962
+ bone.tail[:] = 0.0451, -0.0338, 0.0533
+ bone.roll = 0.0871
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['temple.L']]
+ bones['jaw.L'] = bone.name
+ bone = arm.edit_bones.new('jaw.R')
+ bone.head[:] = -0.0607, -0.0295, 0.0962
+ bone.tail[:] = -0.0451, -0.0338, 0.0533
+ bone.roll = -0.0871
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['temple.R']]
+ bones['jaw.R'] = bone.name
+ bone = arm.edit_bones.new('lid.B.L.001')
+ bone.head[:] = 0.0319, -0.0831, 0.1050
+ bone.tail[:] = 0.0389, -0.0826, 0.1050
+ bone.roll = -0.0207
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.L']]
+ bones['lid.B.L.001'] = bone.name
+ bone = arm.edit_bones.new('lid.B.R.001')
+ bone.head[:] = -0.0319, -0.0831, 0.1050
+ bone.tail[:] = -0.0389, -0.0826, 0.1050
+ bone.roll = 0.0207
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.R']]
+ bones['lid.B.R.001'] = bone.name
+ bone = arm.edit_bones.new('jaw.L.001')
+ bone.head[:] = 0.0451, -0.0338, 0.0533
+ bone.tail[:] = 0.0166, -0.0758, 0.0187
+ bone.roll = 0.0458
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['jaw.L']]
+ bones['jaw.L.001'] = bone.name
+ bone = arm.edit_bones.new('jaw.R.001')
+ bone.head[:] = -0.0451, -0.0338, 0.0533
+ bone.tail[:] = -0.0166, -0.0758, 0.0187
+ bone.roll = -0.0458
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['jaw.R']]
+ bones['jaw.R.001'] = bone.name
+ bone = arm.edit_bones.new('lid.B.L.002')
+ bone.head[:] = 0.0389, -0.0826, 0.1050
+ bone.tail[:] = 0.0472, -0.0781, 0.1068
+ bone.roll = 0.0229
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.L.001']]
+ bones['lid.B.L.002'] = bone.name
+ bone = arm.edit_bones.new('lid.B.R.002')
+ bone.head[:] = -0.0389, -0.0826, 0.1050
+ bone.tail[:] = -0.0472, -0.0781, 0.1068
+ bone.roll = -0.0229
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.R.001']]
+ bones['lid.B.R.002'] = bone.name
+ bone = arm.edit_bones.new('chin.L')
+ bone.head[:] = 0.0166, -0.0758, 0.0187
+ bone.tail[:] = 0.0236, -0.0877, 0.0519
+ bone.roll = 0.1513
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['jaw.L.001']]
+ bones['chin.L'] = bone.name
+ bone = arm.edit_bones.new('chin.R')
+ bone.head[:] = -0.0166, -0.0758, 0.0187
+ bone.tail[:] = -0.0236, -0.0877, 0.0519
+ bone.roll = -0.1513
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['jaw.R.001']]
+ bones['chin.R'] = bone.name
+ bone = arm.edit_bones.new('lid.B.L.003')
+ bone.head[:] = 0.0472, -0.0781, 0.1068
+ bone.tail[:] = 0.0515, -0.0692, 0.1104
+ bone.roll = -0.0147
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.L.002']]
+ bones['lid.B.L.003'] = bone.name
+ bone = arm.edit_bones.new('lid.B.R.003')
+ bone.head[:] = -0.0472, -0.0781, 0.1068
+ bone.tail[:] = -0.0515, -0.0692, 0.1104
+ bone.roll = 0.0147
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['lid.B.R.002']]
+ bones['lid.B.R.003'] = bone.name
+ bone = arm.edit_bones.new('cheek.B.L')
+ bone.head[:] = 0.0236, -0.0877, 0.0519
+ bone.tail[:] = 0.0493, -0.0691, 0.0632
+ bone.roll = 0.0015
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['chin.L']]
+ bones['cheek.B.L'] = bone.name
+ bone = arm.edit_bones.new('cheek.B.R')
+ bone.head[:] = -0.0236, -0.0877, 0.0519
+ bone.tail[:] = -0.0493, -0.0691, 0.0632
+ bone.roll = -0.0015
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['chin.R']]
+ bones['cheek.B.R'] = bone.name
+ bone = arm.edit_bones.new('cheek.B.L.001')
+ bone.head[:] = 0.0493, -0.0691, 0.0632
+ bone.tail[:] = 0.0568, -0.0506, 0.1052
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.B.L']]
+ bones['cheek.B.L.001'] = bone.name
+ bone = arm.edit_bones.new('cheek.B.R.001')
+ bone.head[:] = -0.0493, -0.0691, 0.0632
+ bone.tail[:] = -0.0568, -0.0506, 0.1052
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.B.R']]
+ bones['cheek.B.R.001'] = bone.name
+ bone = arm.edit_bones.new('brow.T.L')
+ bone.head[:] = 0.0568, -0.0506, 0.1052
+ bone.tail[:] = 0.0556, -0.0689, 0.1249
+ bone.roll = 0.1990
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.B.L.001']]
+ bones['brow.T.L'] = bone.name
+ bone = arm.edit_bones.new('brow.T.R')
+ bone.head[:] = -0.0568, -0.0506, 0.1052
+ bone.tail[:] = -0.0556, -0.0689, 0.1249
+ bone.roll = -0.1990
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['cheek.B.R.001']]
+ bones['brow.T.R'] = bone.name
+ bone = arm.edit_bones.new('brow.T.L.001')
+ bone.head[:] = 0.0556, -0.0689, 0.1249
+ bone.tail[:] = 0.0394, -0.0828, 0.1310
+ bone.roll = 0.2372
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.L']]
+ bones['brow.T.L.001'] = bone.name
+ bone = arm.edit_bones.new('brow.T.R.001')
+ bone.head[:] = -0.0556, -0.0689, 0.1249
+ bone.tail[:] = -0.0394, -0.0828, 0.1310
+ bone.roll = -0.2372
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.R']]
+ bones['brow.T.R.001'] = bone.name
+ bone = arm.edit_bones.new('brow.T.L.002')
+ bone.head[:] = 0.0394, -0.0828, 0.1310
+ bone.tail[:] = 0.0144, -0.0912, 0.1236
+ bone.roll = 0.0724
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.L.001']]
+ bones['brow.T.L.002'] = bone.name
+ bone = arm.edit_bones.new('brow.T.R.002')
+ bone.head[:] = -0.0394, -0.0828, 0.1310
+ bone.tail[:] = -0.0144, -0.0912, 0.1236
+ bone.roll = -0.0724
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.R.001']]
+ bones['brow.T.R.002'] = bone.name
+ bone = arm.edit_bones.new('brow.T.L.003')
+ bone.head[:] = 0.0144, -0.0912, 0.1236
+ bone.tail[:] = 0.0003, -0.0905, 0.1125
+ bone.roll = -0.0423
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.L.002']]
+ bones['brow.T.L.003'] = bone.name
+ bone = arm.edit_bones.new('brow.T.R.003')
+ bone.head[:] = -0.0144, -0.0912, 0.1236
+ bone.tail[:] = -0.0003, -0.0905, 0.1125
+ bone.roll = 0.0423
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['brow.T.R.002']]
+ bones['brow.T.R.003'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['face']]
+ pbone.rigify_type = 'pitchipoy.super_face'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.T.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.B.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['jaw']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.T.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.B.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['eye.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['eye.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.T.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.T.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['teeth.T']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['teeth.B']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['tongue']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.T.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.B.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['chin']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.T.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lip.B.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.T.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.T.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['tongue.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['chin.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['forehead.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['tongue.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.L.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.R.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.L.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.L.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.B.R.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.T.R.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['temple.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['temple.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['nose.004']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.L.004']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ear.R.004']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['jaw.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['jaw.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['jaw.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['jaw.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['chin.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['chin.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.L.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['lid.B.R.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.B.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.B.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.B.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['cheek.B.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.R']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.L.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.R.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.L.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.R.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.L.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['brow.T.R.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
+
+
+def create_square_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [
+ ( 0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
+ ( -0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
+ ( 0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
+ ( -0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
+ ]
+
+ edges = [(0, 1), (2, 3), (0, 2), (3, 1) ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ mesh.update()
+ return obj
+ else:
+ return None
+
diff --git a/rigify/legacy/rigs/pitchipoy/super_finger.py b/rigify/legacy/rigs/pitchipoy/super_finger.py
new file mode 100644
index 00000000..86733921
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_finger.py
@@ -0,0 +1,414 @@
+import bpy
+from mathutils import Vector
+from ...utils import copy_bone, flip_bone
+from ...utils import strip_org, make_deformer_name, connected_children_names, make_mechanism_name
+from ...utils import create_circle_widget, create_sphere_widget, create_widget
+from ...utils import MetarigError
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+script = """
+controls = [%s]
+master_name = '%s'
+if is_selected(controls):
+ layout.prop(pose_bones[master_name], '["%s"]', text="Curvature", slider=True)
+"""
+
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+
+ if len(self.org_bones) <= 1:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': listen bro, that finger rig jusaint put tugetha rite. A little hint, use more than one bone!!" % (strip_org(bone_name)))
+
+
+ def generate(self):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Bone name lists
+ ctrl_chain = []
+ def_chain = []
+ mch_chain = []
+ mch_drv_chain = []
+
+ # Create ctrl master bone
+ org_name = self.org_bones[0]
+ temp_name = strip_org(self.org_bones[0])
+
+ suffix = temp_name[-2:]
+ master_name = temp_name[:-5] + "_master" + suffix
+ master_name = copy_bone( self.obj, org_name, master_name )
+ ctrl_bone_master = eb[ master_name ]
+
+ ## Parenting bug fix ??
+ ctrl_bone_master.use_connect = False
+ ctrl_bone_master.parent = None
+
+ ctrl_bone_master.tail += ( eb[ org_bones[-1] ].tail - eb[org_name].head ) * 1.25
+
+ for bone in org_bones:
+ eb[bone].use_connect = False
+ if org_bones.index( bone ) != 0:
+ eb[bone].parent = None
+
+ # Creating the bone chains
+ for i in range(len(self.org_bones)):
+
+ name = self.org_bones[i]
+ ctrl_name = strip_org(name)
+
+ # Create control bones
+ ctrl_bone = copy_bone( self.obj, name, ctrl_name )
+ ctrl_bone_e = eb[ ctrl_name ]
+
+ # Create deformation bones
+ def_name = make_deformer_name( ctrl_name )
+ def_bone = copy_bone( self.obj, name, def_name )
+
+ # Create mechanism bones
+ mch_name = make_mechanism_name( ctrl_name )
+ mch_bone = copy_bone( self.obj, name, mch_name )
+
+ # Create mechanism driver bones
+ drv_name = make_mechanism_name(ctrl_name) + "_drv"
+ mch_bone_drv = copy_bone(self.obj, name, drv_name)
+ mch_bone_drv_e = eb[drv_name]
+
+ # Adding to lists
+ ctrl_chain += [ctrl_name]
+ def_chain += [def_bone]
+ mch_chain += [mch_bone]
+ mch_drv_chain += [drv_name]
+
+ # Restoring org chain parenting
+ for bone in org_bones[1:]:
+ eb[bone].parent = eb[ org_bones[ org_bones.index(bone) - 1 ] ]
+
+ # Parenting the master bone to the first org
+ ctrl_bone_master = eb[ master_name ]
+ ctrl_bone_master.parent = eb[ org_bones[0] ]
+
+ # Parenting chain bones
+ for i in range(len(self.org_bones)):
+ # Edit bone references
+ def_bone_e = eb[def_chain[i]]
+ ctrl_bone_e = eb[ctrl_chain[i]]
+ mch_bone_e = eb[mch_chain[i]]
+ mch_bone_drv_e = eb[mch_drv_chain[i]]
+
+ if i == 0:
+ # First ctl bone
+ ctrl_bone_e.parent = mch_bone_drv_e
+ ctrl_bone_e.use_connect = False
+ # First def bone
+ def_bone_e.parent = eb[self.org_bones[i]].parent
+ def_bone_e.use_connect = False
+ # First mch bone
+ mch_bone_e.parent = eb[self.org_bones[i]].parent
+ mch_bone_e.use_connect = False
+ # First mch driver bone
+ mch_bone_drv_e.parent = eb[self.org_bones[i]].parent
+ mch_bone_drv_e.use_connect = False
+ else:
+ # The rest
+ ctrl_bone_e.parent = mch_bone_drv_e
+ ctrl_bone_e.use_connect = False
+
+ def_bone_e.parent = eb[def_chain[i-1]]
+ def_bone_e.use_connect = True
+
+ mch_bone_drv_e.parent = eb[ctrl_chain[i-1]]
+ mch_bone_drv_e.use_connect = False
+
+ # Parenting mch bone
+ mch_bone_e.parent = ctrl_bone_e
+ mch_bone_e.use_connect = False
+
+ # Creating tip conrtol bone
+ tip_name = copy_bone( self.obj, org_bones[-1], temp_name )
+ ctrl_bone_tip = eb[ tip_name ]
+ flip_bone( self.obj, tip_name )
+ ctrl_bone_tip.length /= 2
+
+ ctrl_bone_tip.parent = eb[ctrl_chain[-1]]
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ pb = self.obj.pose.bones
+
+ # Setting pose bones locks
+ pb_master = pb[master_name]
+ pb_master.lock_scale = True,False,True
+
+ pb[tip_name].lock_scale = True,True,True
+ pb[tip_name].lock_rotation = True,True,True
+ pb[tip_name].lock_rotation_w = True
+
+ pb_master['finger_curve'] = 0.0
+ prop = rna_idprop_ui_prop_get(pb_master, 'finger_curve')
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = "Rubber hose finger cartoon effect"
+
+ # Pose settings
+ for org, ctrl, deform, mch, mch_drv in zip(self.org_bones, ctrl_chain, def_chain, mch_chain, mch_drv_chain):
+
+ # Constraining the org bones
+ #con = pb[org].constraints.new('COPY_TRANSFORMS')
+ #con.target = self.obj
+ #con.subtarget = ctrl
+
+ # Constraining the deform bones
+ con = pb[deform].constraints.new('COPY_TRANSFORMS')
+ con.target = self.obj
+ con.subtarget = mch
+
+ # Constraining the mch bones
+ if mch_chain.index(mch) == 0:
+ con = pb[mch].constraints.new('COPY_LOCATION')
+ con.target = self.obj
+ con.subtarget = ctrl
+
+ con = pb[mch].constraints.new('COPY_SCALE')
+ con.target = self.obj
+ con.subtarget = ctrl
+
+ con = pb[mch].constraints.new('DAMPED_TRACK')
+ con.target = self.obj
+ con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
+
+ con = pb[mch].constraints.new('STRETCH_TO')
+ con.target = self.obj
+ con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
+ con.volume = 'NO_VOLUME'
+
+ elif mch_chain.index(mch) == len(mch_chain) - 1:
+ con = pb[mch].constraints.new('DAMPED_TRACK')
+ con.target = self.obj
+ con.subtarget = tip_name
+
+ con = pb[mch].constraints.new('STRETCH_TO')
+ con.target = self.obj
+ con.subtarget = tip_name
+ con.volume = 'NO_VOLUME'
+ else:
+ con = pb[mch].constraints.new('DAMPED_TRACK')
+ con.target = self.obj
+ con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
+
+ con = pb[mch].constraints.new('STRETCH_TO')
+ con.target = self.obj
+ con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
+ con.volume = 'NO_VOLUME'
+
+ # Constraining and driving mch driver bones
+ pb[mch_drv].rotation_mode = 'YZX'
+
+ if mch_drv_chain.index(mch_drv) == 0:
+ # Constraining to master bone
+ con = pb[mch_drv].constraints.new('COPY_LOCATION')
+ con.target = self.obj
+ con.subtarget = master_name
+
+ con = pb[mch_drv].constraints.new('COPY_ROTATION')
+ con.target = self.obj
+ con.subtarget = master_name
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+
+ else:
+ # Match axis to expression
+ options = {
+ "X" : { "axis" : 0,
+ "expr" : '(1-sy)*pi' },
+ "-X" : { "axis" : 0,
+ "expr" : '-((1-sy)*pi)' },
+ "Y" : { "axis" : 1,
+ "expr" : '(1-sy)*pi' },
+ "-Y" : { "axis" : 1,
+ "expr" : '-((1-sy)*pi)' },
+ "Z" : { "axis" : 2,
+ "expr" : '(1-sy)*pi' },
+ "-Z" : { "axis" : 2,
+ "expr" : '-((1-sy)*pi)' }
+ }
+
+ axis = self.params.primary_rotation_axis
+
+ # Drivers
+ drv = pb[mch_drv].driver_add("rotation_euler", options[axis]["axis"]).driver
+ drv.type = 'SCRIPTED'
+ drv.expression = options[axis]["expr"]
+ drv_var = drv.variables.new()
+ drv_var.name = 'sy'
+ drv_var.type = "SINGLE_PROP"
+ drv_var.targets[0].id = self.obj
+ drv_var.targets[0].data_path = pb[master_name].path_from_id() + '.scale.y'
+
+ # Setting bone curvature setting, costum property, and drivers
+ def_bone = self.obj.data.bones[deform]
+
+ def_bone.bbone_segments = 8
+ drv = def_bone.driver_add("bbone_in").driver # Ease in
+
+ drv.type='SUM'
+ drv_var = drv.variables.new()
+ drv_var.name = "curvature"
+ drv_var.type = "SINGLE_PROP"
+ drv_var.targets[0].id = self.obj
+ drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]'
+
+ drv = def_bone.driver_add("bbone_out").driver # Ease out
+
+ drv.type='SUM'
+ drv_var = drv.variables.new()
+ drv_var.name = "curvature"
+ drv_var.type = "SINGLE_PROP"
+ drv_var.targets[0].id = self.obj
+ drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]'
+
+
+ # Assigning shapes to control bones
+ create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
+
+ # Create ctrl master widget
+ w = create_widget(self.obj, master_name)
+ if w is not None:
+ mesh = w.data
+ verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)]
+ if 'Z' in self.params.primary_rotation_axis:
+ # Flip x/z coordinates
+ temp = []
+ for v in verts:
+ temp += [(v[2], v[1], v[0])]
+ verts = temp
+ edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)]
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ # Create tip control widget
+ create_circle_widget(self.obj, tip_name, radius=0.3, head_tail=0.0)
+
+ # Create UI
+ controls_string = ", ".join(
+ ["'" + x + "'" for x in ctrl_chain]
+ ) + ", " + "'" + master_name + "'"
+ return [script % (controls_string, master_name, 'finger_curve')]
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+ params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+ """
+ r = layout.row()
+ r.label(text="Bend rotation axis:")
+ r.prop(params, "primary_rotation_axis", text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('palm.04.L')
+ bone.head[:] = 0.0043, -0.0030, -0.0026
+ bone.tail[:] = 0.0642, 0.0037, -0.0469
+ bone.roll = -2.5155
+ bone.use_connect = False
+ bones['palm.04.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.01.L')
+ bone.head[:] = 0.0642, 0.0037, -0.0469
+ bone.tail[:] = 0.0703, 0.0039, -0.0741
+ bone.roll = -1.9749
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.04.L']]
+ bones['f_pinky.01.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.02.L')
+ bone.head[:] = 0.0703, 0.0039, -0.0741
+ bone.tail[:] = 0.0732, 0.0044, -0.0965
+ bone.roll = -1.9059
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_pinky.01.L']]
+ bones['f_pinky.02.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.03.L')
+ bone.head[:] = 0.0732, 0.0044, -0.0965
+ bone.tail[:] = 0.0725, 0.0046, -0.1115
+ bone.roll = -1.7639
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_pinky.02.L']]
+ bones['f_pinky.03.L'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['palm.04.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['f_pinky.01.L']]
+ pbone.rigify_type = 'pitchipoy.simple_tentacle'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ 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
+ try:
+ pbone.rigify_parameters.tweak_extra_layers = False
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['f_pinky.02.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['f_pinky.03.L']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
+
+
+
+
+
diff --git a/rigify/legacy/rigs/pitchipoy/super_palm.py b/rigify/legacy/rigs/pitchipoy/super_palm.py
new file mode 100644
index 00000000..68d38958
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_palm.py
@@ -0,0 +1,324 @@
+# ##### 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 re
+from math import cos, pi
+
+import bpy
+
+from ...utils import MetarigError
+from ...utils import copy_bone
+from ...utils import strip_org, deformer
+from ...utils import create_widget
+
+
+def bone_siblings(obj, bone):
+ """ Returns a list of the siblings of the given bone.
+ This requires that the bones has a parent.
+
+ """
+ parent = obj.data.bones[bone].parent
+
+ if parent is None:
+ return []
+
+ bones = []
+
+ for b in parent.children:
+ if b.name != bone:
+ bones += [b.name]
+
+ return bones
+
+
+def bone_distance(obj, bone1, bone2):
+ """ Returns the distance between two bones.
+
+ """
+ vec = obj.data.bones[bone1].head - obj.data.bones[bone2].head
+ return vec.length
+
+
+class Rig:
+ """ A "palm" rig. A set of sibling bones that bend with each other.
+ This is a control and deformation rig.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ """
+ self.obj = obj
+ self.params = params
+
+ siblings = bone_siblings(obj, bone)
+
+ if len(siblings) == 0:
+ raise MetarigError(
+ "RIGIFY ERROR: Bone '%s': must have a parent and at least one sibling" %
+ (strip_org(bone)))
+
+ # Sort list by name and distance
+ siblings.sort()
+ siblings.sort(key=lambda b: bone_distance(obj, bone, b))
+
+ self.org_bones = [bone] + siblings
+
+ # Get rig parameters
+ self.palm_rotation_axis = params.palm_rotation_axis
+
+ 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.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Figure out the name for the control bone (remove the last .##)
+ last_bone = self.org_bones[-1:][0]
+ ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1]
+
+ # Make control bone
+ ctrl = copy_bone(self.obj, last_bone, ctrl_name)
+
+ # Make deformation bones
+ def_bones = []
+ for bone in self.org_bones:
+ b = copy_bone(self.obj, bone, deformer(strip_org(bone)))
+ def_bones += [b]
+
+ # Parenting
+ eb = self.obj.data.edit_bones
+
+ # turn off inherit scale for all ORG-bones to prevent undesired transformations
+
+ for o in self.org_bones:
+ eb[o].use_inherit_scale = False
+
+ for d, b in zip(def_bones, self.org_bones):
+ eb[d].use_connect = False
+ eb[d].parent = eb[b]
+
+ # Get ORG parent bone
+ org_parent = eb[self.org_bones[0]].parent.name
+
+ # Get DEF parent from ORG parent
+ def_parent = deformer(strip_org(org_parent))
+
+ # Switch parent
+ for o in self.org_bones:
+ eb[o].parent = eb[def_parent]
+ eb[ctrl].parent = eb[def_parent]
+
+ # Constraints
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ i = 0
+ div = len(self.org_bones) - 1
+ for b in self.org_bones:
+ con = pb[b].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = ctrl
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+ con.influence = i / div
+
+ con = pb[b].constraints.new('COPY_SCALE')
+ con.name = "copy_scale"
+ con.target = self.obj
+ con.subtarget = def_parent
+ con.target_space = 'WORLD'
+ con.owner_space = 'WORLD'
+ con.influence = 1
+
+ con = pb[b].constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = ctrl
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+ if 'X' in self.palm_rotation_axis:
+ con.invert_x = True
+ con.use_x = True
+ con.use_z = False
+ else:
+ con.invert_z = True
+ con.use_x = False
+ con.use_z = True
+ con.use_y = False
+
+ con.influence = (i / div) - (1 - cos((i * pi / 2) / div))
+
+ i += 1
+
+ # Create control widget
+ w = create_widget(self.obj, ctrl)
+ if w is not None:
+ mesh = w.data
+ verts = [
+ (0.1578, 0.0, -0.3),
+ (0.1578, 1.0, -0.2),
+ (-0.1578, 1.0, -0.2),
+ (-0.1578, -0.0, -0.3),
+ (-0.1578, -0.0, 0.3),
+ (-0.1578, 1.0, 0.2),
+ (0.1578, 1.0, 0.2),
+ (0.1578, 0.0, 0.3),
+ (0.1578, 0.25, -0.275),
+ (-0.1578, 0.25, -0.275),
+ (0.1578, 0.75, -0.225),
+ (-0.1578, 0.75, -0.225),
+ (0.1578, 0.75, 0.225),
+ (0.1578, 0.25, 0.275),
+ (-0.1578, 0.25, 0.275),
+ (-0.1578, 0.75, 0.225),
+ ]
+
+ if 'Z' in self.palm_rotation_axis:
+ # Flip x/z coordinates
+ verts = [v[::-1] for v in verts]
+
+ edges = [
+ (1, 2), (0, 3), (4, 7), (5, 6),
+ (8, 0), (9, 3), (10, 1), (11, 2),
+ (12, 6), (13, 7), (4, 14), (15, 5),
+ (10, 8), (11, 9), (15, 14), (12, 13),
+ ]
+ mesh.from_pydata(verts, edges, [])
+ mesh.update()
+
+ mod = w.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+
+ """
+ items = [('X', 'X', ''), ('Z', 'Z', '')]
+ params.palm_rotation_axis = bpy.props.EnumProperty(
+ items=items,
+ name="Palm Rotation Axis",
+ default='X',
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+
+ """
+ r = layout.row()
+ r.label(text="Primary rotation axis:")
+ r.prop(params, "palm_rotation_axis", text="")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('palm.parent')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0577, 0.0000, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bones['palm.parent'] = bone.name
+ bone = arm.edit_bones.new('palm.04')
+ bone.head[:] = 0.0577, 0.0315, -0.0000
+ bone.tail[:] = 0.1627, 0.0315, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.04'] = bone.name
+ bone = arm.edit_bones.new('palm.03')
+ bone.head[:] = 0.0577, 0.0105, -0.0000
+ bone.tail[:] = 0.1627, 0.0105, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.03'] = bone.name
+ bone = arm.edit_bones.new('palm.02')
+ bone.head[:] = 0.0577, -0.0105, -0.0000
+ bone.tail[:] = 0.1627, -0.0105, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.02'] = bone.name
+ bone = arm.edit_bones.new('palm.01')
+ bone.head[:] = 0.0577, -0.0315, -0.0000
+ bone.tail[:] = 0.1627, -0.0315, -0.0000
+ bone.roll = 3.1416
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.parent']]
+ bones['palm.01'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['palm.parent']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['palm.04']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.03']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.02']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.01']]
+ pbone.rigify_type = 'palm'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, True, True)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'YXZ'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py b/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py
new file mode 100644
index 00000000..e1ff5b0e
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py
@@ -0,0 +1,911 @@
+import bpy
+from mathutils import Vector
+from ...utils import copy_bone, flip_bone, put_bone, org
+from ...utils import strip_org, make_deformer_name, connected_children_names
+from ...utils import create_circle_widget, create_sphere_widget, create_widget
+from ...utils import MetarigError, make_mechanism_name, create_cube_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+script = """
+controls = [%s]
+torso = '%s'
+
+if is_selected( controls ):
+ layout.prop( pose_bones[ torso ], '["%s"]', slider = True )
+ layout.prop( pose_bones[ torso ], '["%s"]', slider = True )
+"""
+
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ """ Initialize torso rig and key rig properties """
+
+ eb = obj.data.edit_bones
+
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+ self.spine_length = sum( [ eb[b].length for b in self.org_bones ] )
+
+ # Check if user provided the positions of the neck and pivot
+ if params.neck_pos and params.pivot_pos:
+ self.neck_pos = params.neck_pos
+ self.pivot_pos = params.pivot_pos
+ else:
+ raise MetarigError(
+ "RIGIFY ERROR: please specify neck and pivot bone positions"
+ )
+
+ # Check if neck is lower than pivot
+ if params.neck_pos <= params.pivot_pos:
+ raise MetarigError(
+ "RIGIFY ERROR: Neck cannot be below or the same as pivot"
+ )
+
+ # TODO:
+ # Limit neck_pos prop to 1 --> num of bones - 1 (last is head)
+ # Limit pivot_pos prop to 2 --> num of bones (must leave place for lower torso)
+
+ if params.tail_pos:
+ self.tail_pos = params.tail_pos
+
+ # Assign values to tweak layers props if opted by user
+ if params.tweak_extra_layers:
+ self.tweak_layers = list(params.tweak_layers)
+ else:
+ self.tweak_layers = None
+
+ # Report error of user created less than the minimum of 4 bones for rig
+ if len(self.org_bones) <= 4:
+ raise MetarigError(
+ "RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
+ )
+
+
+ def build_bone_structure( self ):
+ """ Divide meta-rig into lists of bones according to torso rig anatomy:
+ Neck --> Upper torso --> Lower torso --> Tail (optional) """
+
+ if self.pivot_pos and self.neck_pos:
+
+ neck_index = self.neck_pos - 1
+ pivot_index = self.pivot_pos - 1
+
+ tail_index = 0
+ if 'tail_pos' in dir(self):
+ tail_index = self.tail_pos - 1
+
+ neck_bones = self.org_bones[neck_index::]
+ upper_torso_bones = self.org_bones[pivot_index:neck_index]
+ lower_torso_bones = self.org_bones[tail_index:pivot_index]
+
+ tail_bones = []
+ if tail_index:
+ tail_bones = self.org_bones[::tail_index+1]
+
+ return {
+ 'neck' : neck_bones,
+ 'upper' : upper_torso_bones,
+ 'lower' : lower_torso_bones,
+ 'tail' : tail_bones
+ }
+
+ else:
+ return 'ERROR'
+
+ def orient_bone( self, eb, axis, scale, reverse = False ):
+ v = Vector((0,0,0))
+
+ setattr(v,axis,scale)
+
+ if reverse:
+ tail_vec = v * self.obj.matrix_world
+ eb.head[:] = eb.tail
+ eb.tail[:] = eb.head + tail_vec
+ else:
+ tail_vec = v * self.obj.matrix_world
+ eb.tail[:] = eb.head + tail_vec
+
+
+ def create_pivot( self, pivot ):
+ """ Create the pivot control and mechanism bones """
+ org_bones = self.org_bones
+ pivot_name = org_bones[pivot-1]
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create torso control bone
+ torso_name = 'torso'
+ ctrl_name = copy_bone(self.obj, pivot_name, torso_name)
+ ctrl_eb = eb[ ctrl_name ]
+
+ self.orient_bone( ctrl_eb, 'y', self.spine_length / 2.5 )
+
+ # Create mch_pivot
+ mch_name = make_mechanism_name( 'pivot' )
+ mch_name = copy_bone(self.obj, ctrl_name, mch_name)
+ mch_eb = eb[ mch_name ]
+
+ mch_eb.length /= 4
+
+ # Positioning pivot in a more usable location for animators
+ if hasattr(self,'tail_pos') and self.tail_pos > 0:
+ pivot_loc = eb[ org_bones[pivot-1]].head
+ else:
+ pivot_loc = ( eb[ org_bones[0]].head + eb[ org_bones[0]].tail ) / 2
+
+ put_bone( self.obj, ctrl_name, pivot_loc )
+
+ return {
+ 'ctrl' : ctrl_name,
+ 'mch' : mch_name
+ }
+
+
+ def create_deform( self ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ def_bones = []
+ for org in org_bones:
+ def_name = make_deformer_name( strip_org( org ) )
+ def_name = copy_bone( self.obj, org, def_name )
+ def_bones.append( def_name )
+
+ return def_bones
+
+
+ def create_neck( self, neck_bones ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create neck control
+ neck = copy_bone( self.obj, org(neck_bones[0]), 'neck' )
+ neck_eb = eb[ neck ]
+
+ # Neck spans all neck bones (except head)
+ neck_eb.tail[:] = eb[ org(neck_bones[-1]) ].head
+
+ # Create head control
+ head = copy_bone( self.obj, org(neck_bones[-1]), 'head' )
+
+ # MCH bones
+ # Neck MCH stretch
+ mch_str = copy_bone( self.obj, neck, make_mechanism_name('STR-neck') )
+
+ # Neck MCH rotation
+ mch_neck = copy_bone(
+ self.obj, neck, make_mechanism_name('ROT-neck')
+ )
+
+ self.orient_bone( eb[mch_neck], 'y', self.spine_length / 10 )
+
+ # Head MCH rotation
+ mch_head = copy_bone(
+ self.obj, head, make_mechanism_name('ROT-head')
+ )
+
+ self.orient_bone( eb[mch_head], 'y', self.spine_length / 10 )
+
+ twk,mch = [],[]
+
+ # Intermediary bones
+ for b in neck_bones[1:-1]: # All except 1st neck and (last) head
+ mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
+ eb[mch_name].length /= 4
+
+ mch += [ mch_name ]
+
+ # Tweak bones
+ for b in neck_bones[:-1]: # All except last bone
+ twk_name = "tweak_" + b
+ twk_name = copy_bone( self.obj, org(b), twk_name )
+
+ eb[twk_name].length /= 2
+
+ twk += [ twk_name ]
+
+ return {
+ 'ctrl_neck' : neck,
+ 'ctrl' : head,
+ 'mch_str' : mch_str,
+ 'mch_neck' : mch_neck,
+ 'mch_head' : mch_head,
+ 'mch' : mch,
+ 'tweak' : twk
+ }
+
+
+ def create_chest( self, chest_bones ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # get total spine length
+
+ # Create chest control bone
+ chest = copy_bone( self.obj, org( chest_bones[0] ), 'chest' )
+ self.orient_bone( eb[chest], 'y', self.spine_length / 3 )
+
+ # create chest mch_wgt
+ mch_wgt = copy_bone(
+ self.obj, org( chest_bones[-1] ),
+ make_mechanism_name( 'WGT-chest' )
+ )
+
+ # Create mch and twk bones
+ twk,mch = [],[]
+
+ for b in chest_bones:
+ mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
+ self.orient_bone( eb[mch_name], 'y', self.spine_length / 10 )
+
+ twk_name = "tweak_" + b
+ twk_name = copy_bone( self.obj, org(b), twk_name )
+ eb[twk_name].length /= 2
+
+ mch += [ mch_name ]
+ twk += [ twk_name ]
+
+ return {
+ 'ctrl' : chest,
+ 'mch' : mch,
+ 'tweak' : twk,
+ 'mch_wgt' : mch_wgt
+ }
+
+
+ def create_hips( self, hip_bones ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create hips control bone
+ hips = copy_bone( self.obj, org( hip_bones[-1] ), 'hips' )
+ self.orient_bone(
+ eb[hips],
+ 'y',
+ self.spine_length / 4,
+ reverse = True
+ )
+
+ # create hips mch_wgt
+ mch_wgt = copy_bone(
+ self.obj, org( hip_bones[0] ),
+ make_mechanism_name( 'WGT-hips' )
+ )
+
+ # Create mch and tweak bones
+ twk,mch = [],[]
+ for b in hip_bones:
+ mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
+ self.orient_bone(
+ eb[mch_name], 'y', self.spine_length / 10, reverse = True
+ )
+
+ twk_name = "tweak_" + b
+ twk_name = copy_bone( self.obj, org( b ), twk_name )
+
+ eb[twk_name].length /= 2
+
+ mch += [ mch_name ]
+ twk += [ twk_name ]
+
+ return {
+ 'ctrl' : hips,
+ 'mch' : mch,
+ 'tweak' : twk,
+ 'mch_wgt' : mch_wgt
+ }
+
+
+ def create_tail( self, tail_bones ):
+ pass
+
+
+ def parent_bones( self, bones ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Parent deform bones
+ for i,b in enumerate( bones['def'] ):
+ if i > 0: # For all bones but the first (which has no parent)
+ eb[b].parent = eb[ bones['def'][i-1] ] # to previous
+ eb[b].use_connect = True
+
+ # Parent control bones
+ # Head control => MCH-rotation_head
+ eb[ bones['neck']['ctrl'] ].parent = eb[ bones['neck']['mch_head'] ]
+
+ # MCH stretch => neck ctrl
+ eb[ bones['neck']['mch_str'] ].parent = eb[ bones['neck']['ctrl_neck'] ]
+
+ # Neck control => MCH-rotation_neck
+ eb[ bones['neck']['ctrl_neck'] ].parent = eb[ bones['neck']['mch_neck'] ]
+
+ # Parent hips and chest controls to torso
+ eb[ bones['chest']['ctrl'] ].parent = eb[ bones['pivot']['ctrl'] ]
+ eb[ bones['hips']['ctrl'] ].parent = eb[ bones['pivot']['ctrl'] ]
+
+ # Parent mch bones
+ # Neck mch
+ eb[ bones['neck']['mch_head'] ].parent = eb[ bones['neck']['ctrl_neck'] ]
+
+ parent = eb[ bones['neck']['mch_str'] ]
+ for i,b in enumerate([ eb[n] for n in bones['neck']['mch'] ]):
+ b.parent = parent
+
+ # Chest mch bones and neck mch
+ chest_mch = bones['chest']['mch'] + [ bones['neck']['mch_neck'] ]
+ for i,b in enumerate(chest_mch):
+ if i == 0:
+ eb[b].parent = eb[ bones['pivot']['ctrl'] ]
+ else:
+ eb[b].parent = eb[ chest_mch[i-1] ]
+
+ # Hips mch bones
+ for i,b in enumerate( bones['hips']['mch'] ):
+ if i == len(bones['hips']['mch']) - 1:
+ eb[b].parent = eb[ bones['pivot']['ctrl'] ]
+ else:
+ eb[b].parent = eb[ bones['hips']['mch'][i+1] ]
+
+ # mch pivot
+ eb[ bones['pivot']['mch'] ].parent = eb[ bones['chest']['mch'][0] ]
+
+ # MCH widgets
+ eb[ bones['chest']['mch_wgt'] ].parent = eb[ bones['chest']['mch'][-1] ]
+ eb[ bones['hips' ]['mch_wgt'] ].parent = eb[ bones['hips' ]['mch'][0 ] ]
+
+ # Tweaks
+
+ # Neck tweaks
+ for i,twk in enumerate( bones['neck']['tweak'] ):
+ if i == 0:
+ eb[ twk ].parent = eb[ bones['neck']['ctrl_neck'] ]
+ else:
+ eb[ twk ].parent = eb[ bones['neck']['mch'][i-1] ]
+
+ # Chest tweaks
+ for twk,mch in zip( bones['chest']['tweak'], bones['chest']['mch'] ):
+ if bones['chest']['tweak'].index( twk ) == 0:
+ eb[ twk ].parent = eb[ bones['pivot']['mch'] ]
+ else:
+ eb[ twk ].parent = eb[ mch ]
+
+ # Hips tweaks
+ for i,twk in enumerate(bones['hips']['tweak']):
+ if i == 0:
+ eb[twk].parent = eb[ bones['hips']['mch'][i] ]
+ else:
+ eb[twk].parent = eb[ bones['hips']['mch'][i-1] ]
+
+ # Parent orgs to matching tweaks
+ tweaks = bones['hips']['tweak'] + bones['chest']['tweak']
+ tweaks += bones['neck']['tweak'] + [ bones['neck']['ctrl'] ]
+
+ if 'tail' in bones.keys():
+ tweaks += bones['tail']['tweak']
+
+ for org, twk in zip( org_bones, tweaks ):
+ eb[ org ].parent = eb[ twk ]
+
+
+ def make_constraint( self, bone, constraint ):
+ bpy.ops.object.mode_set(mode = 'OBJECT')
+ pb = self.obj.pose.bones
+
+ owner_pb = pb[bone]
+ const = owner_pb.constraints.new( constraint['constraint'] )
+ const.target = self.obj
+
+ # filter contraint props to those that actually exist in the currnet
+ # type of constraint, then assign values to each
+ for p in [ k for k in constraint.keys() if k in dir(const) ]:
+ setattr( const, p, constraint[p] )
+
+
+ def constrain_bones( self, bones ):
+ # MCH bones
+
+ # head and neck MCH bones
+ for b in [ bones['neck']['mch_head'], bones['neck']['mch_neck'] ]:
+ self.make_constraint( b, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : bones['pivot']['ctrl'],
+ } )
+ self.make_constraint( b, {
+ 'constraint' : 'COPY_SCALE',
+ 'subtarget' : bones['pivot']['ctrl'],
+ } )
+
+ # Neck MCH Stretch
+ self.make_constraint( bones['neck']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : bones['neck']['ctrl'],
+ })
+
+ self.make_constraint( bones['neck']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : bones['neck']['ctrl'],
+ })
+
+ # Intermediary mch bones
+ intermediaries = [ bones['neck'], bones['chest'], bones['hips'] ]
+
+ if 'tail' in bones.keys():
+ intermediaries += bones['tail']
+
+ for i,l in enumerate(intermediaries):
+ mch = l['mch']
+ factor = float( 1 / len( l['tweak'] ) )
+
+ for j,b in enumerate(mch):
+ if i == 0:
+ nfactor = float( (j + 1) / len( mch ) )
+ self.make_constraint( b, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : l['ctrl'],
+ 'influence' : nfactor
+ } )
+ else:
+ self.make_constraint( b, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : l['ctrl'],
+ 'influence' : factor,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ } )
+
+
+ # MCH pivot
+ self.make_constraint( bones['pivot']['mch'], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : bones['hips']['mch'][-1],
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+
+ # DEF bones
+ deform = bones['def']
+ tweaks = bones['hips']['tweak'] + bones['chest']['tweak']
+ tweaks += bones['neck']['tweak'] + [ bones['neck']['ctrl'] ]
+
+ for d,t in zip(deform, tweaks):
+ tidx = tweaks.index(t)
+
+ self.make_constraint( d, {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : t
+ })
+
+ if tidx != len(tweaks) - 1:
+ self.make_constraint( d, {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : tweaks[ tidx + 1 ],
+ })
+
+ self.make_constraint( d, {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : tweaks[ tidx + 1 ],
+ })
+
+ pb = self.obj.pose.bones
+
+ for t in tweaks:
+ if t != bones['neck']['ctrl']:
+ pb[t].rotation_mode = 'ZXY'
+
+
+ def create_drivers( self, bones ):
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ # Setting the torso's props
+ torso = pb[ bones['pivot']['ctrl'] ]
+
+ props = [ "head_follow", "neck_follow" ]
+ owners = [ bones['neck']['mch_head'], bones['neck']['mch_neck'] ]
+
+ for prop in props:
+ if prop == 'neck_follow':
+ torso[prop] = 0.5
+ else:
+ torso[prop] = 0.0
+
+ prop = rna_idprop_ui_prop_get( torso, prop, create=True )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = prop
+
+ # driving the follow rotation switches for neck and head
+ for bone, prop, in zip( owners, props ):
+ # Add driver to copy rotation constraint
+ drv = pb[ bone ].constraints[ 0 ].driver_add("influence").driver
+ drv.type = 'AVERAGE'
+
+ var = drv.variables.new()
+ var.name = prop
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = \
+ torso.path_from_id() + '['+ '"' + prop + '"' + ']'
+
+ drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
+
+ drv_modifier.mode = 'POLYNOMIAL'
+ drv_modifier.poly_order = 1
+ drv_modifier.coefficients[0] = 1.0
+ drv_modifier.coefficients[1] = -1.0
+
+
+ def locks_and_widgets( self, bones ):
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ # deform bones bbone segements
+ for bone in bones['def'][:-1]:
+ self.obj.data.bones[bone].bbone_segments = 8
+
+ self.obj.data.bones[ bones['def'][0] ].bbone_in = 0.0
+ self.obj.data.bones[ bones['def'][-2] ].bbone_out = 0.0
+
+ # Locks
+ tweaks = bones['neck']['tweak'] + bones['chest']['tweak']
+ tweaks += bones['hips']['tweak']
+
+ if 'tail' in bones.keys():
+ tweaks += bones['tail']['tweak']
+
+ # Tweak bones locks
+ for bone in tweaks:
+ pb[bone].lock_rotation = True, False, True
+ pb[bone].lock_scale = False, True, False
+
+ # Widgets
+
+ # Assigning a widget to torso bone
+ create_cube_widget(
+ self.obj,
+ bones['pivot']['ctrl'],
+ radius = 0.5,
+ bone_transform_name = None
+ )
+
+ # Assigning widgets to control bones
+ gen_ctrls = [
+ bones['neck']['ctrl_neck'],
+ bones['chest']['ctrl'],
+ bones['hips']['ctrl']
+ ]
+
+ if 'tail' in bones.keys():
+ gen_ctrls += [ bones['tail']['ctrl'] ]
+
+ for bone in gen_ctrls:
+ create_circle_widget(
+ self.obj,
+ bone,
+ radius = 1.0,
+ head_tail = 0.5,
+ with_line = False,
+ bone_transform_name = None
+ )
+
+ # Head widget
+ create_circle_widget(
+ self.obj,
+ bones['neck']['ctrl'],
+ radius = 0.75,
+ head_tail = 1.0,
+ with_line = False,
+ bone_transform_name = None
+ )
+
+ # place widgets on correct bones
+ chest_widget_loc = pb[ bones['chest']['mch_wgt'] ]
+ pb[ bones['chest']['ctrl'] ].custom_shape_transform = chest_widget_loc
+
+ hips_widget_loc = pb[ bones['hips']['mch_wgt'] ]
+ if 'tail' in bones.keys():
+ hips_widget_loc = bones['def'][self.tail_pos -1]
+
+ pb[ bones['hips']['ctrl'] ].custom_shape_transform = hips_widget_loc
+
+ # Assigning widgets to tweak bones and layers
+ for bone in tweaks:
+ create_sphere_widget(self.obj, bone, bone_transform_name=None)
+
+ if self.tweak_layers:
+ pb[bone].bone.layers = self.tweak_layers
+
+
+ def generate( self ):
+
+ # Torso Rig Anatomy:
+ # Neck: all bones above neck point, last bone is head
+ # Upper torso: all bones between pivot and neck start
+ # Lower torso: all bones below pivot until tail point
+ # Tail: all bones below tail point
+
+ bone_chains = self.build_bone_structure()
+
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Clear parents for org bones
+ for bone in self.org_bones:
+ eb[bone].use_connect = False
+ eb[bone].parent = None
+
+ if bone_chains != 'ERROR':
+
+ # Create lists of bones and strip "ORG" from their names
+ neck_bones = [ strip_org(b) for b in bone_chains['neck' ] ]
+ upper_torso_bones = [ strip_org(b) for b in bone_chains['upper'] ]
+ lower_torso_bones = [ strip_org(b) for b in bone_chains['lower'] ]
+ tail_bones = [ strip_org(b) for b in bone_chains['tail' ] ]
+
+ bones = {}
+
+ bones['def'] = self.create_deform() # Gets org bones from self
+ bones['pivot'] = self.create_pivot( self.pivot_pos )
+ bones['neck'] = self.create_neck( neck_bones )
+ bones['chest'] = self.create_chest( upper_torso_bones )
+ bones['hips'] = self.create_hips( lower_torso_bones )
+ # TODO: Add create tail
+
+ if tail_bones:
+ bones['tail'] = self.create_tail( tail_bones )
+
+ # TEST
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ self.parent_bones( bones )
+ self.constrain_bones( bones )
+ self.create_drivers( bones )
+ self.locks_and_widgets( bones )
+
+
+ controls = [ bones['neck']['ctrl'], bones['neck']['ctrl_neck'] ]
+ controls += [ bones['chest']['ctrl'], bones['hips']['ctrl'] ]
+ controls += [ bones['pivot']['ctrl'] ]
+
+ if 'tail' in bones.keys():
+ controls += [ bones['tail']['ctrl'] ]
+
+ # Create UI
+ controls_string = ", ".join(["'" + x + "'" for x in controls])
+ return [script % (
+ controls_string,
+ bones['pivot']['ctrl'],
+ 'head_follow',
+ 'neck_follow'
+ )]
+
+def add_parameters( params ):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.neck_pos = bpy.props.IntProperty(
+ name = 'neck_position',
+ default = 6,
+ min = 0,
+ description = 'Neck start position'
+ )
+
+ params.pivot_pos = bpy.props.IntProperty(
+ name = 'pivot_position',
+ default = 3,
+ min = 0,
+ description = 'Position of the torso control and pivot point'
+ )
+
+ params.tail_pos = bpy.props.IntProperty(
+ name = 'tail_position',
+ default = 0,
+ min = 0,
+ description = 'Where the tail starts (change from 0 to enable)'
+ )
+
+ # Setting up extra layers for the FK and tweak
+ params.tweak_extra_layers = bpy.props.BoolProperty(
+ name = "tweak_extra_layers",
+ default = True,
+ description = ""
+ )
+
+ params.tweak_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters."""
+
+ r = layout.row()
+ r.prop(params, "neck_pos")
+
+ r = layout.row()
+ r.prop(params, "pivot_pos")
+
+ r = layout.row()
+ r.prop(params, "tail_pos")
+
+ r = layout.row()
+ r.prop(params, "tweak_extra_layers")
+ r.active = params.tweak_extra_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range(8):
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range(16,24):
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range(8,16):
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range(24,32):
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = 0.0000, 0.0552, 1.0099
+ bone.tail[:] = 0.0000, 0.0172, 1.1573
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['spine'] = bone.name
+
+ bone = arm.edit_bones.new('spine.001')
+ bone.head[:] = 0.0000, 0.0172, 1.1573
+ bone.tail[:] = 0.0000, 0.0004, 1.2929
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['spine.001'] = bone.name
+
+ bone = arm.edit_bones.new('spine.002')
+ bone.head[:] = 0.0000, 0.0004, 1.2929
+ bone.tail[:] = 0.0000, 0.0059, 1.4657
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.001']]
+ bones['spine.002'] = bone.name
+
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = 0.0000, 0.0059, 1.4657
+ bone.tail[:] = 0.0000, 0.0114, 1.6582
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.002']]
+ bones['spine.003'] = bone.name
+
+ bone = arm.edit_bones.new('spine.004')
+ bone.head[:] = 0.0000, 0.0114, 1.6582
+ bone.tail[:] = 0.0000, -0.0067, 1.7197
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.003']]
+ bones['spine.004'] = bone.name
+
+ bone = arm.edit_bones.new('spine.005')
+ bone.head[:] = 0.0000, -0.0067, 1.7197
+ bone.tail[:] = 0.0000, -0.0247, 1.7813
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.004']]
+ bones['spine.005'] = bone.name
+
+ bone = arm.edit_bones.new('spine.006')
+ bone.head[:] = 0.0000, -0.0247, 1.7813
+ bone.tail[:] = 0.0000, -0.0247, 1.9796
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.005']]
+ bones['spine.006'] = bone.name
+
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = 'pitchipoy.super_torso_turbo'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ try:
+ pbone.rigify_parameters.chain_bone_controls = "1, 2, 3"
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.neck_pos = 5
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [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, False]
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['spine.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine.004']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine.005']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine.006']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/pitchipoy/super_widgets.py b/rigify/legacy/rigs/pitchipoy/super_widgets.py
new file mode 100644
index 00000000..aee6c14e
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/super_widgets.py
@@ -0,0 +1,164 @@
+import bpy
+import importlib
+import importlib
+from ...utils import create_widget
+
+WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer.
+MODULE_NAME = "super_widgets" # Windows/Mac blender is weird, so __package__ doesn't work
+
+
+def create_eye_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(1.1920928955078125e-07*size, 0.5000000596046448*size, 0.0*size), (-0.12940943241119385*size, 0.482962965965271*size, 0.0*size), (-0.24999988079071045*size, 0.4330127537250519*size, 0.0*size), (-0.35355329513549805*size, 0.35355344414711*size, 0.0*size), (-0.43301260471343994*size, 0.2500000596046448*size, 0.0*size), (-0.4829627275466919*size, 0.12940959632396698*size, 0.0*size), (-0.49999988079071045*size, 1.0094120739267964e-07*size, 0.0*size), (-0.482962965965271*size, -0.12940940260887146*size, 0.0*size), (-0.43301260471343994*size, -0.24999986588954926*size, 0.0*size), (-0.3535534143447876*size, -0.35355323553085327*size, 0.0*size), (-0.25*size, -0.43301257491111755*size, 0.0*size), (-0.1294095516204834*size, -0.48296281695365906*size, 0.0*size), (-1.1920928955078125e-07*size, -0.4999999403953552*size, 0.0*size), (0.12940943241119385*size, -0.4829629063606262*size, 0.0*size), (0.24999988079071045*size, -0.4330127537250519*size, 0.0*size), (0.35355329513549805*size, -0.35355353355407715*size, 0.0*size), (0.4330127239227295*size, -0.25000008940696716*size, 0.0*size), (0.482962965965271*size, -0.12940965592861176*size, 0.0*size), (0.5000001192092896*size, -1.6926388468618825e-07*size, 0.0*size), (0.48296308517456055*size, 0.1294093281030655*size, 0.0*size), (0.4330129623413086*size, 0.24999980628490448*size, 0.0*size), (0.35355377197265625*size, 0.35355323553085327*size, 0.0*size), (0.25000035762786865*size, 0.43301260471343994*size, 0.0*size), (0.1294100284576416*size, 0.48296287655830383*size, 0.0*size), ]
+ edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_eyes_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(0.8928930759429932*size, -0.7071065902709961*size, 0.0*size), (0.8928932547569275*size, 0.7071067690849304*size, 0.0*size), (-1.8588197231292725*size, -0.9659252762794495*size, 0.0*size), (-2.100001096725464*size, -0.8660248517990112*size, 0.0*size), (-2.3071072101593018*size, -0.7071059942245483*size, 0.0*size), (-2.4660258293151855*size, -0.49999913573265076*size, 0.0*size), (-2.5659260749816895*size, -0.258818119764328*size, 0.0*size), (-2.5999999046325684*size, 8.575012770961621e-07*size, 0.0*size), (-2.5659255981445312*size, 0.2588198482990265*size, 0.0*size), (-2.4660253524780273*size, 0.5000006556510925*size, 0.0*size), (-2.3071064949035645*size, 0.7071075439453125*size, 0.0*size), (-2.099999189376831*size, 0.866025984287262*size, 0.0*size), (-1.8588184118270874*size, 0.9659261703491211*size, 0.0*size), (-1.5999996662139893*size, 1.000000238418579*size, 0.0*size), (-1.341180443763733*size, 0.9659258723258972*size, 0.0*size), (-1.0999995470046997*size, 0.8660253882408142*size, 0.0*size), (-0.8928929567337036*size, 0.7071067094802856*size, 0.0*size), (-0.892893373966217*size, -0.7071066498756409*size, 0.0*size), (-1.100000262260437*size, -0.8660252690315247*size, 0.0*size), (-1.3411810398101807*size, -0.9659255743026733*size, 0.0*size), (1.600000023841858*size, 1.0*size, 0.0*size), (1.3411810398101807*size, 0.9659258127212524*size, 0.0*size), (1.100000023841858*size, 0.8660253882408142*size, 0.0*size), (-1.600000262260437*size, -0.9999997615814209*size, 0.0*size), (1.0999997854232788*size, -0.8660252690315247*size, 0.0*size), (1.341180682182312*size, -0.9659257531166077*size, 0.0*size), (1.5999996662139893*size, -1.0*size, 0.0*size), (1.8588186502456665*size, -0.965925931930542*size, 0.0*size), (2.0999996662139893*size, -0.8660256266593933*size, 0.0*size), (2.3071064949035645*size, -0.7071071863174438*size, 0.0*size), (2.4660253524780273*size, -0.5000002980232239*size, 0.0*size), (2.5659255981445312*size, -0.25881943106651306*size, 0.0*size), (2.5999999046325684*size, -4.649122899991198e-07*size, 0.0*size), (2.5659260749816895*size, 0.25881853699684143*size, 0.0*size), (2.4660258293151855*size, 0.4999994933605194*size, 0.0*size), (2.3071072101593018*size, 0.707106351852417*size, 0.0*size), (2.1000006198883057*size, 0.8660250902175903*size, 0.0*size), (1.8588197231292725*size, 0.9659256339073181*size, 0.0*size), (-1.8070557117462158*size, -0.7727401852607727*size, 0.0*size), (-2.0000009536743164*size, -0.6928198337554932*size, 0.0*size), (-2.1656856536865234*size, -0.5656847357749939*size, 0.0*size), (-2.292820692062378*size, -0.3999992609024048*size, 0.0*size), (-2.3727407455444336*size, -0.20705445110797882*size, 0.0*size), (-2.3999998569488525*size, 7.336847716032935e-07*size, 0.0*size), (-2.3727405071258545*size, 0.207055926322937*size, 0.0*size), (-2.2928202152252197*size, 0.40000057220458984*size, 0.0*size), (-2.1656851768493652*size, 0.5656861066818237*size, 0.0*size), (-1.9999992847442627*size, 0.6928208470344543*size, 0.0*size), (-1.8070547580718994*size, 0.7727410197257996*size, 0.0*size), (-1.5999996662139893*size, 0.8000002503395081*size, 0.0*size), (-1.3929443359375*size, 0.7727407813072205*size, 0.0*size), (-1.1999995708465576*size, 0.6928203701972961*size, 0.0*size), (-1.0343143939971924*size, 0.5656854510307312*size, 0.0*size), (-1.0343146324157715*size, -0.5656852722167969*size, 0.0*size), (-1.2000001668930054*size, -0.6928201913833618*size, 0.0*size), (-1.3929448127746582*size, -0.7727404236793518*size, 0.0*size), (-1.6000001430511475*size, -0.7999997735023499*size, 0.0*size), (1.8070557117462158*size, 0.772739827632904*size, 0.0*size), (2.0000009536743164*size, 0.6928195953369141*size, 0.0*size), (2.1656856536865234*size, 0.5656843781471252*size, 0.0*size), (2.292820692062378*size, 0.39999890327453613*size, 0.0*size), (2.3727407455444336*size, 0.20705409348011017*size, 0.0*size), (2.3999998569488525*size, -1.0960745839838637e-06*size, 0.0*size), (2.3727405071258545*size, -0.20705628395080566*size, 0.0*size), (2.2928202152252197*size, -0.4000009298324585*size, 0.0*size), (2.1656851768493652*size, -0.5656863451004028*size, 0.0*size), (1.9999992847442627*size, -0.692821204662323*size, 0.0*size), (1.8070547580718994*size, -0.7727413773536682*size, 0.0*size), (1.5999996662139893*size, -0.8000004887580872*size, 0.0*size), (1.3929443359375*size, -0.7727410197257996*size, 0.0*size), (1.1999995708465576*size, -0.6928204894065857*size, 0.0*size), (1.0343143939971924*size, -0.5656855702400208*size, 0.0*size), (1.0343146324157715*size, 0.5656850337982178*size, 0.0*size), (1.2000004053115845*size, 0.6928199529647827*size, 0.0*size), (1.3929448127746582*size, 0.7727401852607727*size, 0.0*size), (1.6000001430511475*size, 0.7999995350837708*size, 0.0*size), ]
+ edges = [(24, 0), (1, 22), (16, 1), (17, 0), (23, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (21, 20), (22, 21), (13, 14), (14, 15), (15, 16), (17, 18), (18, 19), (19, 23), (25, 24), (26, 25), (27, 26), (28, 27), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (20, 37), (56, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), (49, 50), (50, 51), (51, 52), (53, 54), (54, 55), (55, 56), (75, 57), (57, 58), (58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66), (66, 67), (67, 68), (68, 69), (69, 70), (70, 71), (72, 73), (73, 74), (74, 75), (52, 72), (53, 71), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_ear_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(-2.4903741291382175e-09*size, 1.0*size, -3.123863123732917e-08*size), (-7.450580596923828e-09*size, 0.9829629063606262*size, 0.0776456817984581*size), (-1.4901161193847656e-08*size, 0.9330127239227295*size, 0.1499999761581421*size), (-2.9802322387695312e-08*size, 0.8535534143447876*size, 0.2121320217847824*size), (-2.9802322387695312e-08*size, 0.75*size, 0.25980761647224426*size), (-2.9802322387695312e-08*size, 0.6294095516204834*size, 0.2897777259349823*size), (-2.9802322387695312e-08*size, 0.5000000596046448*size, 0.29999998211860657*size), (-5.960464477539063e-08*size, 0.37059056758880615*size, 0.2897777855396271*size), (-5.960464477539063e-08*size, 0.25000008940696716*size, 0.25980767607688904*size), (-4.470348358154297e-08*size, 0.14644670486450195*size, 0.21213211119174957*size), (-4.470348358154297e-08*size, 0.06698736548423767*size, 0.15000009536743164*size), (-4.470348358154297e-08*size, 0.017037123441696167*size, 0.07764581590890884*size), (-3.6718930118695425e-08*size, 0.0*size, 1.1981423142515268e-07*size), (-2.9802322387695312e-08*size, 0.017037034034729004*size, -0.07764559239149094*size), (-2.9802322387695312e-08*size, 0.06698718667030334*size, -0.14999987185001373*size), (-1.4901161193847656e-08*size, 0.14644640684127808*size, -0.21213191747665405*size), (0.0*size, 0.24999985098838806*size, -0.25980761647224426*size), (0.0*size, 0.3705902695655823*size, -0.2897777259349823*size), (0.0*size, 0.4999997615814209*size, -0.30000004172325134*size), (0.0*size, 0.6294092535972595*size, -0.2897777855396271*size), (0.0*size, 0.7499997615814209*size, -0.2598077356815338*size), (1.4901161193847656e-08*size, 0.8535531759262085*size, -0.21213220059871674*size), (0.0*size, 0.9330125451087952*size, -0.15000019967556*size), (0.0*size, 0.9829628467559814*size, -0.07764596492052078*size), ]
+ edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_jaw_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size), (0.0*size, 1.153113603591919*size, 0.0*size), (-0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (-0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.0*size, 1.153113603591919*size, 0.18649044632911682*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (-0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size), ]
+ edges = [(1, 0), (2, 1), (3, 2), (4, 3), (9, 4), (6, 5), (7, 6), (8, 7), (15, 8), (5, 0), (11, 10), (12, 11), (13, 12), (14, 13), (9, 14), (17, 16), (18, 17), (19, 18), (15, 19), (16, 10), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_teeth_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(0.6314387321472168*size, 0.4999997019767761*size, 0.09999999403953552*size), (0.5394065976142883*size, 0.29289281368255615*size, 0.09999999403953552*size), (0.3887903690338135*size, 0.1339743733406067*size, 0.09999999403953552*size), (0.19801488518714905*size, 0.03407406806945801*size, 0.09999999403953552*size), (-3.4034394502668874e-07*size, 0.0*size, 0.09999999403953552*size), (-0.19801555573940277*size, 0.034074246883392334*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, -0.10000000894069672*size), (-0.6778771877288818*size, 0.7411810755729675*size, -0.10000000894069672*size), (-0.6314389705657959*size, 0.5000001192092896*size, -0.10000000894069672*size), (-0.5394070148468018*size, 0.2928934097290039*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, -0.10000000894069672*size), (-0.19801555573940277*size, 0.034074246883392334*size, -0.10000000894069672*size), (-3.4034394502668874e-07*size, 0.0*size, -0.10000000894069672*size), (0.19801488518714905*size, 0.03407406806945801*size, -0.10000000894069672*size), (0.3887903690338135*size, 0.1339743733406067*size, -0.10000000894069672*size), (0.5394065976142883*size, 0.29289281368255615*size, -0.10000000894069672*size), (0.6314387321472168*size, 0.4999997019767761*size, -0.10000000894069672*size), (0.6778769493103027*size, 0.7411805391311646*size, -0.10000000894069672*size), (0.6999999284744263*size, 0.9999995231628418*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, 0.09999999403953552*size), (-0.5394070148468018*size, 0.2928934097290039*size, 0.09999999403953552*size), (-0.6314389705657959*size, 0.5000001192092896*size, 0.09999999403953552*size), (-0.6778771877288818*size, 0.7411810755729675*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, 0.09999999403953552*size), (0.6778769493103027*size, 0.7411805391311646*size, 0.09999999403953552*size), (0.6999999284744263*size, 0.9999995231628418*size, 0.09999999403953552*size), ]
+ edges = [(25, 24), (24, 0), (0, 1), (1, 2), (2, 3), (3, 4), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (4, 5), (5, 19), (19, 20), (20, 21), (21, 22), (22, 23), (18, 25), (6, 23), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+def create_face_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(-0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, -0.25*size, -0.07499998807907104*size), (-0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, -0.25*size, -0.07499998807907104*size), ]
+ edges = [(4, 5), (5, 1), (1, 0), (0, 4), (5, 6), (6, 2), (2, 1), (6, 7), (7, 3), (3, 2), (7, 4), (0, 3), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.0*size, 1.0*size, -0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), (0.0*size, 1.0*size, 0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), ]
+ edges = [(0, 1), (2, 3), (1, 4), (4, 5), (3, 6), (5, 6), (0, 2), (7, 8), (9, 10), (8, 11), (11, 12), (10, 13), (12, 13), (7, 9), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
+def create_hand_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ # Create hand widget
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(0.0*size, 1.5*size, -0.7000000476837158*size), (1.1920928955078125e-07*size, -0.25*size, -0.6999999284744263*size), (0.0*size, -0.25*size, 0.7000000476837158*size), (-1.1920928955078125e-07*size, 1.5*size, 0.6999999284744263*size), (5.960464477539063e-08*size, 0.7229999899864197*size, -0.699999988079071*size), (-5.960464477539063e-08*size, 0.7229999899864197*size, 0.699999988079071*size), (1.1920928955078125e-07*size, -2.9802322387695312e-08*size, -0.699999988079071*size), (0.0*size, 2.9802322387695312e-08*size, 0.699999988079071*size), ]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+
+ mod = obj.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+ return obj
+ else:
+ return None
+
+def create_foot_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ # Create hand widget
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(-0.6999998688697815*size, -0.5242648720741272*size, 0.0*size), (-0.7000001072883606*size, 1.2257349491119385*size, 0.0*size), (0.6999998688697815*size, 1.2257351875305176*size, 0.0*size), (0.7000001072883606*size, -0.5242648720741272*size, 0.0*size), (-0.6999998688697815*size, 0.2527350187301636*size, 0.0*size), (0.7000001072883606*size, 0.2527352571487427*size, 0.0*size), (-0.7000001072883606*size, 0.975735068321228*size, 0.0*size), (0.6999998688697815*size, 0.9757352471351624*size, 0.0*size), ]
+ edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+
+ mod = obj.modifiers.new("subsurf", 'SUBSURF')
+ mod.levels = 2
+ return obj
+ else:
+ return None
+
+def create_ballsocket_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [(-0.050000108778476715*size, 0.779460072517395*size, -0.2224801927804947*size), (0.049999915063381195*size, 0.779460072517395*size, -0.22248023748397827*size), (0.09999985247850418*size, 0.6790841817855835*size, -0.3658318817615509*size), (-2.3089636158601934e-07*size, 0.5930476188659668*size, -0.488704651594162*size), (-0.10000013560056686*size, 0.6790841817855835*size, -0.3658317029476166*size), (0.04999981075525284*size, 0.6790841817855835*size, -0.36583182215690613*size), (-0.050000183284282684*size, 0.6790841817855835*size, -0.3658318519592285*size), (-0.3658319115638733*size, 0.6790841221809387*size, 0.05000019446015358*size), (-0.3658318817615509*size, 0.6790841221809387*size, -0.04999979957938194*size), (-0.36583176255226135*size, 0.6790841221809387*size, 0.10000018030405045*size), (-0.48870471119880676*size, 0.5930476188659668*size, 2.4472291215715813e-07*size), (-0.3658319413661957*size, 0.679084062576294*size, -0.0999998077750206*size), (-0.22248037159442902*size, 0.7794600129127502*size, -0.04999985918402672*size), (-0.22248034179210663*size, 0.7794600129127502*size, 0.05000016465783119*size), (0.3658319115638733*size, 0.6790841221809387*size, -0.05000000819563866*size), (0.3658319115638733*size, 0.6790841221809387*size, 0.05000000074505806*size), (0.36583179235458374*size, 0.6790841221809387*size, -0.09999998658895493*size), (0.4887046813964844*size, 0.5930476188659668*size, -3.8399143420519977e-08*size), (0.3658319413661957*size, 0.679084062576294*size, 0.10000000149011612*size), (0.050000034272670746*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.04999997466802597*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.09999992698431015*size, 0.679084062576294*size, 0.36583200097084045*size), (1.267315070663244e-07*size, 0.5930474996566772*size, 0.48870477080345154*size), (0.1000000610947609*size, 0.679084062576294*size, 0.3658318519592285*size), (-0.049999915063381195*size, 0.679084062576294*size, 0.3658319413661957*size), (0.05000007897615433*size, 0.679084062576294*size, 0.36583197116851807*size), (0.22248029708862305*size, 0.7794600129127502*size, 0.05000004544854164*size), (0.22248028218746185*size, 0.7794600129127502*size, -0.04999994859099388*size), (-4.752442350763886e-08*size, 0.8284152746200562*size, -0.1499999612569809*size), (-0.03882290795445442*size, 0.8284152746200562*size, -0.14488883316516876*size), (-0.07500004768371582*size, 0.8284152746200562*size, -0.12990377843379974*size), (-0.10606606304645538*size, 0.8284152746200562*size, -0.10606598109006882*size), (-0.1299038827419281*size, 0.8284152746200562*size, -0.07499996572732925*size), (-0.14488893747329712*size, 0.8284152746200562*size, -0.038822825998067856*size), (-0.15000006556510925*size, 0.8284152746200562*size, 2.4781975582754967e-08*size), (-0.1448889672756195*size, 0.8284152746200562*size, 0.038822878152132034*size), (-0.1299038827419281*size, 0.8284152746200562*size, 0.07500001043081284*size), (-0.10606609284877777*size, 0.8284152746200562*size, 0.1060660257935524*size), (-0.0750000923871994*size, 0.8284152746200562*size, 0.12990383803844452*size), (-0.038822952657938004*size, 0.8284152746200562*size, 0.14488889276981354*size), (-1.0593657862045802e-07*size, 0.8284152746200562*size, 0.15000005066394806*size), (0.03882275149226189*size, 0.8284152746200562*size, 0.14488892257213593*size), (0.07499989867210388*size, 0.8284152746200562*size, 0.1299038976430893*size), (0.10606591403484344*size, 0.8284152746200562*size, 0.10606611520051956*size), (0.12990373373031616*size, 0.8284152746200562*size, 0.0750000849366188*size), (0.14488881826400757*size, 0.8284152746200562*size, 0.038822952657938004*size), (0.1499999463558197*size, 0.8284152746200562*size, 1.0584351883835552e-07*size), (0.14488881826400757*size, 0.8284152746200562*size, -0.03882275149226189*size), (0.12990379333496094*size, 0.8284152746200562*size, -0.07499989122152328*size), (0.10606604814529419*size, 0.8284152746200562*size, -0.10606592148542404*size), (0.07500004768371582*size, 0.8284152746200562*size, -0.12990371882915497*size), (0.03882291540503502*size, 0.8284152746200562*size, -0.14488880336284637*size), ]
+ edges = [(1, 0), (3, 2), (5, 2), (4, 3), (6, 4), (1, 5), (0, 6), (13, 7), (12, 8), (7, 9), (9, 10), (8, 11), (27, 14), (26, 15), (14, 16), (16, 17), (15, 18), (17, 18), (10, 11), (12, 13), (20, 19), (22, 21), (24, 21), (23, 22), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (38, 37), (39, 38), (40, 39), (41, 40), (42, 41), (43, 42), (44, 43), (45, 44), (46, 45), (47, 46), (48, 47), (49, 48), (50, 49), (51, 50), (28, 51), (26, 27), (25, 23), (20, 24), (19, 25), ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ return obj
+ else:
+ return None
+
+
diff --git a/rigify/legacy/rigs/pitchipoy/tentacle.py b/rigify/legacy/rigs/pitchipoy/tentacle.py
new file mode 100644
index 00000000..b8d52e88
--- /dev/null
+++ b/rigify/legacy/rigs/pitchipoy/tentacle.py
@@ -0,0 +1,509 @@
+import bpy
+from ...utils import copy_bone
+from ...utils import strip_org, make_deformer_name, connected_children_names
+from ...utils import make_mechanism_name, put_bone, create_sphere_widget
+from ...utils import create_widget, create_circle_widget
+from ...utils import MetarigError
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+script = """
+controls = [%s]
+master_name = '%s'
+
+if is_selected( controls ):
+ layout.prop( pose_bones[ master_name ], '["%s"]', slider = True )
+ layout.prop( pose_bones[ master_name ], '["%s"]', slider = True )
+"""
+
+class Rig:
+
+ def __init__(self, obj, bone_name, params):
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+
+ if params.tweak_extra_layers:
+ self.tweak_layers = list( params.tweak_layers )
+ else:
+ self.tweak_layers = None
+
+ if len(self.org_bones) <= 1:
+ raise MetarigError(
+ "RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
+ )
+
+
+ def make_mch( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ org_bones = self.org_bones
+ mch_parent = self.obj.data.bones[ org_bones[0] ].parent
+
+ mch_parent_name = mch_parent.name # Storing the mch parent's name
+
+ if not mch_parent:
+ mch_parent = self.obj.data.edit_bones[ org_bones[0] ]
+ mch_bone = copy_bone(
+ self.obj,
+ mch_parent_name,
+ make_mechanism_name( strip_org( org_bones[0] ) )
+ )
+ else:
+ mch_bone = copy_bone(
+ self.obj,
+ mch_parent_name,
+ make_mechanism_name( strip_org( org_bones[0] ) )
+ )
+
+ put_bone( self.obj, mch_bone, eb[ mch_parent_name ].tail )
+
+ eb[ mch_bone ].length /= 4 # reduce length to fourth of original
+
+ return mch_bone
+
+
+ def make_master( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+
+ org_bones = self.org_bones
+
+ master_bone = copy_bone(
+ self.obj,
+ org_bones[0],
+ "master_" + strip_org( org_bones[0] )
+ )
+
+ # Make widgets
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ create_square_widget( self.obj, master_bone )
+
+ return master_bone
+
+
+ def make_controls( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+
+ org_bones = self.org_bones
+
+ ctrl_chain = []
+ for i in range( len( org_bones ) ):
+ name = org_bones[i]
+
+ ctrl_bone = copy_bone(
+ self.obj,
+ name,
+ strip_org(name)
+ )
+
+ ctrl_chain.append( ctrl_bone )
+
+ # Make widgets
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ for ctrl in ctrl_chain:
+ create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
+
+ return ctrl_chain
+
+
+ def make_tweaks( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+ org_bones = self.org_bones
+
+ tweak_chain = []
+ for i in range( len( org_bones ) + 1 ):
+ if i == len( org_bones ):
+ # Make final tweak at the tip of the tentacle
+ name = org_bones[i-1]
+ else:
+ name = org_bones[i]
+
+ tweak_bone = copy_bone(
+ self.obj,
+ name,
+ "tweak_" + strip_org(name)
+ )
+
+ tweak_e = eb[ tweak_bone ]
+
+ tweak_e.length /= 2 # Set size to half
+
+ if i == len( org_bones ):
+ # Position final tweak at the tip
+ put_bone( self.obj, tweak_bone, eb[ org_bones[-1]].tail )
+
+ tweak_chain.append( tweak_bone )
+
+ # Make widgets
+ bpy.ops.object.mode_set(mode = 'OBJECT')
+
+ for tweak in tweak_chain:
+ create_sphere_widget( self.obj, tweak )
+
+ tweak_pb = self.obj.pose.bones[ tweak ]
+
+ # Set locks
+ if tweak_chain.index( tweak ) != len( tweak_chain ) - 1:
+ tweak_pb.lock_rotation = (True, False, True)
+ tweak_pb.lock_scale = (False, True, False)
+ else:
+ tweak_pb.lock_rotation_w = True
+ tweak_pb.lock_rotation = (True, True, True)
+ tweak_pb.lock_scale = (True, True, True)
+
+ # Set up tweak bone layers
+ if self.tweak_layers:
+ tweak_pb.bone.layers = self.tweak_layers
+
+ return tweak_chain
+
+
+ def make_deform( self ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+
+ org_bones = self.org_bones
+
+ def_chain = []
+ for i in range( len( org_bones ) ):
+ name = org_bones[i]
+
+ def_bone = copy_bone(
+ self.obj,
+ name,
+ make_deformer_name(strip_org(name))
+ )
+
+ def_chain.append( def_bone )
+
+ return def_chain
+
+
+ def parent_bones( self, all_bones ):
+ bpy.ops.object.mode_set(mode ='EDIT')
+
+ org_bones = self.org_bones
+ eb = self.obj.data.edit_bones
+
+ """ for category in all_bones:
+ if isinstance( all_bones[category], list ):
+ for bone in all_bones[category]:
+ print( "Bone: " + bone )
+ eb[bone].parent = None
+ else:
+ eb[ all_bones[category] ].parent = None
+ """
+
+ # mch bone remains parentless and will be parented to root by rigify
+
+ # Parent master bone
+ # eb[ all_bones['master'] ].parent = eb[ all_bones['mch'] ]
+
+ # Parent control bones
+ # ctrls_n_parent = [ all_bones['master'] ] + all_bones['control']
+
+ for bone in ctrls_n_parent[1:]:
+ previous_index = ctrls_n_parent.index( bone ) - 1
+ eb[ bone ].parent = eb[ ctrls_n_parent[previous_index] ]
+
+ # Parent tweak bones
+ tweaks = all_bones['tweak']
+ for tweak in all_bones['tweak']:
+ parent = ''
+ if tweaks.index( tweak ) == len( tweaks ) - 1:
+ parent = all_bones['control'][ -1 ]
+ else:
+ parent = all_bones['control'][ tweaks.index( tweak ) ]
+
+ eb[ tweak ].parent = eb[ parent ]
+
+ # Parent deform bones
+ for bone in all_bones['deform'][1:]:
+ previous_index = all_bones['deform'].index( bone ) - 1
+
+ eb[ bone ].parent = eb[ all_bones['deform'][previous_index] ]
+ eb[ bone ].use_connect = True
+
+ # Parent org bones ( to tweaks by default, or to the controls )
+ for org, tweak in zip( org_bones, all_bones['tweak'] ):
+ eb[ org ].parent = eb[ tweak ]
+
+
+ def make_constraints( self, all_bones ):
+ bpy.ops.object.mode_set(mode ='OBJECT')
+
+ org_bones = self.org_bones
+ pb = self.obj.pose.bones
+
+ ## MCH bone constraints
+ if pb[ org_bones[0] ].parent:
+ mch_pb = pb[ all_bones['mch'] ]
+
+ con = mch_pb.constraints.new('COPY_LOCATION')
+ con.target = self.obj
+ con.subtarget = pb[ org_bones[0] ].parent.name
+ con.head_tail = 1.0
+
+ con = mch_pb.constraints.new('COPY_ROTATION')
+ con.target = self.obj
+ con.subtarget = pb[ org_bones[0] ].parent.name
+
+ con = mch_pb.constraints.new('COPY_SCALE')
+ con.target = self.obj
+ con.subtarget = pb[ org_bones[0] ].parent.name
+
+ """
+ # Setting the MCH prop
+ master_pb = pb[ all_bones['master'] ]
+ prop_name_r = "rotation_follow"
+ prop_name_s = "scale_follow"
+
+ prop_names = [ prop_name_r, prop_name_s ]
+
+ for prop_name in prop_names:
+ master_pb[prop_name] = 1.0
+
+ prop = rna_idprop_ui_prop_get( master_pb, prop_name )
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+ prop["description"] = prop_name
+
+ # driving the MCH follow rotation switch
+
+ drv = mch_pb.constraints[
+ prop_names.index(prop_name) +1
+ ].driver_add("influence").driver
+
+ drv.type='SUM'
+
+ var = drv.variables.new()
+ var.name = prop_name
+ var.type = "SINGLE_PROP"
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = \
+ master_pb.path_from_id() + '['+ '"' + prop_name + '"' + ']'
+
+ """
+
+ ## Deform bones' constraints
+ ctrls = all_bones['control']
+ tweaks = all_bones['tweak' ]
+ deforms = all_bones['deform' ]
+
+ for deform, tweak, ctrl in zip( deforms, tweaks, ctrls ):
+ con = pb[deform].constraints.new('COPY_TRANSFORMS')
+ con.target = self.obj
+ con.subtarget = tweak
+
+ con = pb[deform].constraints.new('DAMPED_TRACK')
+ con.target = self.obj
+ con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
+
+ con = pb[deform].constraints.new('STRETCH_TO')
+ con.target = self.obj
+ con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
+
+ ## Control bones' constraints
+ if self.params.make_rotations:
+ if ctrl != ctrls[0]:
+ con = pb[ctrl].constraints.new('COPY_ROTATION')
+ con.target = self.obj
+ con.subtarget = ctrls[ ctrls.index(ctrl) - 1 ]
+ con.use_offset = True
+ con.target_space = 'LOCAL'
+ con.owner_space = 'LOCAL'
+
+
+ def generate(self):
+ bpy.ops.object.mode_set(mode ='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Clear all initial parenting
+ for bone in self.org_bones:
+ # eb[ bone ].parent = None
+ eb[ bone ].use_connect = False
+
+ # Creating all bones
+ mch = self.make_mch()
+ # master = self.make_master()
+ ctrl_chain = self.make_controls()
+ tweak_chain = self.make_tweaks()
+ def_chain = self.make_deform()
+
+ all_bones = {
+ 'mch' : mch,
+ # 'master' : master,
+ 'control' : ctrl_chain,
+ 'tweak' : tweak_chain,
+ 'deform' : def_chain
+ }
+
+ self.make_constraints( all_bones )
+ self.parent_bones( all_bones )
+
+ """
+ # Create UI
+ all_controls = all_bones['control'] + all_bones['tweak'] # + [ all_bones['master'] ]
+ controls_string = ", ".join(["'" + x + "'" for x in all_controls])
+ return [script % (
+ controls_string,
+ 'rotation_follow',
+ 'scale_follow'
+ )]
+ """
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.make_rotations = bpy.props.BoolProperty(
+ name = "Rotations",
+ default = True,
+ description = "Make bones follow parent rotation"
+ )
+
+ # Setting up extra tweak layers
+ params.tweak_extra_layers = bpy.props.BoolProperty(
+ name = "tweak_extra_layers",
+ default = True,
+ description = ""
+ )
+
+ params.tweak_layers = bpy.props.BoolVectorProperty(
+ size = 32,
+ description = "Layers for the tweak controls to be on",
+ default = tuple( [ i == 1 for i in range(0, 32) ] )
+ )
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+ """
+
+ r = layout.row()
+ r.prop(params, "make_rotations")
+
+ r = layout.row()
+ r.prop(params, "tweak_extra_layers")
+ r.active = params.tweak_extra_layers
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range( 8 ): # Layers 0-7
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range( 16, 24 ): # Layers 16-23
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ col = r.column(align=True)
+ row = col.row(align=True)
+
+ for i in range( 8, 16 ): # Layers 8-15
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+ row = col.row(align=True)
+
+ for i in range( 24, 32 ): # Layers 24-31
+ row.prop(params, "tweak_layers", index=i, toggle=True, text="")
+
+
+def create_square_widget(rig, bone_name, size=1.0, bone_transform_name=None):
+ obj = create_widget(rig, bone_name, bone_transform_name)
+ if obj is not None:
+ verts = [
+ ( 0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
+ ( -0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
+ ( 0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
+ ( -0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
+ ]
+
+ edges = [(0, 1), (2, 3), (0, 2), (3, 1) ]
+ faces = []
+
+ mesh = obj.data
+ mesh.from_pydata(verts, edges, faces)
+ mesh.update()
+ mesh.update()
+ return obj
+ else:
+ return None
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+ bones = {}
+
+ bone = arm.edit_bones.new('tentacle')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.0000, 1.0000
+ bone.roll = 0.0000
+ bone.use_connect = False
+
+ bones['tentacle'] = bone.name
+
+ bone = arm.edit_bones.new('tentacle.001')
+ bone.head[:] = 0.0000, 0.0000, 1.0000
+ bone.tail[:] = 0.0000, 0.0000, 2.0000
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tentacle']]
+
+ bones['tentacle.001'] = bone.name
+
+ bone = arm.edit_bones.new('tentacle.002')
+ bone.head[:] = 0.0000, 0.0000, 2.0000
+ bone.tail[:] = 0.0000, 0.0000, 3.0000
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tentacle.001']]
+ bones['tentacle.002'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ pbone = obj.pose.bones[bones['tentacle']]
+ pbone.rigify_type = 'tentacle'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+
+ pbone.rotation_mode = 'QUATERNION'
+
+ pbone = obj.pose.bones[bones['tentacle.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+
+ pbone.rotation_mode = 'QUATERNION'
+
+ pbone = obj.pose.bones[bones['tentacle.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
diff --git a/rigify/legacy/rigs/spine.py b/rigify/legacy/rigs/spine.py
new file mode 100644
index 00000000..680a4ceb
--- /dev/null
+++ b/rigify/legacy/rigs/spine.py
@@ -0,0 +1,567 @@
+#====================== 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>
+
+""" TODO:
+ - Add parameters for bone transform alphas.
+ - Add IK spine controls
+"""
+
+from math import floor
+
+import bpy
+from mathutils import Vector
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+from ..utils import MetarigError
+from ..utils import copy_bone, new_bone, flip_bone, put_bone
+from ..utils import connected_children_names
+from ..utils import strip_org, make_mechanism_name, make_deformer_name
+from ..utils import create_circle_widget, create_cube_widget
+
+script = """
+main = "%s"
+spine = [%s]
+if is_selected([main]+ spine):
+ layout.prop(pose_bones[main], '["pivot_slide"]', text="Pivot Slide (" + main + ")", slider=True)
+
+for name in spine[1:-1]:
+ if is_selected(name):
+ layout.prop(pose_bones[name], '["auto_rotate"]', text="Auto Rotate (" + name + ")", slider=True)
+"""
+
+
+class Rig:
+ """ A "spine" rig. It turns a chain of bones into a rig with two controls:
+ One for the hips, and one for the rib cage.
+
+ """
+ def __init__(self, obj, bone_name, params):
+ """ Gather and validate data about the rig.
+
+ """
+ self.obj = obj
+ self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+ self.params = params
+
+ # Collect control bone indices
+ self.control_indices = [0, len(self.org_bones) - 1]
+ temp = self.params.chain_bone_controls.split(",")
+ for i in temp:
+ try:
+ j = int(i) - 1
+ except ValueError:
+ pass
+ else:
+ if (j > 0) and (j < len(self.org_bones)) and (j not in self.control_indices):
+ self.control_indices += [j]
+ self.control_indices.sort()
+
+ self.pivot_rest = self.params.rest_pivot_slide
+ # Clamp pivot_rest to within the middle bones of the spine
+ self.pivot_rest = max(self.pivot_rest, 1.0 / len(self.org_bones))
+ self.pivot_rest = min(self.pivot_rest, 1.0 - (1.0 / len(self.org_bones)))
+
+ 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)))
+
+ def gen_deform(self):
+ """ Generate the deformation rig.
+
+ """
+ for name in self.org_bones:
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create deform bone
+ bone_e = eb[copy_bone(self.obj, name)]
+
+ # Change its name
+ bone_e.name = make_deformer_name(strip_org(name))
+ bone_name = bone_e.name
+
+ # Leave edit mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Get the pose bone
+ bone = self.obj.pose.bones[bone_name]
+
+ # Constrain to the original bone
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name
+
+ def gen_control(self):
+ """ Generate the control rig.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+ #-------------------------
+ # Get rest slide position
+ a = self.pivot_rest * len(self.org_bones)
+ i = floor(a)
+ a -= i
+ if i == len(self.org_bones):
+ i -= 1
+ a = 1.0
+
+ pivot_rest_pos = eb[self.org_bones[i]].head.copy()
+ pivot_rest_pos += eb[self.org_bones[i]].vector * a
+
+ #----------------------
+ # Create controls
+
+ # Create control bones
+ controls = []
+ for i in self.control_indices:
+ name = copy_bone(self.obj, self.org_bones[i], strip_org(self.org_bones[i]))
+ controls += [name]
+
+ # Create control parents
+ control_parents = []
+ for i in self.control_indices[1:-1]:
+ name = new_bone(self.obj, make_mechanism_name("par_" + strip_org(self.org_bones[i])))
+ control_parents += [name]
+
+ # Create sub-control bones
+ subcontrols = []
+ for i in self.control_indices:
+ name = new_bone(self.obj, make_mechanism_name("sub_" + strip_org(self.org_bones[i])))
+ subcontrols += [name]
+
+ # Create main control bone
+ main_control = new_bone(self.obj, self.params.spine_main_control_name)
+
+ eb = self.obj.data.edit_bones
+
+ # Parent the main control
+ eb[main_control].use_connect = False
+ eb[main_control].parent = eb[self.org_bones[0]].parent
+
+ # Parent the controls and sub-controls
+ for name, subname in zip(controls, subcontrols):
+ eb[name].use_connect = False
+ eb[name].parent = eb[main_control]
+ eb[subname].use_connect = False
+ eb[subname].parent = eb[name]
+
+ # Parent the control parents
+ for name, par_name in zip(controls[1:-1], control_parents):
+ eb[par_name].use_connect = False
+ eb[par_name].parent = eb[main_control]
+ eb[name].parent = eb[par_name]
+
+ # Position the main bone
+ put_bone(self.obj, main_control, pivot_rest_pos)
+ eb[main_control].length = sum([eb[b].length for b in self.org_bones]) / 2
+
+ # Position the controls and sub-controls
+ for name, subname in zip(controls, subcontrols):
+ put_bone(self.obj, name, pivot_rest_pos)
+ put_bone(self.obj, subname, pivot_rest_pos)
+ eb[subname].length = eb[name].length / 3
+
+ # Position the control parents
+ for name, par_name in zip(controls[1:-1], control_parents):
+ put_bone(self.obj, par_name, pivot_rest_pos)
+ eb[par_name].length = eb[name].length / 2
+
+ #-----------------------------------------
+ # Control bone constraints and properties
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ # Lock control locations
+ for name in controls:
+ bone = pb[name]
+ bone.lock_location = True, True, True
+
+ # Main control doesn't use local location
+ pb[main_control].bone.use_local_location = False
+
+ # Intermediate controls follow hips and spine
+ for name, par_name, i in zip(controls[1:-1], control_parents, self.control_indices[1:-1]):
+ bone = pb[par_name]
+
+ # Custom bend_alpha property
+ prop = rna_idprop_ui_prop_get(pb[name], "bend_alpha", create=True)
+ pb[name]["bend_alpha"] = i / (len(self.org_bones) - 1) # set bend alpha
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ # Custom auto_rotate
+ prop = rna_idprop_ui_prop_get(pb[name], "auto_rotate", create=True)
+ pb[name]["auto_rotate"] = 1.0
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ # Constraints
+ con1 = bone.constraints.new('COPY_TRANSFORMS')
+ con1.name = "copy_transforms"
+ con1.target = self.obj
+ con1.subtarget = subcontrols[0]
+
+ con2 = bone.constraints.new('COPY_TRANSFORMS')
+ con2.name = "copy_transforms"
+ con2.target = self.obj
+ con2.subtarget = subcontrols[-1]
+
+ # Drivers
+ fcurve = con1.driver_add("influence")
+ driver = fcurve.driver
+ driver.type = 'AVERAGE'
+ var = driver.variables.new()
+ var.name = "auto"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]'
+
+ fcurve = con2.driver_add("influence")
+ driver = fcurve.driver
+ driver.type = 'SCRIPTED'
+ driver.expression = "alpha * auto"
+ var = driver.variables.new()
+ var.name = "alpha"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[name].path_from_id() + '["bend_alpha"]'
+ var = driver.variables.new()
+ var.name = "auto"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = pb[name].path_from_id() + '["auto_rotate"]'
+
+ #-------------------------
+ # Create flex spine chain
+ bpy.ops.object.mode_set(mode='EDIT')
+ flex_bones = []
+ flex_subs = []
+ prev_bone = None
+ for b in self.org_bones:
+ # Create bones
+ bone = copy_bone(self.obj, b, make_mechanism_name(strip_org(b) + ".flex"))
+ sub = new_bone(self.obj, make_mechanism_name(strip_org(b) + ".flex_s"))
+ flex_bones += [bone]
+ flex_subs += [sub]
+
+ eb = self.obj.data.edit_bones
+ bone_e = eb[bone]
+ sub_e = eb[sub]
+
+ # Parenting
+ bone_e.use_connect = False
+ sub_e.use_connect = False
+ if prev_bone is None:
+ sub_e.parent = eb[controls[0]]
+ else:
+ sub_e.parent = eb[prev_bone]
+ bone_e.parent = sub_e
+
+ # Position
+ put_bone(self.obj, sub, bone_e.head)
+ sub_e.length = bone_e.length / 4
+ if prev_bone is not None:
+ sub_e.use_connect = True
+
+ prev_bone = bone
+
+ #----------------------------
+ # Create reverse spine chain
+
+ # Create bones/parenting/positioning
+ bpy.ops.object.mode_set(mode='EDIT')
+ rev_bones = []
+ prev_bone = None
+ for b in zip(flex_bones, self.org_bones):
+ # Create bones
+ bone = copy_bone(self.obj, b[1], make_mechanism_name(strip_org(b[1]) + ".reverse"))
+ rev_bones += [bone]
+ eb = self.obj.data.edit_bones
+ bone_e = eb[bone]
+
+ # Parenting
+ bone_e.use_connect = False
+ bone_e.parent = eb[b[0]]
+
+ # Position
+ flip_bone(self.obj, bone)
+ bone_e.tail = Vector(eb[b[0]].head)
+ #bone_e.head = Vector(eb[b[0]].tail)
+ if prev_bone is None:
+ put_bone(self.obj, bone, pivot_rest_pos)
+ else:
+ put_bone(self.obj, bone, eb[prev_bone].tail)
+
+ prev_bone = bone
+
+ # Constraints
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+ prev_bone = None
+ for bone in rev_bones:
+ bone_p = pb[bone]
+
+ con = bone_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ if prev_bone is None:
+ con.subtarget = main_control
+ else:
+ con.subtarget = prev_bone
+ con.head_tail = 1.0
+ prev_bone = bone
+
+ #----------------------------------------
+ # Constrain original bones to flex spine
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ for obone, fbone in zip(self.org_bones, flex_bones):
+ con = pb[obone].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = fbone
+
+ #---------------------------
+ # Create pivot slide system
+ pb = self.obj.pose.bones
+ bone_p = pb[self.org_bones[0]]
+ main_control_p = pb[main_control]
+
+ # Custom pivot_slide property
+ prop = rna_idprop_ui_prop_get(main_control_p, "pivot_slide", create=True)
+ main_control_p["pivot_slide"] = self.pivot_rest
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 1.0 / len(self.org_bones)
+ prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones))
+
+ # Anchor constraints
+ con = bone_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = rev_bones[0]
+
+ # Slide constraints
+ i = 1
+ tot = len(rev_bones)
+ for rb in rev_bones:
+ con = bone_p.constraints.new('COPY_LOCATION')
+ con.name = "slide." + str(i)
+ con.target = self.obj
+ con.subtarget = rb
+ con.head_tail = 1.0
+
+ # Driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "slide"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = main_control_p.path_from_id() + '["pivot_slide"]'
+ mod = fcurve.modifiers[0]
+ mod.poly_order = 1
+ mod.coefficients[0] = 1 - i
+ mod.coefficients[1] = tot
+
+ i += 1
+
+ #----------------------------------
+ # Constrain flex spine to controls
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ # Constrain the bones that correspond exactly to the controls
+ for i, name in zip(self.control_indices, subcontrols):
+ con = pb[flex_subs[i]].constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name
+
+ # Constrain the bones in-between the controls
+ for i, j, name1, name2 in zip(self.control_indices, self.control_indices[1:], subcontrols, subcontrols[1:]):
+ if (i + 1) < j:
+ for n in range(i + 1, j):
+ bone = pb[flex_subs[n]]
+ # Custom bend_alpha property
+ prop = rna_idprop_ui_prop_get(bone, "bend_alpha", create=True)
+ bone["bend_alpha"] = (n - i) / (j - i) # set bend alpha
+ prop["min"] = 0.0
+ prop["max"] = 1.0
+ prop["soft_min"] = 0.0
+ prop["soft_max"] = 1.0
+
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name1
+
+ con = bone.constraints.new('COPY_TRANSFORMS')
+ con.name = "copy_transforms"
+ con.target = self.obj
+ con.subtarget = name2
+
+ # Driver
+ fcurve = con.driver_add("influence")
+ driver = fcurve.driver
+ var = driver.variables.new()
+ driver.type = 'AVERAGE'
+ var.name = "alpha"
+ var.targets[0].id_type = 'OBJECT'
+ var.targets[0].id = self.obj
+ var.targets[0].data_path = bone.path_from_id() + '["bend_alpha"]'
+
+ #-------------
+ # Final stuff
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ # Control appearance
+ # Main
+ create_cube_widget(self.obj, main_control)
+
+ # Spines
+ for name, i in zip(controls[1:-1], self.control_indices[1:-1]):
+ pb[name].custom_shape_transform = pb[self.org_bones[i]]
+ # Create control widgets
+ create_circle_widget(self.obj, name, radius=1.0, head_tail=0.5, with_line=True, bone_transform_name=self.org_bones[i])
+
+ # Hips
+ pb[controls[0]].custom_shape_transform = pb[self.org_bones[0]]
+ # Create control widgets
+ create_circle_widget(self.obj, controls[0], radius=1.0, head_tail=0.5, with_line=True, bone_transform_name=self.org_bones[0])
+
+ # Ribs
+ pb[controls[-1]].custom_shape_transform = pb[self.org_bones[-1]]
+ # Create control widgets
+ create_circle_widget(self.obj, controls[-1], radius=1.0, head_tail=0.5, with_line=True, bone_transform_name=self.org_bones[-1])
+
+ # Layers
+ pb[main_control].bone.layers = pb[self.org_bones[0]].bone.layers
+
+ return [main_control] + controls
+
+ 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.gen_deform()
+ controls = self.gen_control()
+
+ controls_string = ", ".join(["'" + x + "'" for x in controls[1:]])
+ return [script % (controls[0], controls_string)]
+
+
+def add_parameters(params):
+ """ Add the parameters of this rig type to the
+ RigifyParameters PropertyGroup
+ """
+ params.spine_main_control_name = bpy.props.StringProperty(name="Main control name", default="torso", description="Name that the main control bone should be given")
+ params.rest_pivot_slide = bpy.props.FloatProperty(name="Rest Pivot Slide", default=0.0, min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, description="The pivot slide value in the rest pose")
+ params.chain_bone_controls = bpy.props.StringProperty(name="Control bone list", default="", description="Define which bones have controls")
+
+
+def parameters_ui(layout, params):
+ """ Create the ui for the rig parameters.
+ """
+ r = layout.row()
+ r.prop(params, "spine_main_control_name")
+
+ r = layout.row()
+ r.prop(params, "rest_pivot_slide", slider=True)
+
+ r = layout.row()
+ r.prop(params, "chain_bone_controls")
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('hips')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = -0.0000, -0.0590, 0.2804
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bones['hips'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = -0.0000, -0.0590, 0.2804
+ bone.tail[:] = 0.0000, 0.0291, 0.5324
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['hips']]
+ bones['spine'] = bone.name
+ bone = arm.edit_bones.new('ribs')
+ bone.head[:] = 0.0000, 0.0291, 0.5324
+ bone.tail[:] = -0.0000, 0.0000, 1.0000
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['ribs'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['hips']]
+ pbone.rigify_type = 'spine'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['ribs']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone = obj.pose.bones[bones['hips']]
+ pbone['rigify_type'] = 'spine'
+ pbone.rigify_parameters.chain_bone_controls = "1, 2, 3"
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone