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:
authorNathan Vegdahl <cessen@cessen.com>2014-09-26 07:24:03 +0400
committerNathan Vegdahl <cessen@cessen.com>2014-09-26 07:24:03 +0400
commitc35610f163a05f81951a2b069306b675294f4cb3 (patch)
tree645ec626585d90e3ba3c678ee739e9c36e81b7d1 /rigify/rigs/pitchipoy/limbs
parentfd695c3a81b63db072311e8516e0dbb8d4474047 (diff)
Rigify: new additions from PitchiPoy Animation Productions.
PitchiPoy Animation Productions is sharing its custom rig types with the Blender community at large. The new rig types all start with "pitchipoy." and are used in PitchiPoy's productions. Of particular interest is a face rig type for auto-rigging faces. Other rig types include: - Tentacles - Fingers - Arms/Legs - Spine/Torso Many thanks to PitchiPoy for their hard work and for sharing this back!
Diffstat (limited to 'rigify/rigs/pitchipoy/limbs')
-rw-r--r--rigify/rigs/pitchipoy/limbs/__init__.py0
-rw-r--r--rigify/rigs/pitchipoy/limbs/arm.py109
-rw-r--r--rigify/rigs/pitchipoy/limbs/leg.py327
-rw-r--r--rigify/rigs/pitchipoy/limbs/limb_utils.py70
-rw-r--r--rigify/rigs/pitchipoy/limbs/paw.py217
-rw-r--r--rigify/rigs/pitchipoy/limbs/super_limb.py724
-rw-r--r--rigify/rigs/pitchipoy/limbs/ui.py51
7 files changed, 1498 insertions, 0 deletions
diff --git a/rigify/rigs/pitchipoy/limbs/__init__.py b/rigify/rigs/pitchipoy/limbs/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/__init__.py
diff --git a/rigify/rigs/pitchipoy/limbs/arm.py b/rigify/rigs/pitchipoy/limbs/arm.py
new file mode 100644
index 00000000..50a11e11
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/arm.py
@@ -0,0 +1,109 @@
+#====================== 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'
+ })
+
+ # Create ik/fk switch property
+ pb = cls.obj.pose.bones
+ 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/rigs/pitchipoy/limbs/leg.py b/rigify/rigs/pitchipoy/limbs/leg.py
new file mode 100644
index 00000000..5e1844ab
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/leg.py
@@ -0,0 +1,327 @@
+#====================== 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'
+ })
+
+ # 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/rigs/pitchipoy/limbs/limb_utils.py b/rigify/rigs/pitchipoy/limbs/limb_utils.py
new file mode 100644
index 00000000..73e4f472
--- /dev/null
+++ b/rigify/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/rigs/pitchipoy/limbs/paw.py b/rigify/rigs/pitchipoy/limbs/paw.py
new file mode 100644
index 00000000..50b313f8
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/paw.py
@@ -0,0 +1,217 @@
+#====================== 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'] = []
+
+ 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 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
+
+ # 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
+
+ # 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'
+ })
+
+ # Create ik/fk switch property
+ pb = cls.obj.pose.bones
+ 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'][-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/rigs/pitchipoy/limbs/super_limb.py b/rigify/rigs/pitchipoy/limbs/super_limb.py
new file mode 100644
index 00000000..28e9b70e
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/super_limb.py
@@ -0,0 +1,724 @@
+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 torso rig and key rig properties """
+ self.obj = obj
+ self.params = params
+ self.org_bones = list(
+ [bone_name] + connected_children_names(obj, bone_name)
+ )[:3] # The basic limb is the first 3 bones
+
+ 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
+ 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' )
+ )
+
+ eb[ mch_str ].tail = eb[ org_bones[-1] ].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
+
+ 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 <= 2:
+ 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 ) ]
+
+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/rigs/pitchipoy/limbs/ui.py b/rigify/rigs/pitchipoy/limbs/ui.py
new file mode 100644
index 00000000..118593ed
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/ui.py
@@ -0,0 +1,51 @@
+script = """
+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 )
+
+# 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):
+ # All ctrls have IK/FK switch
+ controls = [ bones['ik']['ctrl']['limb'] ] + bones['fk']['ctrl']
+ controls += bones['ik']['ctrl']['terminal']
+
+ 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]
+
+ return script % (
+ controls_string,
+ tweaks_string,
+ ik_ctrl,
+ bones['fk']['ctrl'][0],
+ bones['parent'],
+ 'IK/FK',
+ 'rubber_tweak',
+ 'IK_Strertch',
+ 'FK_limb_follow'
+ )
+