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!
This commit is contained in:
Nathan Vegdahl 2014-09-25 20:24:03 -07:00
parent fd695c3a81
commit c35610f163
25 changed files with 9264 additions and 33 deletions

View File

@ -382,6 +382,7 @@ def generate_rig(context, metarig):
# Create list of layer name/row pairs
layer_layout = []
for l in metarig.data.rigify_layers:
print( l.name )
layer_layout += [(l.name, l.row)]
# Generate the UI script

View File

@ -20,7 +20,6 @@
import bpy
def create(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')

File diff suppressed because it is too large Load Diff

View File

@ -56,12 +56,14 @@ if is_selected(fk_arm):
if is_selected(ik_arm):
layout.prop(pose_bones[ik_arm[2]], '["stretch_length"]', text="Length IK (" + ik_arm[2] + ")", slider=True)
layout.prop(pose_bones[ik_arm[2]], '["auto_stretch"]', text="Auto-Stretch IK (" + ik_arm[2] + ")", slider=True)
if is_selected([ik_arm[3]]):
layout.prop(pose_bones[ik_arm[3]], '["follow"]', text="Follow Parent (" + ik_arm[3] + ")", slider=True)
"""
hose_script = """
hose_arm = ["%s", "%s", "%s"]
hose_arm = ["%s", "%s", "%s", "%s", "%s"]
if is_selected(hose_arm):
layout.prop(pose_bones[hose_arm[1]], '["smooth_bend"]', text="Smooth Elbow (" + hose_arm[1] + ")", slider=True)
layout.prop(pose_bones[hose_arm[2]], '["smooth_bend"]', text="Smooth Elbow (" + hose_arm[2] + ")", slider=True)
"""
end_script = """
@ -104,7 +106,7 @@ class Rig:
ik_controls = self.ik_rig.generate()
ui_script = script % (fk_controls[0], fk_controls[1], fk_controls[2], ik_controls[0], ik_controls[1], ik_controls[2], ik_controls[3])
if self.params.use_complex_arm:
ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2])
ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2], hose_controls[3], hose_controls[4])
ui_script += end_script
return [ui_script]

View File

@ -59,7 +59,7 @@ class Rig:
pole_target_base_name = self.params.elbow_base_name + "_target"
# Arm is based on common limb
self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch)
self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], None, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch)
def generate(self):
""" Generate the rig.

View File

@ -60,12 +60,14 @@ if is_selected(fk_leg):
if is_selected(ik_leg):
layout.prop(pose_bones[ik_leg[2]], '["stretch_length"]', text="Length IK (" + ik_leg[2] + ")", slider=True)
layout.prop(pose_bones[ik_leg[2]], '["auto_stretch"]', text="Auto-Stretch IK (" + ik_leg[2] + ")", slider=True)
if is_selected([ik_leg[3]]):
layout.prop(pose_bones[ik_leg[3]], '["follow"]', text="Follow Foot (" + ik_leg[3] + ")", slider=True)
"""
hose_script = """
hose_leg = ["%s", "%s", "%s"]
hose_leg = ["%s", "%s", "%s", "%s", "%s"]
if is_selected(hose_leg):
layout.prop(pose_bones[hose_leg[1]], '["smooth_bend"]', text="Smooth Knee (" + hose_leg[1] + ")", slider=True)
layout.prop(pose_bones[hose_leg[2]], '["smooth_bend"]', text="Smooth Knee (" + hose_leg[2] + ")", slider=True)
"""
end_script = """
@ -108,7 +110,7 @@ class Rig:
ik_controls = self.ik_rig.generate()
ui_script = script % (fk_controls[0], fk_controls[1], fk_controls[2], fk_controls[3], ik_controls[0], ik_controls[1], ik_controls[2], ik_controls[3], ik_controls[4], ik_controls[5])
if self.params.use_complex_leg:
ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2])
ui_script += hose_script % (hose_controls[0], hose_controls[1], hose_controls[2], hose_controls[3], hose_controls[4])
ui_script += end_script
return [ui_script]

View File

@ -91,7 +91,7 @@ class Rig:
pole_target_base_name = self.params.knee_base_name + "_target"
# Leg is based on common limb
self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], pole_target_base_name, primary_rotation_axis, bend_hint, self.layers, ikfk_switch)
self.ik_limb = limb_common.IKLimb(obj, self.org_bones[0], self.org_bones[1], self.org_bones[2], self.org_bones[2], pole_target_base_name, primary_rotation_axis, bend_hint, self.layers, ikfk_switch)
def generate(self):
""" Generate the rig.

View File

@ -59,13 +59,15 @@ class FKLimb:
flimb = copy_bone(self.obj, self.org_bones[1], strip_org(insert_before_lr(self.org_bones[1], ".fk")))
elimb = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], ".fk")))
# Create the anti-stretch bones
fantistr = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_antistr.fk"))))
eantistr = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_antistr.fk"))))
# Create the end-limb mechanism bone
elimb_mch = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[2])))
# Create the anti-stretch bones
# These sit between a parent and its child, and counteract the
# stretching of the parent so that the child is unaffected
fantistr = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_antistr.fk"))))
eantistr = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_antistr.fk"))))
# Create the hinge bones
if parent != None:
socket1 = copy_bone(self.obj, ulimb, make_mechanism_name(ulimb + ".socket1"))
@ -297,7 +299,7 @@ class IKLimb:
""" An IK limb rig, with an optional ik/fk switch.
"""
def __init__(self, obj, bone1, bone2, bone3, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch=False):
def __init__(self, obj, bone1, bone2, bone3, pole_parent, pole_target_base_name, primary_rotation_axis, bend_hint, layers, ikfk_switch=False):
self.obj = obj
self.switch = ikfk_switch
@ -310,6 +312,8 @@ class IKLimb:
else:
self.org_parent = self.obj.data.bones[bone1].parent.name
self.pole_parent = pole_parent
# Get the rig parameters
self.pole_target_base_name = pole_target_base_name
self.layers = layers
@ -323,6 +327,8 @@ class IKLimb:
if self.org_parent != None:
loc = Vector(self.obj.data.edit_bones[self.org_bones[0]].head)
parent = make_nonscaling_child(self.obj, self.org_parent, loc, "_ik")
if self.pole_parent == None:
self.pole_parent = parent
else:
parent = None
@ -340,6 +346,10 @@ class IKLimb:
pole_target_name = self.pole_target_base_name + "." + insert_before_lr(self.org_bones[0], ".ik").split(".", 1)[1]
pole = copy_bone(self.obj, self.org_bones[0], pole_target_name)
if self.pole_parent == self.org_bones[2]:
self.pole_parent = elimb_mch
if self.pole_parent != None:
pole_par = copy_bone(self.obj, self.pole_parent, make_mechanism_name(insert_before_lr(pole_target_name, "_parent")))
viselimb = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], ".ik")))
vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole.ik")))
@ -358,6 +368,8 @@ class IKLimb:
ulimb_str_e = eb[ulimb_str]
flimb_str_e = eb[flimb_str]
pole_e = eb[pole]
if self.pole_parent != None:
pole_par_e = eb[pole_par]
viselimb_e = eb[viselimb]
vispole_e = eb[vispole]
@ -384,8 +396,9 @@ class IKLimb:
flimb_str_e.parent = ulimb_e.parent
pole_e.use_connect = False
if parent != None:
pole_e.parent = parent_e
if self.pole_parent != None:
pole_par_e.parent = None
pole_e.parent = pole_par_e
viselimb_e.use_connect = False
viselimb_e.parent = None
@ -418,6 +431,8 @@ class IKLimb:
pole_e.head = flimb_e.head + v2
pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
pole_e.roll = 0.0
if parent != None:
pole_par_e.length *= 0.75
viselimb_e.tail = viselimb_e.head + Vector((0, 0, v1.length / 32))
vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))
@ -440,6 +455,8 @@ class IKLimb:
ulimb_str_p = pb[ulimb_str]
flimb_str_p = pb[flimb_str]
pole_p = pb[pole]
if self.pole_parent != None:
pole_par_p = pb[pole_par]
viselimb_p = pb[viselimb]
vispole_p = pb[vispole]
@ -489,6 +506,12 @@ class IKLimb:
prop["soft_min"] = prop["min"] = 0.0
prop["soft_max"] = prop["max"] = 1.0
if self.pole_parent != None:
prop = rna_idprop_ui_prop_get(pole_p, "follow", create=True)
pole_p["follow"] = 1.0
prop["soft_min"] = prop["min"] = 0.0
prop["soft_max"] = prop["max"] = 1.0
prop = rna_idprop_ui_prop_get(elimb_p, "stretch_length", create=True)
elimb_p["stretch_length"] = 1.0
prop["min"] = 0.05
@ -618,6 +641,21 @@ class IKLimb:
con.name = "stretch"
con.owner_space = 'LOCAL'
# Pole target parent
if self.pole_parent != None:
con = pole_par_p.constraints.new('COPY_TRANSFORMS')
con.name = "parent"
con.target = self.obj
con.subtarget = self.pole_parent
driver = con.driver_add("influence").driver
var = driver.variables.new()
var.name = "follow"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = self.obj
var.targets[0].data_path = pole_p.path_from_id() + '["follow"]'
driver.type = 'SUM'
# Constrain org bones
con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
con.name = "ik"
@ -807,25 +845,34 @@ class RubberHoseLimb:
lr = lr[1]
# Create bones
# Deformation bones
ulimb1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(insert_before_lr(self.org_bones[0], ".01"))))
ulimb2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(insert_before_lr(self.org_bones[0], ".02"))))
flimb1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(insert_before_lr(self.org_bones[1], ".01"))))
flimb2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(insert_before_lr(self.org_bones[1], ".02"))))
elimb = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
# Bones for switchable smooth bbone transition at elbow/knee
ulimb2_smoother = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_smth.02"))))
flimb1_smoother = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_smth.01"))))
flimb1_pos = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".01"))))
# Elbow/knee junction bone
junc = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], ".junc"))))
# Hose controls
uhoseend = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[0], "_hose_end")))
uhose = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[0], "_hose")))
jhose = new_bone(self.obj, self.junc_base_name + "_hose." + lr)
fhose = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[1], "_hose")))
fhoseend = new_bone(self.obj, strip_org(insert_before_lr(self.org_bones[1], "_hose_end")))
uhose_par = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(uhose, "_parent"))))
jhose_par = copy_bone(self.obj, junc, make_mechanism_name(strip_org(insert_before_lr(jhose, "_parent"))))
fhose_par = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(fhose, "_parent"))))
# Hose control parents
uhoseend_par = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(uhoseend, "_p"))))
uhose_par = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(uhose, "_p"))))
jhose_par = copy_bone(self.obj, junc, make_mechanism_name(strip_org(insert_before_lr(jhose, "_p"))))
fhose_par = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(fhose, "_p"))))
fhoseend_par = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(fhoseend, "_p"))))
# Get edit bones
eb = self.obj.data.edit_bones
@ -847,13 +894,17 @@ class RubberHoseLimb:
junc_e = eb[junc]
uhoseend_e = eb[uhoseend]
uhose_e = eb[uhose]
jhose_e = eb[jhose]
fhose_e = eb[fhose]
fhoseend_e = eb[fhoseend]
uhoseend_par_e = eb[uhoseend_par]
uhose_par_e = eb[uhose_par]
jhose_par_e = eb[jhose_par]
fhose_par_e = eb[fhose_par]
fhoseend_par_e = eb[fhoseend_par]
# Parenting
if parent != None:
@ -884,6 +935,9 @@ class RubberHoseLimb:
junc_e.use_connect = False
junc_e.parent = eb[self.org_bones[0]]
uhoseend_e.use_connect = False
uhoseend_e.parent = uhoseend_par_e
uhose_e.use_connect = False
uhose_e.parent = uhose_par_e
@ -893,6 +947,12 @@ class RubberHoseLimb:
fhose_e.use_connect = False
fhose_e.parent = fhose_par_e
fhoseend_e.use_connect = False
fhoseend_e.parent = fhoseend_par_e
uhoseend_par_e.use_connect = False
uhoseend_par_e.parent = parent_e
uhose_par_e.use_connect = False
uhose_par_e.parent = parent_e
@ -902,6 +962,9 @@ class RubberHoseLimb:
fhose_par_e.use_connect = False
fhose_par_e.parent = parent_e
fhoseend_par_e.use_connect = False
fhoseend_par_e.parent = parent_e
# Positioning
ulimb1_e.length *= 0.5
ulimb2_e.head = Vector(ulimb1_e.tail)
@ -917,16 +980,22 @@ class RubberHoseLimb:
junc_e.length *= 0.2
uhoseend_par_e.length *= 0.25
uhose_par_e.length *= 0.25
jhose_par_e.length *= 0.15
fhose_par_e.length *= 0.25
fhoseend_par_e.length *= 0.25
put_bone(self.obj, uhoseend_par, Vector(ulimb1_e.head))
put_bone(self.obj, uhose_par, Vector(ulimb1_e.tail))
put_bone(self.obj, jhose_par, Vector(ulimb2_e.tail))
put_bone(self.obj, fhose_par, Vector(flimb1_e.tail))
put_bone(self.obj, fhoseend_par, Vector(flimb2_e.tail))
put_bone(self.obj, uhoseend, Vector(ulimb1_e.head))
put_bone(self.obj, uhose, Vector(ulimb1_e.tail))
put_bone(self.obj, jhose, Vector(ulimb2_e.tail))
put_bone(self.obj, fhose, Vector(flimb1_e.tail))
put_bone(self.obj, fhoseend, Vector(flimb2_e.tail))
if 'X' in self.primary_rotation_axis:
upoint = Vector(ulimb1_e.z_axis)
@ -949,18 +1018,24 @@ class RubberHoseLimb:
uside = Vector(ulimb1_e.y_axis) * -1
fside = Vector(flimb1_e.y_axis) * -1
uhoseend_e.tail = uhoseend_e.head + upoint
uhose_e.tail = uhose_e.head + upoint
jhose_e.tail = fhose_e.head + upoint + fpoint
fhose_e.tail = fhose_e.head + fpoint
fhoseend_e.tail = fhoseend_e.head + fpoint
align_bone_z_axis(self.obj, uhoseend, uside)
align_bone_z_axis(self.obj, uhose, uside)
align_bone_z_axis(self.obj, jhose, uside + fside)
align_bone_z_axis(self.obj, fhose, fside)
align_bone_z_axis(self.obj, fhoseend, fside)
l = 0.125 * (ulimb1_e.length + ulimb2_e.length + flimb1_e.length + flimb2_e.length)
uhoseend_e.length = l
uhose_e.length = l
jhose_e.length = l
fhose_e.length = l
fhoseend_e.length = l
# Object mode, get pose bones
bpy.ops.object.mode_set(mode='OBJECT')
@ -978,13 +1053,17 @@ class RubberHoseLimb:
junc_p = pb[junc]
uhoseend_p = pb[uhoseend]
uhose_p = pb[uhose]
jhose_p = pb[jhose]
fhose_p = pb[fhose]
fhoseend_p = pb[fhoseend]
#uhoseend_par_p = pb[uhoseend_par]
uhose_par_p = pb[uhose_par]
jhose_par_p = pb[jhose_par]
fhose_par_p = pb[fhose_par]
fhoseend_par_p = pb[fhoseend_par]
# Lock axes
uhose_p.lock_rotation = (True, True, True)
@ -1023,6 +1102,10 @@ class RubberHoseLimb:
prop["soft_max"] = prop["max"] = 1.0
# Constraints
con = ulimb1_p.constraints.new('COPY_LOCATION')
con.name = "anchor"
con.target = self.obj
con.subtarget = uhoseend
con = ulimb1_p.constraints.new('COPY_SCALE')
con.name = "anchor"
con.target = self.obj
@ -1112,11 +1195,11 @@ class RubberHoseLimb:
con = flimb2_p.constraints.new('DAMPED_TRACK')
con.name = "track"
con.target = self.obj
con.subtarget = self.org_bones[2]
con.subtarget = fhoseend
con = flimb2_p.constraints.new('STRETCH_TO')
con.name = "track"
con.target = self.obj
con.subtarget = self.org_bones[2]
con.subtarget = fhoseend
con.volume = 'NO_VOLUME'
con = junc_p.constraints.new('COPY_TRANSFORMS')
@ -1168,20 +1251,37 @@ class RubberHoseLimb:
con.subtarget = self.org_bones[2]
con.influence = 0.5
con = fhoseend_par_p.constraints.new('COPY_ROTATION')
con.name = "follow"
con.target = self.obj
con.subtarget = self.org_bones[1]
con.influence = 1.0
con = fhoseend_par_p.constraints.new('COPY_LOCATION')
con.name = "anchor"
con.target = self.obj
con.subtarget = self.org_bones[2]
con.influence = 1.0
# Layers
if self.layers:
uhoseend_p.bone.layers = self.layers
uhose_p.bone.layers = self.layers
jhose_p.bone.layers = self.layers
fhose_p.bone.layers = self.layers
fhoseend_p.bone.layers = self.layers
else:
layers = list(pb[self.org_bones[0]].bone.layers)
uhoseend_p.bone.layers = layers
uhose_p.bone.layers = layers
jhose_p.bone.layers = layers
fhose_p.bone.layers = layers
fhoseend_p.bone.layers = layers
# Create widgets
create_sphere_widget(self.obj, uhoseend)
create_sphere_widget(self.obj, uhose)
create_sphere_widget(self.obj, jhose)
create_sphere_widget(self.obj, fhose)
create_sphere_widget(self.obj, fhoseend)
return [uhose, jhose, fhose]
return [uhoseend, uhose, jhose, fhose, fhoseend]

