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>2016-09-12 17:14:15 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2016-09-26 15:29:38 +0300
commit1f9e3bfa3b8bc5fe082d7182b422c788691653a1 (patch)
tree5cbd9ba11ec318aa00257e182582d89e38846615
parentd0459333af1b5935013dd3b27121ef61c2360365 (diff)
Pitchipoy: added super_arm and super_leg w root/parent switch
-rw-r--r--rigify/rigs/pitchipoy/limbs/super_arm.py1294
-rw-r--r--rigify/rigs/pitchipoy/limbs/super_leg.py1233
2 files changed, 2527 insertions, 0 deletions
diff --git a/rigify/rigs/pitchipoy/limbs/super_arm.py b/rigify/rigs/pitchipoy/limbs/super_arm.py
new file mode 100644
index 00000000..cddf59c8
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/super_arm.py
@@ -0,0 +1,1294 @@
+import bpy, re
+from ..super_widgets import create_hand_widget
+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
+
+extra_script = """
+controls = [%s]
+ctrl = '%s'
+
+if is_selected( controls ):
+ layout.prop( pose_bones[ ctrl ], '["%s"]')
+ layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
+"""
+
+class Rig:
+ def __init__(self, obj, bone_name, params):
+ """ Initialize arm 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 (self.limb_type == 'paw'):
+ # idx_stop = len(org_bones)
+ #else:
+ # idx_stop = len(org_bones) - 1
+
+ if i < len(org_bones) - 1:
+ # if i < idx_stop:
+ # 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.copy()
+
+
+ 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_arm( self, bones ):
+ org_bones = self.org_bones
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ ctrl = get_bone_name( org_bones[2], 'ctrl', 'ik' )
+
+ # Create IK arm control
+ ctrl = copy_bone( self.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 ik ctrl to root / parent
+
+ # Todo this should be better : target = strip_org(eb[org_bones[0]].parent.name)
+ target = eb[org_bones[0]].parent.name
+
+ make_constraint( self, ctrl, {
+ 'constraint' : 'CHILD_OF',
+ 'subtarget' : 'root',
+ })
+
+
+ make_constraint( self, ctrl, {
+ 'constraint' : 'CHILD_OF',
+ 'subtarget' : target,
+ 'influence' : 0.0,
+ })
+
+
+ pbone = self.obj.pose.bones[target]
+
+ const = self.obj.pose.bones[ctrl].constraints[1]
+ const.inverse_matrix = (self.obj.matrix_world*pbone.matrix).inverted()
+
+ # Constrain mch target bone to the ik control and mch stretch
+
+ make_constraint( self, 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( self, bones['ik']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : ctrl,
+ })
+ make_constraint( self, bones['ik']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : ctrl,
+ })
+ make_constraint( self, 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 = self.obj.pose.bones
+ pb_parent = pb[ bones['parent'] ]
+
+ # 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'
+
+ 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 = self.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ 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
+
+ # Create hand widget
+ create_hand_widget(self.obj, ctrl, bone_transform_name=None)
+
+ bones['ik']['ctrl']['terminal'] = [ ctrl ]
+
+ return bones
+
+ # 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 create_drivers(self, bones):
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ ctrl = pb[bones['ik']['ctrl']['terminal'][0]]
+
+ props = [ "IK_follow", "root/parent" ]
+
+ for prop in props:
+ if prop == 'IK_follow':
+
+ ctrl[prop]=True
+ rna_prop = rna_idprop_ui_prop_get( ctrl, prop, create=True )
+ rna_prop["min"] = False
+ rna_prop["max"] = True
+ rna_prop["description"] = prop
+
+ drv = ctrl.constraints[ 0 ].driver_add("mute").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 = \
+ ctrl.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
+
+ drv = ctrl.constraints[ 1 ].driver_add("mute").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 = \
+ ctrl.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
+
+ else:
+ ctrl[prop]=0.0
+ rna_prop = rna_idprop_ui_prop_get( ctrl, prop, create=True )
+ rna_prop["min"] = 0.0
+ rna_prop["max"] = 1.0
+ rna_prop["soft_min"] = 0.0
+ rna_prop["soft_max"] = 1.0
+ rna_prop["description"] = prop
+
+ drv = ctrl.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 = \
+ ctrl.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
+
+ drv = ctrl.constraints[ 1 ].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 = \
+ ctrl.path_from_id() + '['+ '"' + prop + '"' + ']'
+
+
+ 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_arm( bones )
+ self.create_drivers( bones )
+
+ controls = [ bones['ik']['ctrl']['limb'], bones['ik']['ctrl']['terminal'][0] ]
+
+
+ # Create UI
+ controls_string = ", ".join(["'" + x + "'" for x in controls])
+
+ script = create_script( bones, 'arm' )
+ script += extra_script % (controls_string, bones['ik']['ctrl']['terminal'][0], 'IK_follow', 'root/parent')
+
+ return [ script ]
+
+
+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 = {}
+
+ for _ in range(28):
+ arm.rigify_layers.add()
+
+ arm.rigify_layers[5].name = 'Fingers'
+ arm.rigify_layers[5].row = 5
+ arm.rigify_layers[6].name = 'Fingers (Tweak)'
+ arm.rigify_layers[6].row = 6
+ arm.rigify_layers[7].name = 'Arm.L (IK)'
+ arm.rigify_layers[7].row = 7
+ arm.rigify_layers[8].name = 'Arm.L (FK)'
+ arm.rigify_layers[8].row = 8
+ arm.rigify_layers[9].name = 'Arm.L (Tweak)'
+ arm.rigify_layers[9].row = 9
+
+ bone = arm.edit_bones.new('upper_arm.L')
+ bone.head[:] = 0.1953, 0.0267, 1.5846
+ bone.tail[:] = 0.4424, 0.0885, 1.4491
+ bone.roll = 2.0724
+ bone.use_connect = False
+ bones['upper_arm.L'] = bone.name
+ bone = arm.edit_bones.new('forearm.L')
+ bone.head[:] = 0.4424, 0.0885, 1.4491
+ bone.tail[:] = 0.6594, 0.0492, 1.3061
+ 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.6594, 0.0492, 1.3061
+ bone.tail[:] = 0.7234, 0.0412, 1.2585
+ bone.roll = 2.2103
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['forearm.L']]
+ bones['hand.L'] = bone.name
+ bone = arm.edit_bones.new('palm.01.L')
+ bone.head[:] = 0.6921, 0.0224, 1.2882
+ bone.tail[:] = 0.7464, 0.0051, 1.2482
+ bone.roll = -2.4928
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['hand.L']]
+ bones['palm.01.L'] = bone.name
+ bone = arm.edit_bones.new('palm.02.L')
+ bone.head[:] = 0.6970, 0.0389, 1.2877
+ bone.tail[:] = 0.7518, 0.0277, 1.2487
+ bone.roll = -2.5274
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['hand.L']]
+ bones['palm.02.L'] = bone.name
+ bone = arm.edit_bones.new('palm.03.L')
+ bone.head[:] = 0.6963, 0.0545, 1.2874
+ bone.tail[:] = 0.7540, 0.0521, 1.2482
+ bone.roll = -2.5843
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['hand.L']]
+ bones['palm.03.L'] = bone.name
+ bone = arm.edit_bones.new('palm.04.L')
+ bone.head[:] = 0.6929, 0.0696, 1.2871
+ bone.tail[:] = 0.7528, 0.0763, 1.2428
+ bone.roll = -2.5155
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['hand.L']]
+ bones['palm.04.L'] = bone.name
+ bone = arm.edit_bones.new('f_index.01.L')
+ bone.head[:] = 0.7464, 0.0051, 1.2482
+ bone.tail[:] = 0.7718, 0.0013, 1.2112
+ bone.roll = -2.0315
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.01.L']]
+ bones['f_index.01.L'] = bone.name
+ bone = arm.edit_bones.new('thumb.01.L')
+ bone.head[:] = 0.6705, 0.0214, 1.2738
+ bone.tail[:] = 0.6857, 0.0015, 1.2404
+ bone.roll = -0.1587
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.01.L']]
+ bones['thumb.01.L'] = bone.name
+ bone = arm.edit_bones.new('f_middle.01.L')
+ bone.head[:] = 0.7518, 0.0277, 1.2487
+ bone.tail[:] = 0.7762, 0.0234, 1.2058
+ bone.roll = -2.0067
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.02.L']]
+ bones['f_middle.01.L'] = bone.name
+ bone = arm.edit_bones.new('f_ring.01.L')
+ bone.head[:] = 0.7540, 0.0521, 1.2482
+ bone.tail[:] = 0.7715, 0.0499, 1.2070
+ bone.roll = -2.0082
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['palm.03.L']]
+ bones['f_ring.01.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.01.L')
+ bone.head[:] = 0.7528, 0.0763, 1.2428
+ bone.tail[:] = 0.7589, 0.0765, 1.2156
+ 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_index.02.L')
+ bone.head[:] = 0.7718, 0.0013, 1.2112
+ bone.tail[:] = 0.7840, -0.0003, 1.1858
+ bone.roll = -1.8799
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_index.01.L']]
+ bones['f_index.02.L'] = bone.name
+ bone = arm.edit_bones.new('thumb.02.L')
+ bone.head[:] = 0.6857, 0.0015, 1.2404
+ bone.tail[:] = 0.7056, -0.0057, 1.2145
+ bone.roll = -0.4798
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['thumb.01.L']]
+ bones['thumb.02.L'] = bone.name
+ bone = arm.edit_bones.new('f_middle.02.L')
+ bone.head[:] = 0.7762, 0.0234, 1.2058
+ bone.tail[:] = 0.7851, 0.0218, 1.1749
+ bone.roll = -1.8283
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_middle.01.L']]
+ bones['f_middle.02.L'] = bone.name
+ bone = arm.edit_bones.new('f_ring.02.L')
+ bone.head[:] = 0.7715, 0.0499, 1.2070
+ bone.tail[:] = 0.7794, 0.0494, 1.1762
+ bone.roll = -1.8946
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_ring.01.L']]
+ bones['f_ring.02.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.02.L')
+ bone.head[:] = 0.7589, 0.0765, 1.2156
+ bone.tail[:] = 0.7618, 0.0770, 1.1932
+ 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_index.03.L')
+ bone.head[:] = 0.7840, -0.0003, 1.1858
+ bone.tail[:] = 0.7892, 0.0006, 1.1636
+ bone.roll = -1.6760
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_index.02.L']]
+ bones['f_index.03.L'] = bone.name
+ bone = arm.edit_bones.new('thumb.03.L')
+ bone.head[:] = 0.7056, -0.0057, 1.2145
+ bone.tail[:] = 0.7194, -0.0098, 1.1995
+ bone.roll = -0.5826
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['thumb.02.L']]
+ bones['thumb.03.L'] = bone.name
+ bone = arm.edit_bones.new('f_middle.03.L')
+ bone.head[:] = 0.7851, 0.0218, 1.1749
+ bone.tail[:] = 0.7888, 0.0216, 1.1525
+ bone.roll = -1.7483
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_middle.02.L']]
+ bones['f_middle.03.L'] = bone.name
+ bone = arm.edit_bones.new('f_ring.03.L')
+ bone.head[:] = 0.7794, 0.0494, 1.1762
+ bone.tail[:] = 0.7781, 0.0498, 1.1577
+ bone.roll = -1.6582
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['f_ring.02.L']]
+ bones['f_ring.03.L'] = bone.name
+ bone = arm.edit_bones.new('f_pinky.03.L')
+ bone.head[:] = 0.7618, 0.0770, 1.1932
+ bone.tail[:] = 0.7611, 0.0772, 1.1782
+ 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['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'
+ pbone = obj.pose.bones[bones['palm.01.L']]
+ pbone.rigify_type = 'palm'
+ 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['palm.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 = 'YXZ'
+ pbone = obj.pose.bones[bones['palm.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 = 'YXZ'
+ 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_index.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['thumb.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.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.separate_extra_layers = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_extra_layers = False
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['f_middle.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_ring.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.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_index.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['thumb.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_middle.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_ring.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.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_index.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'
+ pbone = obj.pose.bones[bones['thumb.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'
+ pbone = obj.pose.bones[bones['f_middle.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'
+ pbone = obj.pose.bones[bones['f_ring.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'
+ 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
+
+ for eb in arm.edit_bones:
+ if ('arm' in eb.name) or ('hand' in eb.name):
+ eb.layers = (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, False)
+ else:
+ eb.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)
+ arm.layers = (False, False, False, False, False, True, 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)
+
+
+if __name__ == "__main__":
+ create_sample(bpy.context.active_object) \ No newline at end of file
diff --git a/rigify/rigs/pitchipoy/limbs/super_leg.py b/rigify/rigs/pitchipoy/limbs/super_leg.py
new file mode 100644
index 00000000..8a61bb4d
--- /dev/null
+++ b/rigify/rigs/pitchipoy/limbs/super_leg.py
@@ -0,0 +1,1233 @@
+
+import bpy, re, math
+from ..super_widgets import create_foot_widget, create_ballsocket_widget
+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
+
+extra_script = """
+controls = [%s]
+ctrl = '%s'
+
+if is_selected( controls ):
+ layout.prop( pose_bones[ ctrl ], '["%s"]')
+ layout.prop( pose_bones[ ctrl ], '["%s"]', slider = True )
+"""
+
+class Rig:
+ def __init__(self, obj, bone_name, params):
+ """ Initialize leg 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 (self.limb_type == 'paw'):
+ # idx_stop = len(org_bones)
+ #else:
+ # idx_stop = len(org_bones) - 1
+
+ if i < len(org_bones) - 1:
+ # if i < idx_stop:
+ # 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.copy()
+
+
+ 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_leg( self, bones ):
+ org_bones = list(
+ [self.org_bones[0]] + connected_children_names(self.obj, self.org_bones[0])
+ )
+
+ bones['ik']['ctrl']['terminal'] = []
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ # Create toes def bone
+ toes_def = get_bone_name( org_bones[-1], 'def' )
+ toes_def = copy_bone( self.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( self.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( self.obj, org_bones[2], heel )
+ orient_bone( self, 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( self, 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 self.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( self.obj, org_bones[2], roll1_mch )
+
+ # clear parent
+ eb[ roll1_mch ].use_connect = False
+ eb[ roll1_mch ].parent = None
+
+ flip_bone( self.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( self.obj, org_bones[3], roll2_mch )
+
+ eb[ roll2_mch ].use_connect = False
+ eb[ roll2_mch ].parent = None
+
+ put_bone(
+ self.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( self.obj, tmp_heel, rock1_mch )
+
+ eb[ rock1_mch ].use_connect = False
+ eb[ rock1_mch ].parent = None
+
+ orient_bone( self, 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( self.obj, tmp_heel, rock2_mch )
+
+ eb[ rock2_mch ].use_connect = False
+ eb[ rock2_mch ].parent = None
+
+ orient_bone( self, 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 ]
+
+ # Get target for ctrl constraints
+ # Todo this should be better : target = strip_org(eb[org_bones[0]].parent.name)
+ target = eb[org_bones[0]].parent.name
+
+ # Constrain rock and roll MCH bones
+ make_constraint( self, roll1_mch, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( self, roll1_mch, {
+ 'constraint' : 'LIMIT_ROTATION',
+ 'use_limit_x' : True,
+ 'max_x' : math.radians(360),
+ 'owner_space' : 'LOCAL'
+ })
+ make_constraint( self, roll2_mch, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'use_y' : False,
+ 'use_z' : False,
+ 'invert_x' : True,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( self, roll2_mch, {
+ 'constraint' : 'LIMIT_ROTATION',
+ 'use_limit_x' : True,
+ 'max_x' : math.radians(360),
+ 'owner_space' : 'LOCAL'
+ })
+
+ pb = self.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( self, b, {
+ 'constraint' : 'COPY_ROTATION',
+ 'subtarget' : heel,
+ 'use_x' : False,
+ 'use_z' : False,
+ 'owner_space' : 'LOCAL',
+ 'target_space' : 'LOCAL'
+ })
+ make_constraint( self, 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( self, org_bones[3], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : roll2_mch
+ })
+
+ # Set up constraints
+
+ # Constrain ik ctrl to root / parent
+
+ make_constraint( self, ctrl, {
+ 'constraint' : 'CHILD_OF',
+ 'subtarget' : 'root',
+ })
+
+
+ make_constraint( self, ctrl, {
+ 'constraint' : 'CHILD_OF',
+ 'subtarget' : target,
+ 'influence' : 0.0,
+ })
+
+
+ pbone = self.obj.pose.bones[target]
+
+ const = self.obj.pose.bones[ctrl].constraints[1]
+ const.inverse_matrix = (self.obj.matrix_world*pbone.matrix).inverted()
+
+ # Constrain mch target bone to the ik control and mch stretch
+
+ make_constraint( self, 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( self, bones['ik']['mch_str'], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : roll1_mch,
+ 'head_tail' : 1.0
+ })
+ make_constraint( self, bones['ik']['mch_str'], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : roll1_mch,
+ 'head_tail' : 1.0
+ })
+ make_constraint( self, 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 = self.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ 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
+
+ # Create leg widget
+ create_foot_widget(self.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(self.obj, heel, bone_transform_name=None)
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ eb = self.obj.data.edit_bones
+
+ if len( org_bones ) >= 4:
+ # Create toes control bone
+ toes = get_bone_name( org_bones[3], 'ctrl' )
+ toes = copy_bone( self.obj, org_bones[3], toes )
+
+ eb[ toes ].use_connect = False
+ eb[ toes ].parent = eb[ org_bones[3] ]
+
+ # Constrain toes def bones
+ make_constraint( self, bones['def'][-2], {
+ 'constraint' : 'DAMPED_TRACK',
+ 'subtarget' : toes
+ })
+ make_constraint( self, bones['def'][-2], {
+ 'constraint' : 'STRETCH_TO',
+ 'subtarget' : toes
+ })
+
+ make_constraint( self, bones['def'][-1], {
+ 'constraint' : 'COPY_TRANSFORMS',
+ 'subtarget' : toes
+ })
+
+ # Find IK/FK switch property
+ pb = self.obj.pose.bones
+ prop = rna_idprop_ui_prop_get( pb[ bones['parent'] ], 'IK/FK' )
+
+ # 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'
+
+ # 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 = self.obj
+ var.targets[0].data_path = \
+ pb_parent.path_from_id() + '['+ '"' + prop.name + '"' + ']'
+
+ 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
+
+ # Create toe circle widget
+ create_circle_widget(self.obj, toes, radius=0.4, head_tail=0.5)
+
+ bones['ik']['ctrl']['terminal'] += [ toes ]
+
+ bones['ik']['ctrl']['terminal'] += [ heel, ctrl ]
+
+ return bones
+
+ # 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 create_drivers(self, bones):
+
+ bpy.ops.object.mode_set(mode ='OBJECT')
+ pb = self.obj.pose.bones
+
+ ctrl = pb[bones['ik']['ctrl']['terminal'][-1]]
+
+ props = [ "IK_follow", "root/parent" ]
+
+ for prop in props:
+ if prop == 'IK_follow':
+
+ ctrl[prop]=True
+ rna_prop = rna_idprop_ui_prop_get( ctrl, prop, create=True )
+ rna_prop["min"] = False
+ rna_prop["max"] = True
+ rna_prop["description"] = prop
+
+ drv = ctrl.constraints[ 0 ].driver_add("mute").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 = \
+ ctrl.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
+
+ drv = ctrl.constraints[ 1 ].driver_add("mute").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 = \
+ ctrl.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
+
+ else:
+ ctrl[prop]=0.0
+ rna_prop = rna_idprop_ui_prop_get( ctrl, prop, create=True )
+ rna_prop["min"] = 0.0
+ rna_prop["max"] = 1.0
+ rna_prop["soft_min"] = 0.0
+ rna_prop["soft_max"] = 1.0
+ rna_prop["description"] = prop
+
+ drv = ctrl.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 = \
+ ctrl.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
+
+ drv = ctrl.constraints[ 1 ].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 = \
+ ctrl.path_from_id() + '['+ '"' + prop + '"' + ']'
+
+
+ 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_leg( bones )
+ self.create_drivers( bones )
+
+ controls = [ bones['ik']['ctrl']['limb'], bones['ik']['ctrl']['terminal'][-1], bones['ik']['ctrl']['terminal'][-2] ]
+
+ # Create UI
+ controls_string = ", ".join(["'" + x + "'" for x in controls])
+
+ script = create_script( bones, 'leg' )
+ script += extra_script % (controls_string, bones['ik']['ctrl']['terminal'][-1], 'IK_follow', 'root/parent')
+
+ return [ script ]
+
+
+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 = 'leg'
+ # )
+
+ 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 get_future_names(bone):
+
+ list=[]
+
+ if '.L' in bone or '.R' in bone:
+ name = bone[:-2]
+ suffix = bone[-2:]
+
+ list.append(org(name) + suffix)
+ list.append(make_mechanism_name(name) + 'ik_stretch' + suffix)
+ list.append(make_deformer_name(name) + suffix)
+ list.append(name + '_fk' + suffix)
+ list.append(name + '_tweak' + suffix)
+
+ list.append(name + '_tweak' + suffix + '.001')
+ list.append(name + '_ik' + suffix)
+
+ return list
+
+
+def create_sample(obj):
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ for _ in range(28):
+ arm.rigify_layers.add()
+
+ arm.rigify_layers[13].name = 'Leg.L (IK)'
+ arm.rigify_layers[13].row = 10
+ arm.rigify_layers[14].name = 'Leg.L (FK)'
+ arm.rigify_layers[14].row = 11
+ arm.rigify_layers[15].name = 'Leg.L (Tweak)'
+ arm.rigify_layers[15].row = 12
+
+ bone = arm.edit_bones.new('thigh.L')
+ bone.head[:] = 0.0980, 0.0124, 1.0720
+ bone.tail[:] = 0.0980, -0.0286, 0.5372
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['thigh.L'] = bone.name
+ bone = arm.edit_bones.new('shin.L')
+ bone.head[:] = 0.0980, -0.0286, 0.5372
+ bone.tail[:] = 0.0980, 0.0162, 0.0852
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['thigh.L']]
+ bones['shin.L'] = bone.name
+ bone = arm.edit_bones.new('foot.L')
+ bone.head[:] = 0.0980, 0.0162, 0.0852
+ bone.tail[:] = 0.0980, -0.0934, 0.0167
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['shin.L']]
+ bones['foot.L'] = bone.name
+ bone = arm.edit_bones.new('toe.L')
+ bone.head[:] = 0.0980, -0.0934, 0.0167
+ bone.tail[:] = 0.0980, -0.1606, 0.0167
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['foot.L']]
+ bones['toe.L'] = bone.name
+ bone = arm.edit_bones.new('heel.02.L')
+ bone.head[:] = 0.0600, 0.0459, 0.0000
+ bone.tail[:] = 0.1400, 0.0459, 0.0000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['foot.L']]
+ bones['heel.02.L'] = bone.name
+
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['thigh.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, False, False, False, False, False, False, True, 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, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.limb_type = "leg"
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, False, 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]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, 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]
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['shin.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['foot.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['toe.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['heel.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'
+
+ 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
+
+ for eb in arm.edit_bones:
+ eb.layers = (False, False, False, False, 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)
+
+ arm.layers = (False, False, False, False, 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)
+
+
+if __name__ == "__main__":
+ create_sample(bpy.context.active_object) \ No newline at end of file