View File

View File

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'
)

View File

@ -0,0 +1,350 @@
import bpy
from ...utils import copy_bone
from ...utils import strip_org, make_deformer_name, connected_children_names
from ...utils import make_mechanism_name, put_bone, create_sphere_widget
from ...utils import create_widget, create_circle_widget
from ...utils import MetarigError
from rna_prop_ui import rna_idprop_ui_prop_get
class Rig:
def __init__(self, obj, bone_name, params):
self.obj = obj
self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
self.params = params
self.copy_rotaion_axes = params.copy_rotaion_axes
if params.tweak_extra_layers:
self.tweak_layers = list( params.tweak_layers )
else:
self.tweak_layers = None
if len(self.org_bones) <= 1:
raise MetarigError(
"RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
)
def make_controls( self ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
ctrl_chain = []
for i in range( len( org_bones ) ):
name = org_bones[i]
ctrl_bone = copy_bone(
self.obj,
name,
strip_org(name)
)
ctrl_chain.append( ctrl_bone )
# Make widgets
bpy.ops.object.mode_set(mode ='OBJECT')
for ctrl in ctrl_chain:
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
return ctrl_chain
def make_tweaks( self ):
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
org_bones = self.org_bones
tweak_chain = []
for i in range( len( org_bones ) + 1 ):
if i == len( org_bones ):
# Make final tweak at the tip of the tentacle
name = org_bones[i-1]
else:
name = org_bones[i]
tweak_bone = copy_bone(
self.obj,
name,
"tweak_" + strip_org(name)
)
tweak_e = eb[ tweak_bone ]
tweak_e.length /= 2 # Set size to half
if i == len( org_bones ):
# Position final tweak at the tip
put_bone( self.obj, tweak_bone, eb[ org_bones[-1]].tail )
tweak_chain.append( tweak_bone )
# Make widgets
bpy.ops.object.mode_set(mode = 'OBJECT')
for tweak in tweak_chain:
create_sphere_widget( self.obj, tweak )
tweak_pb = self.obj.pose.bones[ tweak ]
# Set locks
if tweak_chain.index( tweak ) != len( tweak_chain ) - 1:
tweak_pb.lock_rotation = (True, False, True)
tweak_pb.lock_scale = (False, True, False)
else:
tweak_pb.lock_rotation_w = True
tweak_pb.lock_rotation = (True, True, True)
tweak_pb.lock_scale = (True, True, True)
# Set up tweak bone layers
if self.tweak_layers:
tweak_pb.bone.layers = self.tweak_layers
return tweak_chain
def make_deform( self ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
def_chain = []
for i in range( len( org_bones ) ):
name = org_bones[i]
def_bone = copy_bone(
self.obj,
name,
make_deformer_name(strip_org(name))
)
def_chain.append( def_bone )
return def_chain
def parent_bones( self, all_bones ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
eb = self.obj.data.edit_bones
# Parent control bones
for bone in all_bones['control'][1:]:
previous_index = all_bones['control'].index( bone ) - 1
eb[ bone ].parent = eb[ all_bones['control'][previous_index] ]
# Parent tweak bones
tweaks = all_bones['tweak']
for tweak in all_bones['tweak']:
parent = ''
if tweaks.index( tweak ) == len( tweaks ) - 1:
parent = all_bones['control'][ -1 ]
else:
parent = all_bones['control'][ tweaks.index( tweak ) ]
eb[ tweak ].parent = eb[ parent ]
# Parent deform bones
for bone in all_bones['deform'][1:]:
previous_index = all_bones['deform'].index( bone ) - 1
eb[ bone ].parent = eb[ all_bones['deform'][previous_index] ]
eb[ bone ].use_connect = True
# Parent org bones ( to tweaks by default, or to the controls )
for org, tweak in zip( org_bones, all_bones['tweak'] ):
eb[ org ].parent = eb[ tweak ]
def make_constraints( self, all_bones ):
bpy.ops.object.mode_set(mode ='OBJECT')
org_bones = self.org_bones
pb = self.obj.pose.bones
# Deform bones' constraints
ctrls = all_bones['control']
tweaks = all_bones['tweak' ]
deforms = all_bones['deform' ]
for deform, tweak, ctrl in zip( deforms, tweaks, ctrls ):
con = pb[deform].constraints.new('COPY_TRANSFORMS')
con.target = self.obj
con.subtarget = tweak
con = pb[deform].constraints.new('DAMPED_TRACK')
con.target = self.obj
con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
con = pb[deform].constraints.new('STRETCH_TO')
con.target = self.obj
con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
# Control bones' constraints
if ctrl != ctrls[0]:
con = pb[ctrl].constraints.new('COPY_ROTATION')
con.target = self.obj
con.subtarget = ctrls[ ctrls.index(ctrl) - 1 ]
for i, prop in enumerate( [ 'use_x', 'use_y', 'use_z' ] ):
if self.copy_rotaion_axes[i]:
setattr( con, prop, True )
else:
setattr( con, prop, False )
con.use_offset = True
con.target_space = 'LOCAL'
con.owner_space = 'LOCAL'
def generate(self):
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Clear all initial parenting
for bone in self.org_bones:
# eb[ bone ].parent = None
eb[ bone ].use_connect = False
# Creating all bones
ctrl_chain = self.make_controls()
tweak_chain = self.make_tweaks()
def_chain = self.make_deform()
all_bones = {
'control' : ctrl_chain,
'tweak' : tweak_chain,
'deform' : def_chain
}
self.make_constraints( all_bones )
self.parent_bones( all_bones )
def add_parameters(params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.copy_rotaion_axes = bpy.props.BoolVectorProperty(
size = 3,
description = "Layers for the tweak controls to be on",
default = tuple( [ i == 0 for i in range(0, 3) ] )
)
# Setting up extra tweak layers
params.tweak_extra_layers = bpy.props.BoolProperty(
name = "tweak_extra_layers",
default = True,
description = ""
)
params.tweak_layers = bpy.props.BoolVectorProperty(
size = 32,
description = "Layers for the tweak controls to be on",
default = tuple( [ i == 1 for i in range(0, 32) ] )
)
def parameters_ui(layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()
col = r.column(align=True)
row = col.row(align=True)
for i,axis in enumerate( [ 'x', 'y', 'z' ] ):
row.prop(params, "copy_rotaion_axes", index=i, toggle=True, text=axis)
r = layout.row()
r.prop(params, "tweak_extra_layers")
r.active = params.tweak_extra_layers
col = r.column(align=True)
row = col.row(align=True)
for i in range( 8 ): # Layers 0-7
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range( 16, 24 ): # Layers 16-23
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
col = r.column(align=True)
row = col.row(align=True)
for i in range( 8, 16 ): # Layers 8-15
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range( 24, 32 ): # Layers 24-31
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
def create_sample(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bones = {}
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 0.3333
bone.roll = 0.0000
bone.use_connect = False
bones['Bone'] = bone.name
bone = arm.edit_bones.new('Bone.002')
bone.head[:] = 0.0000, 0.0000, 0.3333
bone.tail[:] = 0.0000, 0.0000, 0.6667
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['Bone']]
bones['Bone.002'] = bone.name
bone = arm.edit_bones.new('Bone.001')
bone.head[:] = 0.0000, 0.0000, 0.6667
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['Bone.002']]
bones['Bone.001'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['Bone']]
pbone.rigify_type = 'pitchipoy.simple_tentacle'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['Bone.002']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['Bone.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone.select = False
bone.select_head = False
bone.select_tail = False
for b in bones:
bone = arm.edit_bones[bones[b]]
bone.select = True
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone

View File

@ -0,0 +1,159 @@
#====================== BEGIN GPL LICENSE BLOCK ======================
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#======================= END GPL LICENSE BLOCK ========================
# <pep8 compliant>
import bpy
from ...utils import copy_bone
from ...utils import strip_org, make_deformer_name
from ...utils import create_bone_widget, create_circle_widget
class Rig:
""" A "copy" rig. All it does is duplicate the original bone and
constrain it.
This is a control and deformation rig.
"""
def __init__(self, obj, bone, params):
""" Gather and validate data about the rig.
"""
self.obj = obj
self.org_bone = bone
self.org_name = strip_org(bone)
self.params = params
self.make_control = params.make_control
self.make_widget = params.make_widget
self.make_deform = params.make_deform
def generate(self):
""" Generate the rig.
Do NOT modify any of the original bones, except for adding constraints.
The main armature should be selected and active before this is called.
"""
bpy.ops.object.mode_set(mode='EDIT')
# Make a control bone (copy of original).
if self.make_control:
bone = copy_bone(self.obj, self.org_bone, self.org_name)
# Make a deformation bone (copy of original, child of original).
if self.make_deform:
def_bone = copy_bone(self.obj, self.org_bone, make_deformer_name(self.org_name))
# Get edit bones
eb = self.obj.data.edit_bones
# UNUSED
# if self.make_control:
# bone_e = eb[bone]
if self.make_deform:
def_bone_e = eb[def_bone]
# Parent
if self.make_deform:
def_bone_e.use_connect = False
def_bone_e.parent = eb[self.org_bone]
bpy.ops.object.mode_set(mode='OBJECT')
pb = self.obj.pose.bones
if self.make_control:
# Constrain the original bone.
con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS')
con.name = "copy_transforms"
con.target = self.obj
con.subtarget = bone
# Create control widget
if self.make_widget:
create_circle_widget(self.obj, bone, radius = 0.5 )
else:
create_bone_widget(self.obj, bone, radius = 0.5 )
def add_parameters(params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.make_control = bpy.props.BoolProperty(
name = "Control",
default = True,
description = "Create a control bone for the copy"
)
params.make_widget = bpy.props.BoolProperty(
name = "Widget",
default = True,
description = "Choose a widget for the bone control"
)
params.make_deform = bpy.props.BoolProperty(
name = "Deform",
default = True,
description = "Create a deform bone for the copy"
)
def parameters_ui(layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()
r.prop(params, "make_control")
r = layout.row()
r.prop(params, "make_widget")
r = layout.row()
r.prop(params, "make_deform")
def create_sample(obj):
""" Create a sample metarig for this rig type.
"""
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bones = {}
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 0.2000
bone.roll = 0.0000
bone.use_connect = False
bones['Bone'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['Bone']]
pbone.rigify_type = 'basic.copy'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone.select = False
bone.select_head = False
bone.select_tail = False
for b in bones:
bone = arm.edit_bones[bones[b]]
bone.select = True
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,414 @@
import bpy
from mathutils import Vector
from ...utils import copy_bone, flip_bone
from ...utils import strip_org, make_deformer_name, connected_children_names, make_mechanism_name
from ...utils import create_circle_widget, create_sphere_widget, create_widget
from ...utils import MetarigError
from rna_prop_ui import rna_idprop_ui_prop_get
script = """
controls = [%s]
master_name = '%s'
if is_selected(controls):
layout.prop(pose_bones[master_name], '["%s"]', text="Curvature", slider=True)
"""
class Rig:
def __init__(self, obj, bone_name, params):
self.obj = obj
self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
self.params = params
if len(self.org_bones) <= 1:
raise MetarigError("RIGIFY ERROR: Bone '%s': listen bro, that finger rig jusaint put tugetha rite. A little hint, use more than one bone!!" % (strip_org(bone_name)))
def generate(self):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Bone name lists
ctrl_chain = []
def_chain = []
mch_chain = []
mch_drv_chain = []
# Create ctrl master bone
org_name = self.org_bones[0]
temp_name = strip_org(self.org_bones[0])
suffix = temp_name[-2:]
master_name = temp_name[:-5] + "_master" + suffix
master_name = copy_bone( self.obj, org_name, master_name )
ctrl_bone_master = eb[ master_name ]
## Parenting bug fix ??
ctrl_bone_master.use_connect = False
ctrl_bone_master.parent = None
ctrl_bone_master.tail += ( eb[ org_bones[-1] ].tail - eb[org_name].head ) * 1.25
for bone in org_bones:
eb[bone].use_connect = False
if org_bones.index( bone ) != 0:
eb[bone].parent = None
# Creating the bone chains
for i in range(len(self.org_bones)):
name = self.org_bones[i]
ctrl_name = strip_org(name)
# Create control bones
ctrl_bone = copy_bone( self.obj, name, ctrl_name )
ctrl_bone_e = eb[ ctrl_name ]
# Create deformation bones
def_name = make_deformer_name( ctrl_name )
def_bone = copy_bone( self.obj, name, def_name )
# Create mechanism bones
mch_name = make_mechanism_name( ctrl_name )
mch_bone = copy_bone( self.obj, name, mch_name )
# Create mechanism driver bones
drv_name = make_mechanism_name(ctrl_name) + "_drv"
mch_bone_drv = copy_bone(self.obj, name, drv_name)
mch_bone_drv_e = eb[drv_name]
# Adding to lists
ctrl_chain += [ctrl_name]
def_chain += [def_bone]
mch_chain += [mch_bone]
mch_drv_chain += [drv_name]
# Restoring org chain parenting
for bone in org_bones[1:]:
eb[bone].parent = eb[ org_bones[ org_bones.index(bone) - 1 ] ]
# Parenting the master bone to the first org
ctrl_bone_master = eb[ master_name ]
ctrl_bone_master.parent = eb[ org_bones[0] ]
# Parenting chain bones
for i in range(len(self.org_bones)):
# Edit bone references
def_bone_e = eb[def_chain[i]]
ctrl_bone_e = eb[ctrl_chain[i]]
mch_bone_e = eb[mch_chain[i]]
mch_bone_drv_e = eb[mch_drv_chain[i]]
if i == 0:
# First ctl bone
ctrl_bone_e.parent = mch_bone_drv_e
ctrl_bone_e.use_connect = False
# First def bone
def_bone_e.parent = eb[self.org_bones[i]].parent
def_bone_e.use_connect = False
# First mch bone
mch_bone_e.parent = eb[self.org_bones[i]].parent
mch_bone_e.use_connect = False
# First mch driver bone
mch_bone_drv_e.parent = eb[self.org_bones[i]].parent
mch_bone_drv_e.use_connect = False
else:
# The rest
ctrl_bone_e.parent = mch_bone_drv_e
ctrl_bone_e.use_connect = False
def_bone_e.parent = eb[def_chain[i-1]]
def_bone_e.use_connect = True
mch_bone_drv_e.parent = eb[ctrl_chain[i-1]]
mch_bone_drv_e.use_connect = False
# Parenting mch bone
mch_bone_e.parent = ctrl_bone_e
mch_bone_e.use_connect = False
# Creating tip conrtol bone
tip_name = copy_bone( self.obj, org_bones[-1], temp_name )
ctrl_bone_tip = eb[ tip_name ]
flip_bone( self.obj, tip_name )
ctrl_bone_tip.length /= 2
ctrl_bone_tip.parent = eb[ctrl_chain[-1]]
bpy.ops.object.mode_set(mode ='OBJECT')
pb = self.obj.pose.bones
# Setting pose bones locks
pb_master = pb[master_name]
pb_master.lock_scale = True,False,True
pb[tip_name].lock_scale = True,True,True
pb[tip_name].lock_rotation = True,True,True
pb[tip_name].lock_rotation_w = True
pb_master['finger_curve'] = 0.0
prop = rna_idprop_ui_prop_get(pb_master, 'finger_curve')
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["description"] = "Rubber hose finger cartoon effect"
# Pose settings
for org, ctrl, deform, mch, mch_drv in zip(self.org_bones, ctrl_chain, def_chain, mch_chain, mch_drv_chain):
# Constraining the org bones
#con = pb[org].constraints.new('COPY_TRANSFORMS')
#con.target = self.obj
#con.subtarget = ctrl
# Constraining the deform bones
con = pb[deform].constraints.new('COPY_TRANSFORMS')
con.target = self.obj
con.subtarget = mch
# Constraining the mch bones
if mch_chain.index(mch) == 0:
con = pb[mch].constraints.new('COPY_LOCATION')
con.target = self.obj
con.subtarget = ctrl
con = pb[mch].constraints.new('COPY_SCALE')
con.target = self.obj
con.subtarget = ctrl
con = pb[mch].constraints.new('DAMPED_TRACK')
con.target = self.obj
con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
con = pb[mch].constraints.new('STRETCH_TO')
con.target = self.obj
con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
con.volume = 'NO_VOLUME'
elif mch_chain.index(mch) == len(mch_chain) - 1:
con = pb[mch].constraints.new('DAMPED_TRACK')
con.target = self.obj
con.subtarget = tip_name
con = pb[mch].constraints.new('STRETCH_TO')
con.target = self.obj
con.subtarget = tip_name
con.volume = 'NO_VOLUME'
else:
con = pb[mch].constraints.new('DAMPED_TRACK')
con.target = self.obj
con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
con = pb[mch].constraints.new('STRETCH_TO')
con.target = self.obj
con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1]
con.volume = 'NO_VOLUME'
# Constraining and driving mch driver bones
pb[mch_drv].rotation_mode = 'YZX'
if mch_drv_chain.index(mch_drv) == 0:
# Constraining to master bone
con = pb[mch_drv].constraints.new('COPY_LOCATION')
con.target = self.obj
con.subtarget = master_name
con = pb[mch_drv].constraints.new('COPY_ROTATION')
con.target = self.obj
con.subtarget = master_name
con.target_space = 'LOCAL'
con.owner_space = 'LOCAL'
else:
# Match axis to expression
options = {
"X" : { "axis" : 0,
"expr" : '(1-sy)*pi' },
"-X" : { "axis" : 0,
"expr" : '-((1-sy)*pi)' },
"Y" : { "axis" : 1,
"expr" : '(1-sy)*pi' },
"-Y" : { "axis" : 1,
"expr" : '-((1-sy)*pi)' },
"Z" : { "axis" : 2,
"expr" : '(1-sy)*pi' },
"-Z" : { "axis" : 2,
"expr" : '-((1-sy)*pi)' }
}
axis = self.params.primary_rotation_axis
# Drivers
drv = pb[mch_drv].driver_add("rotation_euler", options[axis]["axis"]).driver
drv.type = 'SCRIPTED'
drv.expression = options[axis]["expr"]
drv_var = drv.variables.new()
drv_var.name = 'sy'
drv_var.type = "SINGLE_PROP"
drv_var.targets[0].id = self.obj
drv_var.targets[0].data_path = pb[master_name].path_from_id() + '.scale.y'
# Setting bone curvature setting, costum property, and drivers
def_bone = self.obj.data.bones[deform]
def_bone.bbone_segments = 8
drv = def_bone.driver_add("bbone_in").driver # Ease in
drv.type='SUM'
drv_var = drv.variables.new()
drv_var.name = "curvature"
drv_var.type = "SINGLE_PROP"
drv_var.targets[0].id = self.obj
drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]'
drv = def_bone.driver_add("bbone_out").driver # Ease out
drv.type='SUM'
drv_var = drv.variables.new()
drv_var.name = "curvature"
drv_var.type = "SINGLE_PROP"
drv_var.targets[0].id = self.obj
drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]'
# Assigning shapes to control bones
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
# Create ctrl master widget
w = create_widget(self.obj, master_name)
if w != None:
mesh = w.data
verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)]
if 'Z' in self.params.primary_rotation_axis:
# Flip x/z coordinates
temp = []
for v in verts:
temp += [(v[2], v[1], v[0])]
verts = temp
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)]
mesh.from_pydata(verts, edges, [])
mesh.update()
# Create tip control widget
create_circle_widget(self.obj, tip_name, radius=0.3, head_tail=0.0)
# Create UI
controls_string = ", ".join(
["'" + x + "'" for x in ctrl_chain]
) + ", " + "'" + master_name + "'"
return [script % (controls_string, master_name, 'finger_curve')]
def add_parameters(params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
def parameters_ui(layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()
r.label(text="Bend rotation axis:")
r.prop(params, "primary_rotation_axis", text="")
def create_sample(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bones = {}
bone = arm.edit_bones.new('palm.04.L')
bone.head[:] = 0.0043, -0.0030, -0.0026
bone.tail[:] = 0.0642, 0.0037, -0.0469
bone.roll = -2.5155
bone.use_connect = False
bones['palm.04.L'] = bone.name
bone = arm.edit_bones.new('f_pinky.01.L')
bone.head[:] = 0.0642, 0.0037, -0.0469
bone.tail[:] = 0.0703, 0.0039, -0.0741
bone.roll = -1.9749
bone.use_connect = False
bone.parent = arm.edit_bones[bones['palm.04.L']]
bones['f_pinky.01.L'] = bone.name
bone = arm.edit_bones.new('f_pinky.02.L')
bone.head[:] = 0.0703, 0.0039, -0.0741
bone.tail[:] = 0.0732, 0.0044, -0.0965
bone.roll = -1.9059
bone.use_connect = True
bone.parent = arm.edit_bones[bones['f_pinky.01.L']]
bones['f_pinky.02.L'] = bone.name
bone = arm.edit_bones.new('f_pinky.03.L')
bone.head[:] = 0.0732, 0.0044, -0.0965
bone.tail[:] = 0.0725, 0.0046, -0.1115
bone.roll = -1.7639
bone.use_connect = True
bone.parent = arm.edit_bones[bones['f_pinky.02.L']]
bones['f_pinky.03.L'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['palm.04.L']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'YXZ'
pbone = obj.pose.bones[bones['f_pinky.01.L']]
pbone.rigify_type = 'pitchipoy.simple_tentacle'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
pbone.rigify_parameters.separate_extra_layers = True
except AttributeError:
pass
try:
pbone.rigify_parameters.extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
pbone.rigify_parameters.tweak_extra_layers = False
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_pinky.02.L']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['f_pinky.03.L']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone.select = False
bone.select_head = False
bone.select_tail = False
for b in bones:
bone = arm.edit_bones[bones[b]]
bone.select = True
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone

View File

@ -0,0 +1,901 @@
import bpy
from mathutils import Vector
from ...utils import copy_bone, flip_bone, put_bone, org
from ...utils import strip_org, make_deformer_name, connected_children_names
from ...utils import create_circle_widget, create_sphere_widget, create_widget
from ...utils import MetarigError, make_mechanism_name, create_cube_widget
from rna_prop_ui import rna_idprop_ui_prop_get
script = """
controls = [%s]
torso = '%s'
if is_selected( controls ):
layout.prop( pose_bones[ torso ], '["%s"]', slider = True )
layout.prop( pose_bones[ torso ], '["%s"]', slider = True )
"""
class Rig:
def __init__(self, obj, bone_name, params):
""" Initialize torso rig and key rig properties """
eb = obj.data.edit_bones
self.obj = obj
self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
self.params = params
self.spine_length = sum( [ eb[b].length for b in self.org_bones ] )
# Check if user provided the positions of the neck and pivot
if params.neck_pos and params.pivot_pos:
self.neck_pos = params.neck_pos
self.pivot_pos = params.pivot_pos
else:
raise MetarigError(
"RIGIFY ERROR: please specify neck and pivot bone positions"
)
# Check if neck is lower than pivot
if params.neck_pos <= params.pivot_pos:
raise MetarigError(
"RIGIFY ERROR: Neck cannot be below or the same as pivot"
)
# TODO:
# Limit neck_pos prop to 1 --> num of bones - 1 (last is head)
# Limit pivot_pos prop to 2 --> num of bones (must leave place for lower torso)
if params.tail_pos:
self.tail_pos = params.tail_pos
# Assign values to tweak layers props if opted by user
if params.tweak_extra_layers:
self.tweak_layers = list(params.tweak_layers)
else:
self.tweak_layers = None
# Report error of user created less than the minimum of 4 bones for rig
if len(self.org_bones) <= 4:
raise MetarigError(
"RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
)
def build_bone_structure( self ):
""" Divide meta-rig into lists of bones according to torso rig anatomy:
Neck --> Upper torso --> Lower torso --> Tail (optional) """
if self.pivot_pos and self.neck_pos:
neck_index = self.neck_pos - 1
pivot_index = self.pivot_pos - 1
tail_index = 0
if 'tail_pos' in dir(self):
tail_index = self.tail_pos - 1
neck_bones = self.org_bones[neck_index::]
upper_torso_bones = self.org_bones[pivot_index:neck_index]
lower_torso_bones = self.org_bones[tail_index:pivot_index]
tail_bones = []
if tail_index:
tail_bones = self.org_bones[::tail_index+1]
return {
'neck' : neck_bones,
'upper' : upper_torso_bones,
'lower' : lower_torso_bones,
'tail' : tail_bones
}
else:
return 'ERROR'
def orient_bone( self, eb, axis, scale, reverse = False ):
v = Vector((0,0,0))
setattr(v,axis,scale)
if reverse:
tail_vec = v * self.obj.matrix_world
eb.head[:] = eb.tail
eb.tail[:] = eb.head + tail_vec
else:
tail_vec = v * self.obj.matrix_world
eb.tail[:] = eb.head + tail_vec
def create_pivot( self, pivot ):
""" Create the pivot control and mechanism bones """
org_bones = self.org_bones
pivot_name = org_bones[pivot-1]
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Create torso control bone
torso_name = 'torso'
ctrl_name = copy_bone(self.obj, pivot_name, torso_name)
ctrl_eb = eb[ ctrl_name ]
self.orient_bone( ctrl_eb, 'y', self.spine_length / 2.5 )
# Create mch_pivot
mch_name = make_mechanism_name( 'pivot' )
mch_name = copy_bone(self.obj, ctrl_name, mch_name)
mch_eb = eb[ mch_name ]
mch_eb.length /= 4
# Positioning pivot in a more usable location for animators
pivot_loc = ( eb[ org_bones[0]].head + eb[ org_bones[0]].tail ) / 2
put_bone( self.obj, ctrl_name, pivot_loc )
return {
'ctrl' : ctrl_name,
'mch' : mch_name
}
def create_deform( self ):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
def_bones = []
for org in org_bones:
def_name = make_deformer_name( strip_org( org ) )
def_name = copy_bone( self.obj, org, def_name )
def_bones.append( def_name )
return def_bones
def create_neck( self, neck_bones ):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Create neck control
neck = copy_bone( self.obj, org(neck_bones[0]), 'neck' )
neck_eb = eb[ neck ]
# Neck spans all neck bones (except head)
neck_eb.tail[:] = eb[ org(neck_bones[-1]) ].head
# Create head control
head = copy_bone( self.obj, org(neck_bones[-1]), 'head' )
# MCH bones
# Neck MCH stretch
mch_str = copy_bone( self.obj, neck, make_mechanism_name('STR-neck') )
# Neck MCH rotation
mch_neck = copy_bone(
self.obj, neck, make_mechanism_name('ROT-neck')
)
self.orient_bone( eb[mch_neck], 'y', self.spine_length / 10 )
# Head MCH rotation
mch_head = copy_bone(
self.obj, head, make_mechanism_name('ROT-head')
)
self.orient_bone( eb[mch_head], 'y', self.spine_length / 10 )
twk,mch = [],[]
# Intermediary bones
for b in neck_bones[1:-1]: # All except 1st neck and (last) head
mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
eb[mch_name].length /= 4
mch += [ mch_name ]
# Tweak bones
for b in neck_bones[:-1]: # All except last bone
twk_name = "tweak_" + b
twk_name = copy_bone( self.obj, org(b), twk_name )
eb[twk_name].length /= 2
twk += [ twk_name ]
return {
'ctrl_neck' : neck,
'ctrl' : head,
'mch_str' : mch_str,
'mch_neck' : mch_neck,
'mch_head' : mch_head,
'mch' : mch,
'tweak' : twk
}
def create_chest( self, chest_bones ):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# get total spine length
# Create chest control bone
chest = copy_bone( self.obj, org( chest_bones[0] ), 'chest' )
self.orient_bone( eb[chest], 'y', self.spine_length / 3 )
# create chest mch_wgt
mch_wgt = copy_bone(
self.obj, org( chest_bones[-1] ),
make_mechanism_name( 'WGT-chest' )
)
# Create mch and twk bones
twk,mch = [],[]
for b in chest_bones:
mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
self.orient_bone( eb[mch_name], 'y', self.spine_length / 10 )
twk_name = "tweak_" + b
twk_name = copy_bone( self.obj, org(b), twk_name )
eb[twk_name].length /= 2
mch += [ mch_name ]
twk += [ twk_name ]
return {
'ctrl' : chest,
'mch' : mch,
'tweak' : twk,
'mch_wgt' : mch_wgt
}
def create_hips( self, hip_bones ):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Create hips control bone
hips = copy_bone( self.obj, org( hip_bones[-1] ), 'hips' )
self.orient_bone(
eb[hips],
'y',
self.spine_length / 4,
reverse = True
)
# create hips mch_wgt
mch_wgt = copy_bone(
self.obj, org( hip_bones[0] ),
make_mechanism_name( 'WGT-hips' )
)
# Create mch and tweak bones
twk,mch = [],[]
for b in hip_bones:
mch_name = copy_bone( self.obj, org(b), make_mechanism_name(b) )
self.orient_bone(
eb[mch_name], 'y', self.spine_length / 10, reverse = True
)
twk_name = "tweak_" + b
twk_name = copy_bone( self.obj, org( b ), twk_name )
eb[twk_name].length /= 2
mch += [ mch_name ]
twk += [ twk_name ]
return {
'ctrl' : hips,
'mch' : mch,
'tweak' : twk,
'mch_wgt' : mch_wgt
}
def create_tail( self, tail_bones ):
pass
def parent_bones( self, bones ):
org_bones = self.org_bones
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Parent deform bones
for i,b in enumerate( bones['def'] ):
if i > 0: # For all bones but the first (which has no parent)
eb[b].parent = eb[ bones['def'][i-1] ] # to previous
eb[b].use_connect = True
# Parent control bones
# Head control => MCH-rotation_head
eb[ bones['neck']['ctrl'] ].parent = eb[ bones['neck']['mch_head'] ]
# MCH stretch => neck ctrl
eb[ bones['neck']['mch_str'] ].parent = eb[ bones['neck']['ctrl_neck'] ]
# Neck control => MCH-rotation_neck
eb[ bones['neck']['ctrl_neck'] ].parent = eb[ bones['neck']['mch_neck'] ]
# Parent hips and chest controls to torso
eb[ bones['chest']['ctrl'] ].parent = eb[ bones['pivot']['ctrl'] ]
eb[ bones['hips']['ctrl'] ].parent = eb[ bones['pivot']['ctrl'] ]
# Parent mch bones
# Neck mch
eb[ bones['neck']['mch_head'] ].parent = eb[ bones['neck']['ctrl_neck'] ]
parent = eb[ bones['neck']['mch_str'] ]
for i,b in enumerate([ eb[n] for n in bones['neck']['mch'] ]):
b.parent = parent
# Chest mch bones and neck mch
chest_mch = bones['chest']['mch'] + [ bones['neck']['mch_neck'] ]
for i,b in enumerate(chest_mch):
if i == 0:
eb[b].parent = eb[ bones['pivot']['ctrl'] ]
else:
eb[b].parent = eb[ chest_mch[i-1] ]
# Hips mch bones
for i,b in enumerate( bones['hips']['mch'] ):
if i == len(bones['hips']['mch']) - 1:
eb[b].parent = eb[ bones['pivot']['ctrl'] ]
else:
eb[b].parent = eb[ bones['hips']['mch'][i+1] ]
# mch pivot
eb[ bones['pivot']['mch'] ].parent = eb[ bones['chest']['mch'][0] ]
# MCH widgets
eb[ bones['chest']['mch_wgt'] ].parent = eb[ bones['chest']['mch'][-1] ]
eb[ bones['hips' ]['mch_wgt'] ].parent = eb[ bones['hips' ]['mch'][0 ] ]
# Tweaks
# Neck tweaks
for i,twk in enumerate( bones['neck']['tweak'] ):
if i == 0:
eb[ twk ].parent = eb[ bones['neck']['ctrl_neck'] ]
else:
eb[ twk ].parent = eb[ bones['neck']['mch'][i-1] ]
# Chest tweaks
for twk,mch in zip( bones['chest']['tweak'], bones['chest']['mch'] ):
if bones['chest']['tweak'].index( twk ) == 0:
eb[ twk ].parent = eb[ bones['pivot']['mch'] ]
else:
eb[ twk ].parent = eb[ mch ]
# Hips tweaks
for i,twk in enumerate(bones['hips']['tweak']):
if i == 0:
eb[twk].parent = eb[ bones['hips']['mch'][i] ]
else:
eb[twk].parent = eb[ bones['hips']['mch'][i-1] ]
# Parent orgs to matching tweaks
tweaks = bones['hips']['tweak'] + bones['chest']['tweak']
tweaks += bones['neck']['tweak'] + [ bones['neck']['ctrl'] ]
if 'tail' in bones.keys():
tweaks += bones['tail']['tweak']
for org, twk in zip( org_bones, tweaks ):
eb[ org ].parent = eb[ twk ]
def make_constraint( self, bone, constraint ):
bpy.ops.object.mode_set(mode = 'OBJECT')
pb = self.obj.pose.bones
owner_pb = pb[bone]
const = owner_pb.constraints.new( constraint['constraint'] )
const.target = self.obj
# filter contraint props to those that actually exist in the currnet
# type of constraint, then assign values to each
for p in [ k for k in constraint.keys() if k in dir(const) ]:
setattr( const, p, constraint[p] )
def constrain_bones( self, bones ):
# MCH bones
# head and neck MCH bones
for b in [ bones['neck']['mch_head'], bones['neck']['mch_neck'] ]:
self.make_constraint( b, {
'constraint' : 'COPY_ROTATION',
'subtarget' : bones['pivot']['ctrl'],
} )
self.make_constraint( b, {
'constraint' : 'COPY_SCALE',
'subtarget' : bones['pivot']['ctrl'],
} )
# Neck MCH Stretch
self.make_constraint( bones['neck']['mch_str'], {
'constraint' : 'DAMPED_TRACK',
'subtarget' : bones['neck']['ctrl'],
})
self.make_constraint( bones['neck']['mch_str'], {
'constraint' : 'STRETCH_TO',
'subtarget' : bones['neck']['ctrl'],
})
# Intermediary mch bones
intermediaries = [ bones['neck'], bones['chest'], bones['hips'] ]
if 'tail' in bones.keys():
intermediaries += bones['tail']
for i,l in enumerate(intermediaries):
mch = l['mch']
factor = float( 1 / len( l['tweak'] ) )
for j,b in enumerate(mch):
if i == 0:
nfactor = float( (j + 1) / len( mch ) )
self.make_constraint( b, {
'constraint' : 'COPY_ROTATION',
'subtarget' : l['ctrl'],
'influence' : nfactor
} )
else:
self.make_constraint( b, {
'constraint' : 'COPY_TRANSFORMS',
'subtarget' : l['ctrl'],
'influence' : factor,
'owner_space' : 'LOCAL',
'target_space' : 'LOCAL'
} )
# MCH pivot
self.make_constraint( bones['pivot']['mch'], {
'constraint' : 'COPY_TRANSFORMS',
'subtarget' : bones['hips']['mch'][-1],
'owner_space' : 'LOCAL',
'target_space' : 'LOCAL'
})
# DEF bones
deform = bones['def']
tweaks = bones['hips']['tweak'] + bones['chest']['tweak']
tweaks += bones['neck']['tweak'] + [ bones['neck']['ctrl'] ]
for d,t in zip(deform, tweaks):
tidx = tweaks.index(t)
self.make_constraint( d, {
'constraint' : 'COPY_TRANSFORMS',
'subtarget' : t
})
if tidx != len(tweaks) - 1:
self.make_constraint( d, {
'constraint' : 'DAMPED_TRACK',
'subtarget' : tweaks[ tidx + 1 ],
})
self.make_constraint( d, {
'constraint' : 'STRETCH_TO',
'subtarget' : tweaks[ tidx + 1 ],
})
def create_drivers( self, bones ):
bpy.ops.object.mode_set(mode ='OBJECT')
pb = self.obj.pose.bones
# Setting the torso's props
torso = pb[ bones['pivot']['ctrl'] ]
props = [ "head_follow", "neck_follow" ]
owners = [ bones['neck']['mch_head'], bones['neck']['mch_neck'] ]
for prop in props:
if prop == 'neck_follow':
torso[prop] = 0.5
else:
torso[prop] = 0.0
prop = rna_idprop_ui_prop_get( torso, prop, create=True )
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["description"] = prop
# driving the follow rotation switches for neck and head
for bone, prop, in zip( owners, props ):
# Add driver to copy rotation constraint
drv = pb[ bone ].constraints[ 0 ].driver_add("influence").driver
drv.type = 'AVERAGE'
var = drv.variables.new()
var.name = prop
var.type = "SINGLE_PROP"
var.targets[0].id = self.obj
var.targets[0].data_path = \
torso.path_from_id() + '['+ '"' + prop + '"' + ']'
drv_modifier = self.obj.animation_data.drivers[-1].modifiers[0]
drv_modifier.mode = 'POLYNOMIAL'
drv_modifier.poly_order = 1
drv_modifier.coefficients[0] = 1.0
drv_modifier.coefficients[1] = -1.0
def locks_and_widgets( self, bones ):
bpy.ops.object.mode_set(mode ='OBJECT')
pb = self.obj.pose.bones
# deform bones bbone segements
for bone in bones['def'][:-1]:
self.obj.data.bones[bone].bbone_segments = 8
self.obj.data.bones[ bones['def'][0] ].bbone_in = 0.0
self.obj.data.bones[ bones['def'][-2] ].bbone_out = 0.0
# Locks
tweaks = bones['neck']['tweak'] + bones['chest']['tweak']
tweaks += bones['hips']['tweak']
if 'tail' in bones.keys():
tweaks += bones['tail']['tweak']
# Tweak bones locks
for bone in tweaks:
pb[bone].lock_rotation = True, False, True
pb[bone].lock_scale = False, True, False
# Widgets
# Assigning a widget to torso bone
create_cube_widget(
self.obj,
bones['pivot']['ctrl'],
radius = 0.5,
bone_transform_name = None
)
# Assigning widgets to control bones
gen_ctrls = [
bones['neck']['ctrl_neck'],
bones['chest']['ctrl'],
bones['hips']['ctrl']
]
if 'tail' in bones.keys():
gen_ctrls += [ bones['tail']['ctrl'] ]
for bone in gen_ctrls:
create_circle_widget(
self.obj,
bone,
radius = 1.0,
head_tail = 0.5,
with_line = False,
bone_transform_name = None
)
# Head widget
create_circle_widget(
self.obj,
bones['neck']['ctrl'],
radius = 0.75,
head_tail = 1.0,
with_line = False,
bone_transform_name = None
)
# place widgets on correct bones
chest_widget_loc = pb[ bones['chest']['mch_wgt'] ]
pb[ bones['chest']['ctrl'] ].custom_shape_transform = chest_widget_loc
hips_widget_loc = pb[ bones['hips']['mch_wgt'] ]
if 'tail' in bones.keys():
hips_widget_loc = bones['def'][self.tail_pos -1]
pb[ bones['hips']['ctrl'] ].custom_shape_transform = hips_widget_loc
# Assigning widgets to tweak bones and layers
for bone in tweaks:
create_sphere_widget(self.obj, bone, bone_transform_name=None)
if self.tweak_layers:
pb[bone].bone.layers = self.tweak_layers
def generate( self ):
# Torso Rig Anatomy:
# Neck: all bones above neck point, last bone is head
# Upper torso: all bones between pivot and neck start
# Lower torso: all bones below pivot until tail point
# Tail: all bones below tail point
bone_chains = self.build_bone_structure()
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Clear parents for org bones
for bone in self.org_bones:
eb[bone].use_connect = False
eb[bone].parent = None
if bone_chains != 'ERROR':
# Create lists of bones and strip "ORG" from their names
neck_bones = [ strip_org(b) for b in bone_chains['neck' ] ]
upper_torso_bones = [ strip_org(b) for b in bone_chains['upper'] ]
lower_torso_bones = [ strip_org(b) for b in bone_chains['lower'] ]
tail_bones = [ strip_org(b) for b in bone_chains['tail' ] ]
bones = {}
bones['def'] = self.create_deform() # Gets org bones from self
bones['pivot'] = self.create_pivot( self.pivot_pos )
bones['neck'] = self.create_neck( neck_bones )
bones['chest'] = self.create_chest( upper_torso_bones )
bones['hips'] = self.create_hips( lower_torso_bones )
# TODO: Add create tail
if tail_bones:
bones['tail'] = self.create_tail( tail_bones )
# TEST
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
self.parent_bones( bones )
self.constrain_bones( bones )
self.create_drivers( bones )
self.locks_and_widgets( bones )
controls = [ bones['neck']['ctrl'], bones['neck']['ctrl_neck'] ]
controls += [ bones['chest']['ctrl'], bones['hips']['ctrl'] ]
controls += [ bones['pivot']['ctrl'] ]
if 'tail' in bones.keys():
controls += [ bones['tail']['ctrl'] ]
# Create UI
controls_string = ", ".join(["'" + x + "'" for x in controls])
return [script % (
controls_string,
bones['pivot']['ctrl'],
'head_follow',
'neck_follow'
)]
def add_parameters( params ):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.neck_pos = bpy.props.IntProperty(
name = 'neck_position',
default = 6,
min = 0,
description = 'Neck start position'
)
params.pivot_pos = bpy.props.IntProperty(
name = 'pivot_position',
default = 3,
min = 0,
description = 'Position of the torso control and pivot point'
)
params.tail_pos = bpy.props.IntProperty(
name = 'tail_position',
default = 0,
min = 0,
description = 'Where the tail starts (change from 0 to enable)'
)
# Setting up extra layers for the FK and tweak
params.tweak_extra_layers = bpy.props.BoolProperty(
name = "tweak_extra_layers",
default = True,
description = ""
)
params.tweak_layers = bpy.props.BoolVectorProperty(
size = 32,
description = "Layers for the tweak controls to be on",
default = tuple( [ i == 1 for i in range(0, 32) ] )
)
def parameters_ui(layout, params):
""" Create the ui for the rig parameters."""
r = layout.row()
r.prop(params, "neck_pos")
r = layout.row()
r.prop(params, "pivot_pos")
r = layout.row()
r.prop(params, "tail_pos")
r = layout.row()
r.prop(params, "tweak_extra_layers")
r.active = params.tweak_extra_layers
col = r.column(align=True)
row = col.row(align=True)
for i in range(8):
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range(16,24):
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
col = r.column(align=True)
row = col.row(align=True)
for i in range(8,16):
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range(24,32):
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
def create_sample(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bones = {}
bone = arm.edit_bones.new('spine')
bone.head[:] = 0.0000, 0.0552, 1.0099
bone.tail[:] = 0.0000, 0.0172, 1.1573
bone.roll = 0.0000
bone.use_connect = False
bones['spine'] = bone.name
bone = arm.edit_bones.new('spine.001')
bone.head[:] = 0.0000, 0.0172, 1.1573
bone.tail[:] = 0.0000, 0.0004, 1.2929
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine']]
bones['spine.001'] = bone.name
bone = arm.edit_bones.new('spine.002')
bone.head[:] = 0.0000, 0.0004, 1.2929
bone.tail[:] = 0.0000, 0.0059, 1.4657
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.001']]
bones['spine.002'] = bone.name
bone = arm.edit_bones.new('spine.003')
bone.head[:] = 0.0000, 0.0059, 1.4657
bone.tail[:] = 0.0000, 0.0114, 1.6582
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.002']]
bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.004')
bone.head[:] = 0.0000, 0.0114, 1.6582
bone.tail[:] = 0.0000, -0.0067, 1.7197
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.004'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = 0.0000, -0.0067, 1.7197
bone.tail[:] = 0.0000, -0.0247, 1.7813
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.004']]
bones['spine.005'] = bone.name
bone = arm.edit_bones.new('spine.006')
bone.head[:] = 0.0000, -0.0247, 1.7813
bone.tail[:] = 0.0000, -0.0247, 1.9796
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.005']]
bones['spine.006'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['spine']]
pbone.rigify_type = 'pitchipoy.super_torso_turbo'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
pbone.rigify_parameters.chain_bone_controls = "1, 2, 3"
except AttributeError:
pass
try:
pbone.rigify_parameters.neck_pos = 5
except AttributeError:
pass
try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['spine.002']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['spine.003']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['spine.004']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['spine.005']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['spine.006']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone.select = False
bone.select_head = False
bone.select_tail = False
for b in bones:
bone = arm.edit_bones[bones[b]]
bone.select = True
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone

View File

@ -0,0 +1,164 @@
import bpy
import imp
import importlib
from ...utils import create_widget
WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer.
MODULE_NAME = "super_widgets" # Windows/Mac blender is weird, so __package__ doesn't work
def create_eye_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(1.1920928955078125e-07*size, 0.5000000596046448*size, 0.0*size), (-0.12940943241119385*size, 0.482962965965271*size, 0.0*size), (-0.24999988079071045*size, 0.4330127537250519*size, 0.0*size), (-0.35355329513549805*size, 0.35355344414711*size, 0.0*size), (-0.43301260471343994*size, 0.2500000596046448*size, 0.0*size), (-0.4829627275466919*size, 0.12940959632396698*size, 0.0*size), (-0.49999988079071045*size, 1.0094120739267964e-07*size, 0.0*size), (-0.482962965965271*size, -0.12940940260887146*size, 0.0*size), (-0.43301260471343994*size, -0.24999986588954926*size, 0.0*size), (-0.3535534143447876*size, -0.35355323553085327*size, 0.0*size), (-0.25*size, -0.43301257491111755*size, 0.0*size), (-0.1294095516204834*size, -0.48296281695365906*size, 0.0*size), (-1.1920928955078125e-07*size, -0.4999999403953552*size, 0.0*size), (0.12940943241119385*size, -0.4829629063606262*size, 0.0*size), (0.24999988079071045*size, -0.4330127537250519*size, 0.0*size), (0.35355329513549805*size, -0.35355353355407715*size, 0.0*size), (0.4330127239227295*size, -0.25000008940696716*size, 0.0*size), (0.482962965965271*size, -0.12940965592861176*size, 0.0*size), (0.5000001192092896*size, -1.6926388468618825e-07*size, 0.0*size), (0.48296308517456055*size, 0.1294093281030655*size, 0.0*size), (0.4330129623413086*size, 0.24999980628490448*size, 0.0*size), (0.35355377197265625*size, 0.35355323553085327*size, 0.0*size), (0.25000035762786865*size, 0.43301260471343994*size, 0.0*size), (0.1294100284576416*size, 0.48296287655830383*size, 0.0*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_eyes_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(0.8928930759429932*size, -0.7071065902709961*size, 0.0*size), (0.8928932547569275*size, 0.7071067690849304*size, 0.0*size), (-1.8588197231292725*size, -0.9659252762794495*size, 0.0*size), (-2.100001096725464*size, -0.8660248517990112*size, 0.0*size), (-2.3071072101593018*size, -0.7071059942245483*size, 0.0*size), (-2.4660258293151855*size, -0.49999913573265076*size, 0.0*size), (-2.5659260749816895*size, -0.258818119764328*size, 0.0*size), (-2.5999999046325684*size, 8.575012770961621e-07*size, 0.0*size), (-2.5659255981445312*size, 0.2588198482990265*size, 0.0*size), (-2.4660253524780273*size, 0.5000006556510925*size, 0.0*size), (-2.3071064949035645*size, 0.7071075439453125*size, 0.0*size), (-2.099999189376831*size, 0.866025984287262*size, 0.0*size), (-1.8588184118270874*size, 0.9659261703491211*size, 0.0*size), (-1.5999996662139893*size, 1.000000238418579*size, 0.0*size), (-1.341180443763733*size, 0.9659258723258972*size, 0.0*size), (-1.0999995470046997*size, 0.8660253882408142*size, 0.0*size), (-0.8928929567337036*size, 0.7071067094802856*size, 0.0*size), (-0.892893373966217*size, -0.7071066498756409*size, 0.0*size), (-1.100000262260437*size, -0.8660252690315247*size, 0.0*size), (-1.3411810398101807*size, -0.9659255743026733*size, 0.0*size), (1.600000023841858*size, 1.0*size, 0.0*size), (1.3411810398101807*size, 0.9659258127212524*size, 0.0*size), (1.100000023841858*size, 0.8660253882408142*size, 0.0*size), (-1.600000262260437*size, -0.9999997615814209*size, 0.0*size), (1.0999997854232788*size, -0.8660252690315247*size, 0.0*size), (1.341180682182312*size, -0.9659257531166077*size, 0.0*size), (1.5999996662139893*size, -1.0*size, 0.0*size), (1.8588186502456665*size, -0.965925931930542*size, 0.0*size), (2.0999996662139893*size, -0.8660256266593933*size, 0.0*size), (2.3071064949035645*size, -0.7071071863174438*size, 0.0*size), (2.4660253524780273*size, -0.5000002980232239*size, 0.0*size), (2.5659255981445312*size, -0.25881943106651306*size, 0.0*size), (2.5999999046325684*size, -4.649122899991198e-07*size, 0.0*size), (2.5659260749816895*size, 0.25881853699684143*size, 0.0*size), (2.4660258293151855*size, 0.4999994933605194*size, 0.0*size), (2.3071072101593018*size, 0.707106351852417*size, 0.0*size), (2.1000006198883057*size, 0.8660250902175903*size, 0.0*size), (1.8588197231292725*size, 0.9659256339073181*size, 0.0*size), (-1.8070557117462158*size, -0.7727401852607727*size, 0.0*size), (-2.0000009536743164*size, -0.6928198337554932*size, 0.0*size), (-2.1656856536865234*size, -0.5656847357749939*size, 0.0*size), (-2.292820692062378*size, -0.3999992609024048*size, 0.0*size), (-2.3727407455444336*size, -0.20705445110797882*size, 0.0*size), (-2.3999998569488525*size, 7.336847716032935e-07*size, 0.0*size), (-2.3727405071258545*size, 0.207055926322937*size, 0.0*size), (-2.2928202152252197*size, 0.40000057220458984*size, 0.0*size), (-2.1656851768493652*size, 0.5656861066818237*size, 0.0*size), (-1.9999992847442627*size, 0.6928208470344543*size, 0.0*size), (-1.8070547580718994*size, 0.7727410197257996*size, 0.0*size), (-1.5999996662139893*size, 0.8000002503395081*size, 0.0*size), (-1.3929443359375*size, 0.7727407813072205*size, 0.0*size), (-1.1999995708465576*size, 0.6928203701972961*size, 0.0*size), (-1.0343143939971924*size, 0.5656854510307312*size, 0.0*size), (-1.0343146324157715*size, -0.5656852722167969*size, 0.0*size), (-1.2000001668930054*size, -0.6928201913833618*size, 0.0*size), (-1.3929448127746582*size, -0.7727404236793518*size, 0.0*size), (-1.6000001430511475*size, -0.7999997735023499*size, 0.0*size), (1.8070557117462158*size, 0.772739827632904*size, 0.0*size), (2.0000009536743164*size, 0.6928195953369141*size, 0.0*size), (2.1656856536865234*size, 0.5656843781471252*size, 0.0*size), (2.292820692062378*size, 0.39999890327453613*size, 0.0*size), (2.3727407455444336*size, 0.20705409348011017*size, 0.0*size), (2.3999998569488525*size, -1.0960745839838637e-06*size, 0.0*size), (2.3727405071258545*size, -0.20705628395080566*size, 0.0*size), (2.2928202152252197*size, -0.4000009298324585*size, 0.0*size), (2.1656851768493652*size, -0.5656863451004028*size, 0.0*size), (1.9999992847442627*size, -0.692821204662323*size, 0.0*size), (1.8070547580718994*size, -0.7727413773536682*size, 0.0*size), (1.5999996662139893*size, -0.8000004887580872*size, 0.0*size), (1.3929443359375*size, -0.7727410197257996*size, 0.0*size), (1.1999995708465576*size, -0.6928204894065857*size, 0.0*size), (1.0343143939971924*size, -0.5656855702400208*size, 0.0*size), (1.0343146324157715*size, 0.5656850337982178*size, 0.0*size), (1.2000004053115845*size, 0.6928199529647827*size, 0.0*size), (1.3929448127746582*size, 0.7727401852607727*size, 0.0*size), (1.6000001430511475*size, 0.7999995350837708*size, 0.0*size), ]
edges = [(24, 0), (1, 22), (16, 1), (17, 0), (23, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (21, 20), (22, 21), (13, 14), (14, 15), (15, 16), (17, 18), (18, 19), (19, 23), (25, 24), (26, 25), (27, 26), (28, 27), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (20, 37), (56, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), (49, 50), (50, 51), (51, 52), (53, 54), (54, 55), (55, 56), (75, 57), (57, 58), (58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66), (66, 67), (67, 68), (68, 69), (69, 70), (70, 71), (72, 73), (73, 74), (74, 75), (52, 72), (53, 71), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_ear_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(-2.4903741291382175e-09*size, 1.0*size, -3.123863123732917e-08*size), (-7.450580596923828e-09*size, 0.9829629063606262*size, 0.0776456817984581*size), (-1.4901161193847656e-08*size, 0.9330127239227295*size, 0.1499999761581421*size), (-2.9802322387695312e-08*size, 0.8535534143447876*size, 0.2121320217847824*size), (-2.9802322387695312e-08*size, 0.75*size, 0.25980761647224426*size), (-2.9802322387695312e-08*size, 0.6294095516204834*size, 0.2897777259349823*size), (-2.9802322387695312e-08*size, 0.5000000596046448*size, 0.29999998211860657*size), (-5.960464477539063e-08*size, 0.37059056758880615*size, 0.2897777855396271*size), (-5.960464477539063e-08*size, 0.25000008940696716*size, 0.25980767607688904*size), (-4.470348358154297e-08*size, 0.14644670486450195*size, 0.21213211119174957*size), (-4.470348358154297e-08*size, 0.06698736548423767*size, 0.15000009536743164*size), (-4.470348358154297e-08*size, 0.017037123441696167*size, 0.07764581590890884*size), (-3.6718930118695425e-08*size, 0.0*size, 1.1981423142515268e-07*size), (-2.9802322387695312e-08*size, 0.017037034034729004*size, -0.07764559239149094*size), (-2.9802322387695312e-08*size, 0.06698718667030334*size, -0.14999987185001373*size), (-1.4901161193847656e-08*size, 0.14644640684127808*size, -0.21213191747665405*size), (0.0*size, 0.24999985098838806*size, -0.25980761647224426*size), (0.0*size, 0.3705902695655823*size, -0.2897777259349823*size), (0.0*size, 0.4999997615814209*size, -0.30000004172325134*size), (0.0*size, 0.6294092535972595*size, -0.2897777855396271*size), (0.0*size, 0.7499997615814209*size, -0.2598077356815338*size), (1.4901161193847656e-08*size, 0.8535531759262085*size, -0.21213220059871674*size), (0.0*size, 0.9330125451087952*size, -0.15000019967556*size), (0.0*size, 0.9829628467559814*size, -0.07764596492052078*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_jaw_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size), (0.0*size, 1.153113603591919*size, 0.0*size), (-0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (-0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.0*size, 1.153113603591919*size, 0.18649044632911682*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (-0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (9, 4), (6, 5), (7, 6), (8, 7), (15, 8), (5, 0), (11, 10), (12, 11), (13, 12), (14, 13), (9, 14), (17, 16), (18, 17), (19, 18), (15, 19), (16, 10), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_teeth_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(0.6314387321472168*size, 0.4999997019767761*size, 0.09999999403953552*size), (0.5394065976142883*size, 0.29289281368255615*size, 0.09999999403953552*size), (0.3887903690338135*size, 0.1339743733406067*size, 0.09999999403953552*size), (0.19801488518714905*size, 0.03407406806945801*size, 0.09999999403953552*size), (-3.4034394502668874e-07*size, 0.0*size, 0.09999999403953552*size), (-0.19801555573940277*size, 0.034074246883392334*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, -0.10000000894069672*size), (-0.6778771877288818*size, 0.7411810755729675*size, -0.10000000894069672*size), (-0.6314389705657959*size, 0.5000001192092896*size, -0.10000000894069672*size), (-0.5394070148468018*size, 0.2928934097290039*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, -0.10000000894069672*size), (-0.19801555573940277*size, 0.034074246883392334*size, -0.10000000894069672*size), (-3.4034394502668874e-07*size, 0.0*size, -0.10000000894069672*size), (0.19801488518714905*size, 0.03407406806945801*size, -0.10000000894069672*size), (0.3887903690338135*size, 0.1339743733406067*size, -0.10000000894069672*size), (0.5394065976142883*size, 0.29289281368255615*size, -0.10000000894069672*size), (0.6314387321472168*size, 0.4999997019767761*size, -0.10000000894069672*size), (0.6778769493103027*size, 0.7411805391311646*size, -0.10000000894069672*size), (0.6999999284744263*size, 0.9999995231628418*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, 0.09999999403953552*size), (-0.5394070148468018*size, 0.2928934097290039*size, 0.09999999403953552*size), (-0.6314389705657959*size, 0.5000001192092896*size, 0.09999999403953552*size), (-0.6778771877288818*size, 0.7411810755729675*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, 0.09999999403953552*size), (0.6778769493103027*size, 0.7411805391311646*size, 0.09999999403953552*size), (0.6999999284744263*size, 0.9999995231628418*size, 0.09999999403953552*size), ]
edges = [(25, 24), (24, 0), (0, 1), (1, 2), (2, 3), (3, 4), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (4, 5), (5, 19), (19, 20), (20, 21), (21, 22), (22, 23), (18, 25), (6, 23), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_face_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(-0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, -0.25*size, -0.07499998807907104*size), (-0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, -0.25*size, -0.07499998807907104*size), ]
edges = [(4, 5), (5, 1), (1, 0), (0, 4), (5, 6), (6, 2), (2, 1), (6, 7), (7, 3), (3, 2), (7, 4), (0, 3), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.0*size, 1.0*size, -0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), (0.0*size, 1.0*size, 0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), ]
edges = [(0, 1), (2, 3), (1, 4), (4, 5), (3, 6), (5, 6), (0, 2), (7, 8), (9, 10), (8, 11), (11, 12), (10, 13), (12, 13), (7, 9), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None
def create_hand_widget(rig, bone_name, size=1.0, bone_transform_name=None):
# Create hand widget
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(0.0*size, 1.5*size, -0.7000000476837158*size), (1.1920928955078125e-07*size, -0.25*size, -0.6999999284744263*size), (0.0*size, -0.25*size, 0.7000000476837158*size), (-1.1920928955078125e-07*size, 1.5*size, 0.6999999284744263*size), (5.960464477539063e-08*size, 0.7229999899864197*size, -0.699999988079071*size), (-5.960464477539063e-08*size, 0.7229999899864197*size, 0.699999988079071*size), (1.1920928955078125e-07*size, -2.9802322387695312e-08*size, -0.699999988079071*size), (0.0*size, 2.9802322387695312e-08*size, 0.699999988079071*size), ]
edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
mod = obj.modifiers.new("subsurf", 'SUBSURF')
mod.levels = 2
return obj
else:
return None
def create_foot_widget(rig, bone_name, size=1.0, bone_transform_name=None):
# Create hand widget
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(-0.6999998688697815*size, -0.5242648720741272*size, 0.0*size), (-0.7000001072883606*size, 1.2257349491119385*size, 0.0*size), (0.6999998688697815*size, 1.2257351875305176*size, 0.0*size), (0.7000001072883606*size, -0.5242648720741272*size, 0.0*size), (-0.6999998688697815*size, 0.2527350187301636*size, 0.0*size), (0.7000001072883606*size, 0.2527352571487427*size, 0.0*size), (-0.7000001072883606*size, 0.975735068321228*size, 0.0*size), (0.6999998688697815*size, 0.9757352471351624*size, 0.0*size), ]
edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
mod = obj.modifiers.new("subsurf", 'SUBSURF')
mod.levels = 2
return obj
else:
return None
def create_ballsocket_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [(-0.050000108778476715*size, 0.779460072517395*size, -0.2224801927804947*size), (0.049999915063381195*size, 0.779460072517395*size, -0.22248023748397827*size), (0.09999985247850418*size, 0.6790841817855835*size, -0.3658318817615509*size), (-2.3089636158601934e-07*size, 0.5930476188659668*size, -0.488704651594162*size), (-0.10000013560056686*size, 0.6790841817855835*size, -0.3658317029476166*size), (0.04999981075525284*size, 0.6790841817855835*size, -0.36583182215690613*size), (-0.050000183284282684*size, 0.6790841817855835*size, -0.3658318519592285*size), (-0.3658319115638733*size, 0.6790841221809387*size, 0.05000019446015358*size), (-0.3658318817615509*size, 0.6790841221809387*size, -0.04999979957938194*size), (-0.36583176255226135*size, 0.6790841221809387*size, 0.10000018030405045*size), (-0.48870471119880676*size, 0.5930476188659668*size, 2.4472291215715813e-07*size), (-0.3658319413661957*size, 0.679084062576294*size, -0.0999998077750206*size), (-0.22248037159442902*size, 0.7794600129127502*size, -0.04999985918402672*size), (-0.22248034179210663*size, 0.7794600129127502*size, 0.05000016465783119*size), (0.3658319115638733*size, 0.6790841221809387*size, -0.05000000819563866*size), (0.3658319115638733*size, 0.6790841221809387*size, 0.05000000074505806*size), (0.36583179235458374*size, 0.6790841221809387*size, -0.09999998658895493*size), (0.4887046813964844*size, 0.5930476188659668*size, -3.8399143420519977e-08*size), (0.3658319413661957*size, 0.679084062576294*size, 0.10000000149011612*size), (0.050000034272670746*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.04999997466802597*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.09999992698431015*size, 0.679084062576294*size, 0.36583200097084045*size), (1.267315070663244e-07*size, 0.5930474996566772*size, 0.48870477080345154*size), (0.1000000610947609*size, 0.679084062576294*size, 0.3658318519592285*size), (-0.049999915063381195*size, 0.679084062576294*size, 0.3658319413661957*size), (0.05000007897615433*size, 0.679084062576294*size, 0.36583197116851807*size), (0.22248029708862305*size, 0.7794600129127502*size, 0.05000004544854164*size), (0.22248028218746185*size, 0.7794600129127502*size, -0.04999994859099388*size), (-4.752442350763886e-08*size, 0.8284152746200562*size, -0.1499999612569809*size), (-0.03882290795445442*size, 0.8284152746200562*size, -0.14488883316516876*size), (-0.07500004768371582*size, 0.8284152746200562*size, -0.12990377843379974*size), (-0.10606606304645538*size, 0.8284152746200562*size, -0.10606598109006882*size), (-0.1299038827419281*size, 0.8284152746200562*size, -0.07499996572732925*size), (-0.14488893747329712*size, 0.8284152746200562*size, -0.038822825998067856*size), (-0.15000006556510925*size, 0.8284152746200562*size, 2.4781975582754967e-08*size), (-0.1448889672756195*size, 0.8284152746200562*size, 0.038822878152132034*size), (-0.1299038827419281*size, 0.8284152746200562*size, 0.07500001043081284*size), (-0.10606609284877777*size, 0.8284152746200562*size, 0.1060660257935524*size), (-0.0750000923871994*size, 0.8284152746200562*size, 0.12990383803844452*size), (-0.038822952657938004*size, 0.8284152746200562*size, 0.14488889276981354*size), (-1.0593657862045802e-07*size, 0.8284152746200562*size, 0.15000005066394806*size), (0.03882275149226189*size, 0.8284152746200562*size, 0.14488892257213593*size), (0.07499989867210388*size, 0.8284152746200562*size, 0.1299038976430893*size), (0.10606591403484344*size, 0.8284152746200562*size, 0.10606611520051956*size), (0.12990373373031616*size, 0.8284152746200562*size, 0.0750000849366188*size), (0.14488881826400757*size, 0.8284152746200562*size, 0.038822952657938004*size), (0.1499999463558197*size, 0.8284152746200562*size, 1.0584351883835552e-07*size), (0.14488881826400757*size, 0.8284152746200562*size, -0.03882275149226189*size), (0.12990379333496094*size, 0.8284152746200562*size, -0.07499989122152328*size), (0.10606604814529419*size, 0.8284152746200562*size, -0.10606592148542404*size), (0.07500004768371582*size, 0.8284152746200562*size, -0.12990371882915497*size), (0.03882291540503502*size, 0.8284152746200562*size, -0.14488880336284637*size), ]
edges = [(1, 0), (3, 2), (5, 2), (4, 3), (6, 4), (1, 5), (0, 6), (13, 7), (12, 8), (7, 9), (9, 10), (8, 11), (27, 14), (26, 15), (14, 16), (16, 17), (15, 18), (17, 18), (10, 11), (12, 13), (20, 19), (22, 21), (24, 21), (23, 22), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (38, 37), (39, 38), (40, 39), (41, 40), (42, 41), (43, 42), (44, 43), (45, 44), (46, 45), (47, 46), (48, 47), (49, 48), (50, 49), (51, 50), (28, 51), (26, 27), (25, 23), (20, 24), (19, 25), ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
return obj
else:
return None

View File

@ -0,0 +1,509 @@
import bpy
from ...utils import copy_bone
from ...utils import strip_org, make_deformer_name, connected_children_names
from ...utils import make_mechanism_name, put_bone, create_sphere_widget
from ...utils import create_widget, create_circle_widget
from ...utils import MetarigError
from rna_prop_ui import rna_idprop_ui_prop_get
script = """
controls = [%s]
master_name = '%s'
if is_selected( controls ):
layout.prop( pose_bones[ master_name ], '["%s"]', slider = True )
layout.prop( pose_bones[ master_name ], '["%s"]', slider = True )
"""
class Rig:
def __init__(self, obj, bone_name, params):
self.obj = obj
self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
self.params = params
if params.tweak_extra_layers:
self.tweak_layers = list( params.tweak_layers )
else:
self.tweak_layers = None
if len(self.org_bones) <= 1:
raise MetarigError(
"RIGIFY ERROR: invalid rig structure" % (strip_org(bone_name))
)
def make_mch( self ):
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
org_bones = self.org_bones
mch_parent = self.obj.data.bones[ org_bones[0] ].parent
mch_parent_name = mch_parent.name # Storing the mch parent's name
if not mch_parent:
mch_parent = self.obj.data.edit_bones[ org_bones[0] ]
mch_bone = copy_bone(
self.obj,
mch_parent_name,
make_mechanism_name( strip_org( org_bones[0] ) )
)
else:
mch_bone = copy_bone(
self.obj,
mch_parent_name,
make_mechanism_name( strip_org( org_bones[0] ) )
)
put_bone( self.obj, mch_bone, eb[ mch_parent_name ].tail )
eb[ mch_bone ].length /= 4 # reduce length to fourth of original
return mch_bone
def make_master( self ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
master_bone = copy_bone(
self.obj,
org_bones[0],
"master_" + strip_org( org_bones[0] )
)
# Make widgets
bpy.ops.object.mode_set(mode ='OBJECT')
create_square_widget( self.obj, master_bone )
return master_bone
def make_controls( self ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
ctrl_chain = []
for i in range( len( org_bones ) ):
name = org_bones[i]
ctrl_bone = copy_bone(
self.obj,
name,
strip_org(name)
)
ctrl_chain.append( ctrl_bone )
# Make widgets
bpy.ops.object.mode_set(mode ='OBJECT')
for ctrl in ctrl_chain:
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
return ctrl_chain
def make_tweaks( self ):
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
org_bones = self.org_bones
tweak_chain = []
for i in range( len( org_bones ) + 1 ):
if i == len( org_bones ):
# Make final tweak at the tip of the tentacle
name = org_bones[i-1]
else:
name = org_bones[i]
tweak_bone = copy_bone(
self.obj,
name,
"tweak_" + strip_org(name)
)
tweak_e = eb[ tweak_bone ]
tweak_e.length /= 2 # Set size to half
if i == len( org_bones ):
# Position final tweak at the tip
put_bone( self.obj, tweak_bone, eb[ org_bones[-1]].tail )
tweak_chain.append( tweak_bone )
# Make widgets
bpy.ops.object.mode_set(mode = 'OBJECT')
for tweak in tweak_chain:
create_sphere_widget( self.obj, tweak )
tweak_pb = self.obj.pose.bones[ tweak ]
# Set locks
if tweak_chain.index( tweak ) != len( tweak_chain ) - 1:
tweak_pb.lock_rotation = (True, False, True)
tweak_pb.lock_scale = (False, True, False)
else:
tweak_pb.lock_rotation_w = True
tweak_pb.lock_rotation = (True, True, True)
tweak_pb.lock_scale = (True, True, True)
# Set up tweak bone layers
if self.tweak_layers:
tweak_pb.bone.layers = self.tweak_layers
return tweak_chain
def make_deform( self ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
def_chain = []
for i in range( len( org_bones ) ):
name = org_bones[i]
def_bone = copy_bone(
self.obj,
name,
make_deformer_name(strip_org(name))
)
def_chain.append( def_bone )
return def_chain
def parent_bones( self, all_bones ):
bpy.ops.object.mode_set(mode ='EDIT')
org_bones = self.org_bones
eb = self.obj.data.edit_bones
""" for category in all_bones:
if isinstance( all_bones[category], list ):
for bone in all_bones[category]:
print( "Bone: " + bone )
eb[bone].parent = None
else:
eb[ all_bones[category] ].parent = None
"""
# mch bone remains parentless and will be parented to root by rigify
# Parent master bone
# eb[ all_bones['master'] ].parent = eb[ all_bones['mch'] ]
# Parent control bones
# ctrls_n_parent = [ all_bones['master'] ] + all_bones['control']
for bone in ctrls_n_parent[1:]:
previous_index = ctrls_n_parent.index( bone ) - 1
eb[ bone ].parent = eb[ ctrls_n_parent[previous_index] ]
# Parent tweak bones
tweaks = all_bones['tweak']
for tweak in all_bones['tweak']:
parent = ''
if tweaks.index( tweak ) == len( tweaks ) - 1:
parent = all_bones['control'][ -1 ]
else:
parent = all_bones['control'][ tweaks.index( tweak ) ]
eb[ tweak ].parent = eb[ parent ]
# Parent deform bones
for bone in all_bones['deform'][1:]:
previous_index = all_bones['deform'].index( bone ) - 1
eb[ bone ].parent = eb[ all_bones['deform'][previous_index] ]
eb[ bone ].use_connect = True
# Parent org bones ( to tweaks by default, or to the controls )
for org, tweak in zip( org_bones, all_bones['tweak'] ):
eb[ org ].parent = eb[ tweak ]
def make_constraints( self, all_bones ):
bpy.ops.object.mode_set(mode ='OBJECT')
org_bones = self.org_bones
pb = self.obj.pose.bones
## MCH bone constraints
if pb[ org_bones[0] ].parent:
mch_pb = pb[ all_bones['mch'] ]
con = mch_pb.constraints.new('COPY_LOCATION')
con.target = self.obj
con.subtarget = pb[ org_bones[0] ].parent.name
con.head_tail = 1.0
con = mch_pb.constraints.new('COPY_ROTATION')
con.target = self.obj
con.subtarget = pb[ org_bones[0] ].parent.name
con = mch_pb.constraints.new('COPY_SCALE')
con.target = self.obj
con.subtarget = pb[ org_bones[0] ].parent.name
"""
# Setting the MCH prop
master_pb = pb[ all_bones['master'] ]
prop_name_r = "rotation_follow"
prop_name_s = "scale_follow"
prop_names = [ prop_name_r, prop_name_s ]
for prop_name in prop_names:
master_pb[prop_name] = 1.0
prop = rna_idprop_ui_prop_get( master_pb, prop_name )
prop["min"] = 0.0
prop["max"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["description"] = prop_name
# driving the MCH follow rotation switch
drv = mch_pb.constraints[
prop_names.index(prop_name) +1
].driver_add("influence").driver
drv.type='SUM'
var = drv.variables.new()
var.name = prop_name
var.type = "SINGLE_PROP"
var.targets[0].id = self.obj
var.targets[0].data_path = \
master_pb.path_from_id() + '['+ '"' + prop_name + '"' + ']'
"""
## Deform bones' constraints
ctrls = all_bones['control']
tweaks = all_bones['tweak' ]
deforms = all_bones['deform' ]
for deform, tweak, ctrl in zip( deforms, tweaks, ctrls ):
con = pb[deform].constraints.new('COPY_TRANSFORMS')
con.target = self.obj
con.subtarget = tweak
con = pb[deform].constraints.new('DAMPED_TRACK')
con.target = self.obj
con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
con = pb[deform].constraints.new('STRETCH_TO')
con.target = self.obj
con.subtarget = tweaks[ tweaks.index( tweak ) + 1 ]
## Control bones' constraints
if self.params.make_rotations:
if ctrl != ctrls[0]:
con = pb[ctrl].constraints.new('COPY_ROTATION')
con.target = self.obj
con.subtarget = ctrls[ ctrls.index(ctrl) - 1 ]
con.use_offset = True
con.target_space = 'LOCAL'
con.owner_space = 'LOCAL'
def generate(self):
bpy.ops.object.mode_set(mode ='EDIT')
eb = self.obj.data.edit_bones
# Clear all initial parenting
for bone in self.org_bones:
# eb[ bone ].parent = None
eb[ bone ].use_connect = False
# Creating all bones
mch = self.make_mch()
# master = self.make_master()
ctrl_chain = self.make_controls()
tweak_chain = self.make_tweaks()
def_chain = self.make_deform()
all_bones = {
'mch' : mch,
# 'master' : master,
'control' : ctrl_chain,
'tweak' : tweak_chain,
'deform' : def_chain
}
self.make_constraints( all_bones )
self.parent_bones( all_bones )
"""
# Create UI
all_controls = all_bones['control'] + all_bones['tweak'] # + [ all_bones['master'] ]
controls_string = ", ".join(["'" + x + "'" for x in all_controls])
return [script % (
controls_string,
'rotation_follow',
'scale_follow'
)]
"""
def add_parameters(params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.make_rotations = bpy.props.BoolProperty(
name = "Rotations",
default = True,
description = "Make bones follow parent rotation"
)
# Setting up extra tweak layers
params.tweak_extra_layers = bpy.props.BoolProperty(
name = "tweak_extra_layers",
default = True,
description = ""
)
params.tweak_layers = bpy.props.BoolVectorProperty(
size = 32,
description = "Layers for the tweak controls to be on",
default = tuple( [ i == 1 for i in range(0, 32) ] )
)
def parameters_ui(layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()
r.prop(params, "make_rotations")
r = layout.row()
r.prop(params, "tweak_extra_layers")
r.active = params.tweak_extra_layers
col = r.column(align=True)
row = col.row(align=True)
for i in range( 8 ): # Layers 0-7
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range( 16, 24 ): # Layers 16-23
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
col = r.column(align=True)
row = col.row(align=True)
for i in range( 8, 16 ): # Layers 8-15
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
row = col.row(align=True)
for i in range( 24, 32 ): # Layers 24-31
row.prop(params, "tweak_layers", index=i, toggle=True, text="")
def create_square_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj != None:
verts = [
( 0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
( -0.5 * size, -2.9802322387695312e-08 * size, 0.5 * size ),
( 0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
( -0.5 * size, 2.9802322387695312e-08 * size, -0.5 * size ),
]
edges = [(0, 1), (2, 3), (0, 2), (3, 1) ]
faces = []
mesh = obj.data
mesh.from_pydata(verts, edges, faces)
mesh.update()
mesh.update()
return obj
else:
return None
def create_sample(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
arm = obj.data
bones = {}
bone = arm.edit_bones.new('tentacle')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.use_connect = False
bones['tentacle'] = bone.name
bone = arm.edit_bones.new('tentacle.001')
bone.head[:] = 0.0000, 0.0000, 1.0000
bone.tail[:] = 0.0000, 0.0000, 2.0000
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['tentacle']]
bones['tentacle.001'] = bone.name
bone = arm.edit_bones.new('tentacle.002')
bone.head[:] = 0.0000, 0.0000, 2.0000
bone.tail[:] = 0.0000, 0.0000, 3.0000
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['tentacle.001']]
bones['tentacle.002'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['tentacle']]
pbone.rigify_type = 'tentacle'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['tentacle.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone = obj.pose.bones[bones['tentacle.002']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
bpy.ops.object.mode_set(mode='EDIT')
for bone in arm.edit_bones:
bone.select = False
bone.select_head = False
bone.select_tail = False
for b in bones:
bone = arm.edit_bones[bones[b]]
bone.select = True
bone.select_head = True
bone.select_tail = True
arm.edit_bones.active = bone

View File

@ -125,9 +125,10 @@ class DATA_PT_rigify_layer_names(bpy.types.Panel):
row = col.row()
row.prop(arm, "layers", index=i, text="", toggle=True)
split = row.split(percentage=0.8)
split.prop(rigify_layer, "name", text="Layer %d" % (i + 1))
split.prop(rigify_layer, "row", text="")
#split.prop(rigify_layer, "column", text="")
split.prop(rigify_layer, "name", text="Layer %d" % (i + 1))
split.prop(rigify_layer, "row", text="")
#split.prop(rigify_layer, "column", text="")
class BONE_PT_rigify_buttons(bpy.types.Panel):
@ -198,15 +199,10 @@ class BONE_PT_rigify_buttons(bpy.types.Panel):
class VIEW3D_PT_tools_rigify_dev(bpy.types.Panel):
bl_category = "Tools"
bl_label = "Rigify Dev Tools"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
@classmethod
def poll(cls, context):
return context.mode == 'EDIT_ARMATURE' or context.mode == 'EDIT_MESH'
def draw(self, context):
obj = context.active_object
if obj != None:
@ -424,7 +420,6 @@ def register():
bpy.utils.register_class(EncodeMetarig)
bpy.utils.register_class(EncodeMetarigSample)
bpy.utils.register_class(EncodeWidget)
#space_info.INFO_MT_armature_add.append(ui.menu_func)

View File

@ -135,12 +135,41 @@ def new_bone(obj, bone_name):
else:
raise MetarigError("Can't add new bone '%s' outside of edit mode" % bone_name)
def copy_bone_simple(obj, bone_name, assign_name=''):
""" Makes a copy of the given bone in the given armature object.
but only copies head, tail positions and roll. Does not
address parenting either.
"""
#if bone_name not in obj.data.bones:
if bone_name not in obj.data.edit_bones:
raise MetarigError("copy_bone(): bone '%s' not found, cannot copy it" % bone_name)
if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
if assign_name == '':
assign_name = bone_name
# Copy the edit bone
edit_bone_1 = obj.data.edit_bones[bone_name]
edit_bone_2 = obj.data.edit_bones.new(assign_name)
bone_name_1 = bone_name
bone_name_2 = edit_bone_2.name
# Copy edit bone attributes
edit_bone_2.layers = list(edit_bone_1.layers)
edit_bone_2.head = Vector(edit_bone_1.head)
edit_bone_2.tail = Vector(edit_bone_1.tail)
edit_bone_2.roll = edit_bone_1.roll
return bone_name_2
else:
raise MetarigError("Cannot copy bones outside of edit mode")
def copy_bone(obj, bone_name, assign_name=''):
""" Makes a copy of the given bone in the given armature object.
Returns the resulting bone's name.
"""
if bone_name not in obj.data.bones:
#if bone_name not in obj.data.bones:
if bone_name not in obj.data.edit_bones:
raise MetarigError("copy_bone(): bone '%s' not found, cannot copy it" % bone_name)
if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
@ -698,7 +727,7 @@ def write_metarig(obj, layers=False, func_name="create"):
"""
code = []
code.append("import bpy\n")
code.append("import bpy\n\n")
code.append("def %s(obj):" % func_name)
code.append(" # generated by rigify.utils.write_metarig")