- Added two driven-shape-key rig types that create and drive shape keys on a mesh/meshes based on the distance or rotation difference between two bones.
- Fixed bug in finger curl rig type where secondary finger controls were not created.  Finger type can also now (optionally) have a hinge switch (useful when using it for wings).
- Changed the blending system in rigify_utils to use copy_transforms constraints instead of copy_loc+copy_rot.
- Finished the quadruped leg type.  Now has both ik and fk control and ik/fk switching.  Also uses a rotating bone to control the knee direction instead of a pole target (seems to work more consistently for quadruped setups).  There's still one annoying bug regarding foot roll, but it's not blocking.  I'll track it down later.
- Mouth rig now creates corrective shape keys on the face mesh for dealing with mouth corners when they spread open.
- Biped arm and leg types now cause mesh to scale when you scale the fk controls.
- Misc improvements to the rig types.
This commit is contained in:
2010-01-19 19:07:09 +00:00
parent 40fb29862e
commit c54d54e8ae
11 changed files with 1233 additions and 229 deletions

View File

@@ -223,6 +223,7 @@ def fk(obj, definitions, base_names, options):
fk_chain.forearm_p.rotation_mode = 'XYZ'
fk_chain.forearm_p.lock_rotation = (False, True, True)
fk_chain.hand_p.rotation_mode = 'ZXY'
fk_chain.arm_p.lock_location = True, True, True
con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
con.target = obj
@@ -276,7 +277,14 @@ def fk(obj, definitions, base_names, options):
fk_chain.arm_b.layer = layer
fk_chain.forearm_b.layer = layer
fk_chain.hand_b.layer = layer
# Forearm was getting wrong roll somehow. Hack to fix that.
bpy.ops.object.mode_set(mode='EDIT')
fk_chain.update()
mt.update()
fk_chain.forearm_e.roll = mt.forearm_e.roll
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
@@ -338,6 +346,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = definitions[2]
con = uarm1.constraints.new('COPY_SCALE')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[1]
con = uarm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
@@ -349,6 +362,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = definitions[2]
con = farm1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = farm2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj

View File

@@ -150,103 +150,171 @@ def deform(obj, definitions, base_names, options):
def main(obj, bone_definition, base_names, options):
# *** EDITMODE
bpy.ops.object.mode_set(mode='EDIT')
# get assosiated data
arm = obj.data
orig_ebone = arm.edit_bones[bone_definition[0]]
bb = obj.data.bones
eb = obj.data.edit_bones
pb = obj.pose.bones
org_f1 = bone_definition[0] # Original finger bone 01
org_f2 = bone_definition[1] # Original finger bone 02
org_f3 = bone_definition[2] # Original finger bone 03
# Check options
if "bend_ratio" in options:
bend_ratio = options["bend_ratio"]
else:
bend_ratio = 0.4
yes = [1, 1.0, True, "True", "true", "Yes", "yes"]
make_hinge = False
if ("hinge" in options) and (eb[org_f1].parent is not None):
if options["hinge"] in yes:
make_hinge = True
obj.animation_data_create() # needed if its a new armature with no keys
children = orig_ebone.children_recursive
tot_len = reduce(lambda f, ebone: f + ebone.length, children, orig_ebone.length)
# FIXME, the line below is far too arbitrary
base_name = base_names[bone_definition[0]].rsplit(".", 2)[0]
# first make a new bone at the location of the finger
#control_ebone = arm.edit_bones.new(base_name)
control_ebone = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True)
control_bone_name = control_ebone.name # we dont know if we get the name requested
control_ebone.connected = orig_ebone.connected
control_ebone.parent = orig_ebone.parent
control_ebone.length = tot_len
# now add bones inbetween this and its children recursively
# switching modes so store names only!
children = [ebone.name for ebone in children]
driver_bone_pairs = []
for child_bone_name in children:
child_ebone = arm.edit_bones[child_bone_name]
# finger.02 --> finger_driver.02
driver_bone_name = child_bone_name.split('.')
driver_bone_name = driver_bone_name[0] + "_driver." + ".".join(driver_bone_name[1:])
driver_ebone = copy_bone_simple(arm, child_ebone.name, driver_bone_name)
driver_ebone.length *= 0.5
# Insert driver_ebone in the chain without connected parents
driver_ebone.connected = False
driver_ebone.parent = child_ebone.parent
child_ebone.connected = False
child_ebone.parent = driver_ebone
# Add the drivers to these when in posemode.
driver_bone_pairs.append((child_bone_name, driver_bone_name))
del control_ebone
# Needed if its a new armature with no keys
obj.animation_data_create()
# Create the control bone
base_name = base_names[bone_definition[0]].split(".", 1)[0]
tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
control = copy_bone_simple(arm, bone_definition[0], base_name + get_side_name(base_names[bone_definition[0]]), parent=True).name
eb[control].connected = eb[org_f1].connected
eb[control].parent = eb[org_f1].parent
eb[control].length = tot_len
# Create secondary control bones
f1 = copy_bone_simple(arm, bone_definition[0], base_names[bone_definition[0]]).name
f2 = copy_bone_simple(arm, bone_definition[1], base_names[bone_definition[1]]).name
f3 = copy_bone_simple(arm, bone_definition[2], base_names[bone_definition[2]]).name
# Create driver bones
df1 = copy_bone_simple(arm, bone_definition[0], "MCH-" + base_names[bone_definition[0]]).name
eb[df1].length /= 2
df2 = copy_bone_simple(arm, bone_definition[1], "MCH-" + base_names[bone_definition[1]]).name
eb[df2].length /= 2
df3 = copy_bone_simple(arm, bone_definition[2], "MCH-" + base_names[bone_definition[2]]).name
eb[df3].length /= 2
# Set parents of the bones, interleaving the driver bones with the secondary control bones
eb[f3].connected = False
eb[df3].connected = False
eb[f2].connected = False
eb[df2].connected = False
eb[f1].connected = False
eb[df1].connected = eb[org_f1].connected
eb[f3].parent = eb[df3]
eb[df3].parent = eb[f2]
eb[f2].parent = eb[df2]
eb[df2].parent = eb[f1]
eb[f1].parent = eb[df1]
eb[df1].parent = eb[org_f1].parent
# Set up bones for hinge
if make_hinge:
socket = copy_bone_simple(arm, org_f1, "MCH-socket_"+control, parent=True).name
hinge = copy_bone_simple(arm, eb[org_f1].parent.name, "MCH-hinge_"+control).name
eb[control].connected = False
eb[control].parent = eb[hinge]
# Create the deform rig while we're still in edit mode
deform(obj, bone_definition, base_names, options)
# *** POSEMODE
bpy.ops.object.mode_set(mode='OBJECT')
orig_pbone = obj.pose.bones[bone_definition[0]]
control_pbone = obj.pose.bones[control_bone_name]
control_bbone = arm.bones[control_bone_name]
control_pbone.rotation_mode = obj.pose.bones[bone_definition[0]].rotation_mode
# only allow Y scale
control_pbone.lock_scale = (True, False, True)
control_pbone["bend_ratio"] = 0.4
prop = rna_idprop_ui_prop_get(control_pbone, "bend_ratio", create=True)
# Set rotation modes and axis locks
pb[control].rotation_mode = obj.pose.bones[bone_definition[0]].rotation_mode
pb[control].lock_location = True, True, True
pb[control].lock_scale = True, False, True
pb[f1].rotation_mode = 'YZX'
pb[f2].rotation_mode = 'YZX'
pb[f3].rotation_mode = 'YZX'
pb[f1].lock_location = True, True, True
pb[f2].lock_location = True, True, True
pb[f3].lock_location = True, True, True
pb[df2].rotation_mode = 'YZX'
pb[df3].rotation_mode = 'YZX'
# Add the bend_ratio property to the control bone
pb[control]["bend_ratio"] = bend_ratio
prop = rna_idprop_ui_prop_get(pb[control], "bend_ratio", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
con = orig_pbone.constraints.new('COPY_LOCATION')
# Add hinge property to the control bone
if make_hinge:
pb[control]["hinge"] = 0.0
prop = rna_idprop_ui_prop_get(pb[control], "hinge", create=True)
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
# Constraints
con = pb[df1].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = control_bone_name
con.subtarget = control
con = orig_pbone.constraints.new('COPY_ROTATION')
con = pb[df1].constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = control_bone_name
con.subtarget = control
con = pb[org_f1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f1
con = pb[org_f2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f2
con = pb[org_f3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = f3
if make_hinge:
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = bb[org_f1].parent.name
hinge_driver_path = pb[control].path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
# setup child drivers on each new smaller bone added. assume 2 for now.
# drives the bones
controller_path = control_pbone.path_to_id() # 'pose.bones["%s"]' % control_bone_name
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
con = pb[control].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Create the drivers for the driver bones (control bone scale rotates driver bones)
controller_path = pb[control].path_to_id() # 'pose.bones["%s"]' % control_bone_name
i = 0
for child_bone_name, driver_bone_name in driver_bone_pairs:
for bone in [df2, df3]:
# XXX - todo, any number
if i == 2:
break
driver_pbone = obj.pose.bones[driver_bone_name]
pbone = pb[bone]
driver_pbone.rotation_mode = 'YZX'
fcurve_driver = driver_pbone.driver_add("rotation_euler", 0)
pbone.rotation_mode = 'YZX'
fcurve_driver = pbone.driver_add("rotation_euler", 0)
#obj.driver_add('pose.bones["%s"].scale', 1)
#obj.animation_data.drivers[-1] # XXX, WATCH THIS
@@ -272,24 +340,18 @@ def main(obj, bone_definition, base_names, options):
elif i == 1:
driver.expression = '(-scale+1.0)*pi*2.0*br'
child_pbone = obj.pose.bones[child_bone_name]
# only allow X rotation
driver_pbone.lock_rotation = child_pbone.lock_rotation = (False, True, True)
i += 1
# last step setup layers
# Last step setup layers
if "ex_layer" in options:
layer = [n==options["ex_layer"] for n in range(0,32)]
else:
layer = list(arm.bones[bone_definition[0]].layer)
for child_bone_name, driver_bone_name in driver_bone_pairs:
arm.bones[driver_bone_name].layer = layer
for bone_name in [f1, f2, f3]:
arm.bones[bone_name].layer = layer
layer = list(arm.bones[bone_definition[0]].layer)
control_bbone.layer = layer
bb[control].layer = layer
# no blending the result of this
return None

View File

@@ -219,6 +219,8 @@ def ik(obj, bone_definition, base_names, options):
ik.foot_roll_p.lock_rotation = False, True, True
ik_chain.toe_p.rotation_mode = 'YXZ'
ik_chain.toe_p.lock_rotation = False, True, True
ik_chain.toe_p.lock_location = True, True, True
ik.foot_roll_p.lock_location = True, True, True
# IK
con = ik_chain.shin_p.constraints.new('IK')
@@ -329,6 +331,7 @@ def fk(obj, bone_definition, base_names, options):
foot_p.rotation_mode = 'YXZ'
fk_chain.toe_p.rotation_mode = 'YXZ'
fk_chain.toe_p.lock_rotation = False, True, True
fk_chain.thigh_p.lock_location = True, True, True
con = fk_chain.thigh_p.constraints.new('COPY_LOCATION')
con.target = obj
@@ -336,7 +339,7 @@ def fk(obj, bone_definition, base_names, options):
# hinge
prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True)
fk_chain.thigh_p["hinge"] = 0.5
fk_chain.thigh_p["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
@@ -441,6 +444,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = definitions[2]
con = uleg1.constraints.new('COPY_SCALE')
con.name = "scale"
con.target = obj
con.subtarget = definitions[1]
con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
@@ -452,6 +460,11 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = definitions[2]
con = lleg1.constraints.new('COPY_SCALE')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
@@ -484,5 +497,5 @@ def main(obj, bone_definition, base_names, options):
deform(obj, bone_definition, base_names, options)
bpy.ops.object.mode_set(mode='OBJECT')
blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=0.0)
blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=1.0)

View File

@@ -19,6 +19,8 @@
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import pi
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, get_side_name, get_base_name
from Mathutils import Vector
@@ -104,6 +106,8 @@ def metarig_definition(obj, orig_bone_name):
def ik(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data
bpy.ops.object.mode_set(mode='EDIT')
@@ -114,13 +118,14 @@ def ik(obj, bone_definition, base_names, options):
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
ik_chain = mt_chain.copy(to_fmt="%s", base_names=base_names)
ik_chain = mt_chain.copy(to_fmt="MCH-%s.ik", base_names=base_names)
ik_chain.thigh_e.connected = False
ik_chain.thigh_e.parent = mt.hips_e
ik_chain.foot_e.parent = None
ik_chain.rename("foot", get_base_name(ik_chain.foot) + "_ik" + get_side_name(ik_chain.foot))
ik_chain.rename("foot", get_base_name(base_names[bone_definition[3]]) + "_ik" + get_side_name(base_names[bone_definition[3]]))
ik_chain.rename("toe", get_base_name(base_names[bone_definition[4]]) + "_ik" + get_side_name(base_names[bone_definition[4]]))
# keep the foot_ik as the parent
ik_chain.toe_e.connected = False
@@ -129,21 +134,29 @@ def ik(obj, bone_definition, base_names, options):
ik_chain.foot_e.align_orientation(mt_chain.toe_e)
# children of ik_foot
ik = bone_class_instance(obj, ["foot_roll", "foot_roll_01", "foot_roll_02", "knee_target", "foot_target"])
ik = bone_class_instance(obj, ["foot_roll", "foot_roll_01", "foot_roll_02", "foot_target"])
ik.knee_target = add_pole_target_bone(obj, mt_chain.shin, "knee_target" + get_side_name(base_names[mt_chain.foot])) #XXX - pick a better name
ik.update()
ik.knee_target_e.parent = mt.hips_e
# knee rotator
knee_rotator = copy_bone_simple(arm, mt_chain.toe, "knee_rotator" + get_side_name(base_names[mt_chain.foot]), parent=True).name
eb[knee_rotator].connected = False
eb[knee_rotator].parent = eb[mt.hips]
eb[knee_rotator].head = eb[ik_chain.thigh].head
eb[knee_rotator].tail = eb[knee_rotator].head + eb[mt_chain.toe].vector
eb[knee_rotator].length = eb[ik_chain.thigh].length / 2
eb[knee_rotator].roll += pi/2
# parent ik leg to the knee rotator
eb[ik_chain.thigh].parent = eb[knee_rotator]
# foot roll is an interesting one!
# plot a vector from the toe bones head, bactwards to the length of the foot
# then align it with the foot but reverse direction.
ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot]))
ik.foot_roll = ik.foot_roll_e.name
ik.foot_roll_e.connected = False
ik.foot_roll_e.parent = ik_chain.foot_e
ik.foot_roll_e.translate(- (mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length))
ik.foot_roll_e.align_orientation(mt_chain.foot_e)
ik.foot_roll_e.tail = ik.foot_roll_e.head - ik.foot_roll_e.vector # flip
ik.foot_roll_e.head -= mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length
ik.foot_roll_e.tail = ik.foot_roll_e.head - (mt_chain.foot_e.vector.normalize() * mt_chain.toe_e.length)
ik.foot_roll_e.align_roll(mt_chain.foot_e.matrix.rotationPart() * Vector(0.0, 0.0, -1.0))
# MCH-foot
@@ -173,23 +186,74 @@ def ik(obj, bone_definition, base_names, options):
mt_chain.update()
ik.update()
ik_chain.update()
# Set rotation modes and axis locks
#pb[knee_rotator].rotation_mode = 'YXZ'
#pb[knee_rotator].lock_rotation = False, True, False
pb[knee_rotator].lock_location = True, True, True
pb[ik.foot_roll].rotation_mode = 'XYZ'
pb[ik.foot_roll].lock_rotation = False, True, True
pb[ik_chain.toe].rotation_mode = 'XYZ'
pb[ik_chain.toe].lock_rotation = False, True, True
# IK switch property
prop = rna_idprop_ui_prop_get(pb[ik_chain.foot], "ik", create=True)
pb[ik_chain.foot]["ik"] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
ik_driver_path = pb[ik_chain.foot].path_to_id() + '["ik"]'
# simple constraining of orig bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.thigh
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.shin
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik.foot_roll_02
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = ik_chain.toe
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = ik_driver_path
# others...
con = ik.foot_roll_01_p.constraints.new('COPY_ROTATION')
@@ -211,8 +275,7 @@ def ik(obj, bone_definition, base_names, options):
con.target = obj
con.subtarget = ik.foot_target
con.pole_target = obj
con.pole_subtarget = ik.knee_target
con.pole_target = None
ik.update()
ik_chain.update()
@@ -226,12 +289,204 @@ def ik(obj, bone_definition, base_names, options):
obj.data.bones[getattr(ik_chain, attr)].layer = layer
for attr in ik.attr_names:
obj.data.bones[getattr(ik, attr)].layer = layer
obj.data.bones[knee_rotator].layer = layer
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe
def fk(obj, bone_definition, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
arm = obj.data
bpy.ops.object.mode_set(mode='EDIT')
# setup the existing bones, use names from METARIG_NAMES
mt = bone_class_instance(obj, ["hips"])
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
mt.attr_initialize(METARIG_NAMES, bone_definition)
mt_chain.attr_initialize(METARIG_NAMES, bone_definition)
fk_chain = mt_chain.copy(to_fmt="%s", base_names=base_names)
# Create the socket
socket = copy_bone_simple(arm, mt_chain.thigh, "MCH-leg_socket").name
eb[socket].parent = eb[mt.hips]
eb[socket].length = eb[mt_chain.thigh].length / 4
# Create the hinge
hinge = copy_bone_simple(arm, mt.hips, "MCH-leg_hinge").name
eb[hinge].length = eb[mt.hips].length / 2
# Make leg child of hinge
eb[fk_chain.thigh].connected = False
eb[fk_chain.thigh].parent = eb[hinge]
bpy.ops.object.mode_set(mode='OBJECT')
# Set rotation modes and axis locks
pb[fk_chain.shin].rotation_mode = 'XYZ'
pb[fk_chain.shin].lock_rotation = False, True, True
# Constrain original bones to control bones
con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.thigh
con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.shin
con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.foot
con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = fk_chain.toe
# Socket constraint
con = pb[fk_chain.thigh].constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = socket
# Hinge constraint
con = pb[hinge].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = mt.hips
prop = rna_idprop_ui_prop_get(pb[fk_chain.thigh], "hinge", create=True)
pb[fk_chain.thigh]["hinge"] = 0.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
hinge_driver_path = pb[fk_chain.thigh].path_to_id() + '["hinge"]'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
var = driver.variables.new()
driver.type = 'AVERAGE'
var.name = "var"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = hinge_driver_path
mod = fcurve.modifiers[0]
mod.poly_order = 1
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
# Create upper leg bones: two bones, each half of the upper leg.
uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
uleg1.connected = False
uleg2.connected = False
uleg2.parent = uleg1
center = uleg1.center
uleg1.tail = center
uleg2.head = center
# Create lower leg bones: two bones, each half of the lower leg.
lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
lleg1.connected = False
lleg2.connected = False
lleg2.parent = lleg1
center = lleg1.center
lleg1.tail = center
lleg2.head = center
# Create a bone for the second lower leg deform bone to twist with
twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist")
twist.length /= 4
twist.connected = False
twist.parent = obj.data.edit_bones[definitions[3]]
# Create foot bone
foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
# Create toe bone
toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True)
# Store names before leaving edit mode
uleg1_name = uleg1.name
uleg2_name = uleg2.name
lleg1_name = lleg1.name
lleg2_name = lleg2.name
twist_name = twist.name
foot_name = foot.name
toe_name = toe.name
# Leave edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the pose bones
uleg1 = obj.pose.bones[uleg1_name]
uleg2 = obj.pose.bones[uleg2_name]
lleg1 = obj.pose.bones[lleg1_name]
lleg2 = obj.pose.bones[lleg2_name]
foot = obj.pose.bones[foot_name]
toe = obj.pose.bones[toe_name]
# Upper leg constraints
con = uleg1.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[2]
con = uleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[1]
# Lower leg constraints
con = lleg1.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[2]
con = lleg2.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = twist_name
con = lleg2.constraints.new('DAMPED_TRACK')
con.name = "trackto"
con.target = obj
con.subtarget = definitions[3]
# Foot constraint
con = foot.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[3]
# Toe constraint
con = toe.constraints.new('COPY_ROTATION')
con.name = "copy_rot"
con.target = obj
con.subtarget = definitions[4]
bpy.ops.object.mode_set(mode='EDIT')
return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None)
def main(obj, bone_definition, base_names, options):
bones_fk = fk(obj, bone_definition, base_names, options)
bones_ik = ik(obj, bone_definition, base_names, options)
deform(obj, bone_definition, base_names, options)
return bones_ik

View File

@@ -19,15 +19,69 @@
# <pep8 compliant>
import bpy
from math import acos
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos, pi
from Mathutils import Vector
from rigify import get_layer_dict
from rigify import get_layer_dict, RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "mouth"
def mark_actions():
for action in bpy.data.actions:
action.tag = True
def get_unmarked_action():
for action in bpy.data.actions:
if action.tag != True:
return action
return None
def add_action(name=None):
mark_actions()
bpy.ops.action.new()
action = get_unmarked_action()
if name is not None:
action.name = name
return action
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
@@ -49,7 +103,7 @@ def metarig_definition(obj, orig_bone_name):
chain = []
try:
chain += [bone.parent.name, bone.parent.parent.name, bone.name]
chain += [bone.parent.parent.name, bone.parent.name, bone.name]
except AttributeError:
raise RigifyError("'%s' rig type requires a chain of two parents (bone: %s)" % (RIG_TYPE, base_names[0]))
@@ -67,62 +121,70 @@ def deform(obj, definitions, base_names, options):
eb = obj.data.edit_bones
pb = obj.pose.bones
print("YAHOO")
# Options
req_options = ["mesh"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
print("YAHOO2")
meshes = options["mesh"].replace(" ", "").split(",")
# Upper lip MCH
lip1 = make_lip_stretch_bone(obj, "MCH-lip", definitions[2], definitions[3], 1.0)
lip2 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[4], 1.0)
lip22 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[5], 1.0)
lip33 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[3], 1.0)
lip3 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[4], 1.0)
lip4 = make_lip_stretch_bone(obj, "MCH-lip", definitions[6], definitions[5], 1.0)
lip1 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[2], 0.0)
lip2 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[3], 0.0)
lip22 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[4], 0.0)
lip33 = make_lip_stretch_bone(obj, "MCH-lip", definitions[3], definitions[4], 0.0)
lip3 = make_lip_stretch_bone(obj, "MCH-lip", definitions[4], definitions[5], 0.0)
lip4 = make_lip_stretch_bone(obj, "MCH-lip", definitions[5], definitions[6], 0.0)
dlip22 = copy_bone_simple(obj.data, lip22, "MCH-lip", parent=True).name
dlip33 = copy_bone_simple(obj.data, lip33, "MCH-lip", parent=True).name
eb[dlip22].bbone_segments = 8
eb[dlip33].bbone_segments = 8
eb[lip1].parent = eb[definitions[3]]
eb[lip2].parent = eb[definitions[4]]
eb[lip22].parent = eb[definitions[5]]
eb[lip33].parent = eb[definitions[3]]
eb[lip3].parent = eb[definitions[4]]
eb[lip4].parent = eb[definitions[5]]
eb[lip1].parent = eb[definitions[2]]
eb[lip2].parent = eb[definitions[3]]
eb[lip22].parent = eb[definitions[4]]
eb[lip33].parent = eb[definitions[4]]
eb[lip3].parent = eb[definitions[5]]
eb[lip4].parent = eb[definitions[6]]
eb[lip22].bbone_segments = 8
eb[lip33].bbone_segments = 8
# Lower lip MCH
lip5 = make_lip_stretch_bone(obj, "MCH-lip", definitions[6], definitions[7], 1.0)
lip6 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[8], 1.0)
lip66 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[9], 1.0)
lip77 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[7], 1.0)
lip7 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[8], 1.0)
lip8 = make_lip_stretch_bone(obj, "MCH-lip", definitions[2], definitions[9], 1.0)
lip5 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[6], 0.0)
lip6 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[7], 0.0)
lip66 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[8], 0.0)
lip77 = make_lip_stretch_bone(obj, "MCH-lip", definitions[7], definitions[8], 0.0)
lip7 = make_lip_stretch_bone(obj, "MCH-lip", definitions[8], definitions[9], 0.0)
lip8 = make_lip_stretch_bone(obj, "MCH-lip", definitions[9], definitions[2], 0.0)
dlip66 = copy_bone_simple(obj.data, lip66, "MCH-lip", parent=True).name
dlip77 = copy_bone_simple(obj.data, lip77, "MCH-lip", parent=True).name
eb[dlip66].bbone_segments = 8
eb[dlip77].bbone_segments = 8
eb[lip5].parent = eb[definitions[7]]
eb[lip6].parent = eb[definitions[8]]
eb[lip66].parent = eb[definitions[9]]
eb[lip77].parent = eb[definitions[7]]
eb[lip7].parent = eb[definitions[8]]
eb[lip8].parent = eb[definitions[9]]
eb[lip5].parent = eb[definitions[6]]
eb[lip6].parent = eb[definitions[7]]
eb[lip66].parent = eb[definitions[8]]
eb[lip77].parent = eb[definitions[8]]
eb[lip7].parent = eb[definitions[9]]
eb[lip8].parent = eb[definitions[2]]
eb[lip66].bbone_segments = 8
eb[lip77].bbone_segments = 8
# Upper lip DEF
dlip1 = copy_bone_simple(obj.data, lip1, "DEF-lip", parent=True).name
dlip2 = copy_bone_simple(obj.data, lip2, "DEF-lip", parent=True).name
dlip3 = copy_bone_simple(obj.data, lip3, "DEF-lip", parent=True).name
dlip4 = copy_bone_simple(obj.data, lip4, "DEF-lip", parent=True).name
dlip1 = copy_bone_simple(obj.data, lip1, "DEF-" + base_names[definitions[4]] + ".01.R", parent=True).name
dlip2 = copy_bone_simple(obj.data, lip2, "DEF-" + base_names[definitions[4]] + ".02.R", parent=True).name
dlip3 = copy_bone_simple(obj.data, lip3, "DEF-" + base_names[definitions[4]] + ".02.L", parent=True).name
dlip4 = copy_bone_simple(obj.data, lip4, "DEF-" + base_names[definitions[4]] + ".01.L", parent=True).name
eb[dlip2].parent = eb[dlip1]
eb[dlip22].parent = eb[dlip2]
eb[dlip1].parent = eb[dlip2]
eb[dlip2].parent = eb[lip22]
eb[dlip3].parent = eb[dlip4]
eb[dlip33].parent = eb[dlip3]
eb[dlip4].parent = eb[dlip3]
eb[dlip3].parent = eb[lip33]
eb[dlip2].connected = True
eb[dlip22].connected = True
eb[dlip3].connected = True
eb[dlip33].connected = True
eb[dlip1].connected = True
eb[dlip2].connected = True
eb[dlip4].connected = True
eb[dlip3].connected = True
eb[dlip1].bbone_segments = 8
eb[dlip2].bbone_segments = 8
@@ -130,43 +192,37 @@ def deform(obj, definitions, base_names, options):
eb[dlip4].bbone_segments = 8
# Lower lip DEF
dlip5 = copy_bone_simple(obj.data, lip5, "DEF-lip", parent=True).name
dlip6 = copy_bone_simple(obj.data, lip6, "DEF-lip", parent=True).name
dlip7 = copy_bone_simple(obj.data, lip7, "DEF-lip", parent=True).name
dlip8 = copy_bone_simple(obj.data, lip8, "DEF-lip", parent=True).name
dlip8 = copy_bone_simple(obj.data, lip8, "DEF-" + base_names[definitions[8]] + ".01.R", parent=True).name
dlip7 = copy_bone_simple(obj.data, lip7, "DEF-" + base_names[definitions[8]] + ".02.R", parent=True).name
dlip6 = copy_bone_simple(obj.data, lip6, "DEF-" + base_names[definitions[8]] + ".02.L", parent=True).name
dlip5 = copy_bone_simple(obj.data, lip5, "DEF-" + base_names[definitions[8]] + ".01.L", parent=True).name
eb[dlip6].parent = eb[dlip5]
eb[dlip66].parent = eb[dlip6]
eb[dlip7].parent = eb[dlip8]
eb[dlip77].parent = eb[dlip7]
eb[dlip5].parent = eb[dlip6]
eb[dlip6].parent = eb[lip66]
eb[dlip8].parent = eb[dlip7]
eb[dlip7].parent = eb[lip77]
eb[dlip5].connected = True
eb[dlip6].connected = True
eb[dlip66].connected = True
eb[dlip8].connected = True
eb[dlip7].connected = True
eb[dlip77].connected = True
eb[dlip5].bbone_segments = 8
eb[dlip6].bbone_segments = 8
eb[dlip7].bbone_segments = 8
eb[dlip8].bbone_segments = 8
print("OBJECT MODE1")
bpy.ops.object.mode_set(mode='OBJECT')
print("OBJECT MODE2")
# Constraints
con = pb[dlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip1
con = pb[dlip22].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip22
con = pb[dlip33].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip33
con = pb[dlip2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip2
@@ -187,14 +243,6 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = lip6
con = pb[dlip66].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip66
con = pb[dlip77].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip77
con = pb[dlip7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = lip7
@@ -203,6 +251,90 @@ def deform(obj, definitions, base_names, options):
con.target = obj
con.subtarget = lip8
# Corrective shape keys for the corners of the mouth.
bpy.ops.object.mode_set(mode='EDIT')
# Calculate the rotation difference between the bones
rotdiff_r = acos(eb[lip1].matrix.toQuat() * eb[lip8].matrix.toQuat()) * 2
rotdiff_l = acos(eb[lip4].matrix.toQuat() * eb[lip5].matrix.toQuat()) * 2
print (rotdiff_l)
bpy.ops.object.mode_set(mode='OBJECT')
# Left side
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".L.spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[6]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip4
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip5
# Set fcurve offset
mod = fcurve.modifiers[0]
if rotdiff_l != pi:
mod.coefficients[0] = -rotdiff_l / (pi-rotdiff_l)
mod.coefficients[1] = 1 / (pi-rotdiff_l)
# Right side
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".R.spread"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[2]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip1
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip8
# Set fcurve offset
mod = fcurve.modifiers[0]
if rotdiff_r != pi:
mod.coefficients[0] = -rotdiff_r / (pi-rotdiff_r)
mod.coefficients[1] = 1 / (pi-rotdiff_r)
return (None,)
@@ -217,6 +349,7 @@ def control(obj, definitions, base_names, options):
head_e = eb[definitions[0]]
jaw_e = eb[definitions[1]]
jaw = definitions[1]
# Head lips
hlip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".head").name
@@ -285,14 +418,14 @@ def control(obj, definitions, base_names, options):
eb[lip7].roll = 0
eb[lip8].roll = 0
eb[lip1].parent = eb[jlip1]
eb[lip2].parent = eb[jlip2]
eb[lip3].parent = eb[jlip3]
eb[lip4].parent = eb[jlip4]
eb[lip5].parent = eb[jlip5]
eb[lip6].parent = eb[jlip6]
eb[lip7].parent = eb[jlip7]
eb[lip8].parent = eb[jlip8]
eb[lip1].parent = eb[hlip1]
eb[lip2].parent = eb[hlip2]
eb[lip3].parent = eb[hlip3]
eb[lip4].parent = eb[hlip4]
eb[lip5].parent = eb[hlip5]
eb[lip6].parent = eb[hlip6]
eb[lip7].parent = eb[hlip7]
eb[lip8].parent = eb[hlip8]
# Link lips
llip1 = copy_bone_simple(obj.data, definitions[2], "MCH-"+base_names[definitions[2]]+".link").name
@@ -313,53 +446,84 @@ def control(obj, definitions, base_names, options):
eb[llip7].parent = eb[lip7]
eb[llip8].parent = eb[lip8]
# Jaw open tracker
jopent = copy_bone_simple(obj.data, jaw_e.name, "MCH-"+base_names[jaw_e.name]+".track", parent=True).name
eb[jopent].connected = False
eb[jopent].tail = jaw_e.tail + Vector(0,0,jaw_e.length)
eb[jopent].head = jaw_e.tail
bpy.ops.object.mode_set(mode='OBJECT')
# Add eye close action if it doesn't already exist
action_name = "mouth_open"
if action_name in bpy.data.actions:
open_action = bpy.data.actions[action_name]
else:
open_action = add_action(name=action_name)
# Add close property (useful when making the animation in the action)
prop_name = "open_action"
prop = rna_idprop_ui_prop_get(pb[lip1], prop_name, create=True)
pb[lip1][prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0
prop["min"] = 0.0
prop["max"] = 1.0
open_driver_path = pb[lip1].path_to_id() + '["open_action"]'
# Constraints
# Jaw lips to head lips
influence = [0.0, 0.1, 0.5]
con = pb[jlip1].constraints.new('COPY_TRANSFORMS')
# Jaw open tracker stretches to jaw tip
con = pb[jopent].constraints.new('STRETCH_TO')
con.target = obj
con.subtarget = hlip1
con.subtarget = jaw
con.head_tail = 1.0
con.original_length = bb[jopent].length
con.volume = 'NO_VOLUME'
# Head lips to jaw lips
influence = [0.0, 0.1, 0.5, 0.25, 0.0]
con = pb[hlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = jlip1
con.influence = influence[2]
con = pb[jlip2].constraints.new('COPY_TRANSFORMS')
con = pb[hlip2].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip2
con.subtarget = jlip2
con.influence = influence[1]
con = pb[jlip3].constraints.new('COPY_TRANSFORMS')
con = pb[hlip3].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip3
con.subtarget = jlip3
con.influence = influence[0]
con = pb[jlip4].constraints.new('COPY_TRANSFORMS')
con = pb[hlip4].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip4
con.subtarget = jlip4
con.influence = influence[1]
con = pb[jlip5].constraints.new('COPY_TRANSFORMS')
con = pb[hlip5].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip5
con.subtarget = jlip5
con.influence = influence[2]
con = pb[jlip6].constraints.new('COPY_TRANSFORMS')
con = pb[hlip6].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip6
con.influence = 1.0 - influence[1]
con.subtarget = jlip6
con.influence = 1.0 - influence[3]
con = pb[jlip7].constraints.new('COPY_TRANSFORMS')
con = pb[hlip7].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip7
con.influence = 1.0 - influence[0]
con.subtarget = jlip7
con.influence = 1.0 - influence[4]
con = pb[jlip8].constraints.new('COPY_TRANSFORMS')
con = pb[hlip8].constraints.new('COPY_TRANSFORMS')
con.target = obj
con.subtarget = hlip8
con.influence = 1.0 - influence[1]
con.subtarget = jlip8
con.influence = 1.0 - influence[3]
# ORG bones to link lips
con = pb[definitions[2]].constraints.new('COPY_TRANSFORMS')
@@ -394,6 +558,151 @@ def control(obj, definitions, base_names, options):
con.target = obj
con.subtarget = llip8
# Action constraints for open mouth
con = pb[lip1].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip2].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip3].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip4].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip5].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip6].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip7].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
con = pb[lip8].constraints.new('ACTION')
con.target = obj
con.subtarget = jopent
con.action = open_action
con.transform_channel = 'SCALE_Y'
con.start_frame = 0
con.end_frame = 60
con.minimum = 0.0
con.maximum = 1.0
con.target_space = 'LOCAL'
fcurve = con.driver_add("influence", 0)
driver = fcurve.driver
driver.type = 'AVERAGE'
var = driver.variables.new()
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].data_path = open_driver_path
# Set layers
layer = list(bb[definitions[2]].layer)
@@ -414,9 +723,12 @@ def control(obj, definitions, base_names, options):
def main(obj, bone_definition, base_names, options):
# Create control rig
print("CONTROL")
control(obj, bone_definition, base_names, options)
print("DEFORM")
# Create deform rig
deform(obj, bone_definition, base_names, options)
print("DONE")
return (None,)

View File

@@ -213,6 +213,9 @@ def main(obj, bone_definition, base_names, options):
ex_chain.update()
ex.update()
# Axis locks
ex.head_ctrl_p.lock_location = True, True, True
# Simple one off constraints, no drivers
con = ex.head_ctrl_p.constraints.new('COPY_LOCATION')
con.target = obj

View File

@@ -152,6 +152,7 @@ def main(obj, bone_definition, base_names, options):
control_pbone.rotation_mode = 'YZX'
control_pbone.lock_rotation = False, True, True
control_pbone.lock_location = True, True, True
driver_fcurves = pinky_pbone.driver_add("rotation_euler")
@@ -163,6 +164,8 @@ def main(obj, bone_definition, base_names, options):
prop = rna_idprop_ui_prop_get(control_pbone, "spread", create=True)
prop["soft_min"] = -1.0
prop["soft_max"] = 1.0
prop["min"] = -1.0
prop["max"] = 1.0
# *****

View File

@@ -0,0 +1,176 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_distance"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the distance between the bones
distance = (eb[bone_from].head - eb[bone_to].head).length
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "LOC_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if distance > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / distance
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@@ -0,0 +1,176 @@
# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from rna_prop_ui import rna_idprop_ui_prop_get
from math import acos
from Mathutils import Vector
from rigify import get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple
#METARIG_NAMES = ("cpy",)
RIG_TYPE = "shape_key_rotdiff"
def addget_shape_key(obj, name="Key"):
""" Fetches a shape key, or creates it if it doesn't exist
"""
# Create a shapekey set if it doesn't already exist
if obj.data.shape_keys is None:
shape = obj.add_shape_key(name="Basis", from_mix=False)
obj.active_shape_key_index = 0
# Get the shapekey, or create it if it doesn't already exist
if name in obj.data.shape_keys.keys:
shape_key = obj.data.shape_keys.keys[name]
else:
shape_key = obj.add_shape_key(name=name, from_mix=False)
return shape_key
def addget_shape_key_driver(obj, name="Key"):
""" Fetches the driver for the shape key, or creates it if it doesn't
already exist.
"""
driver_path = 'keys["' + name + '"].value'
fcurve = None
driver = None
if obj.data.shape_keys.animation_data is not None:
for driver_s in obj.data.shape_keys.animation_data.drivers:
if driver_s.data_path == driver_path:
fcurve = driver_s
if fcurve == None:
fcurve = obj.data.shape_keys.keys[name].driver_add("value", 0)
fcurve.driver.type = 'AVERAGE'
return fcurve
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
obj = bpy.context.active_object
arm = obj.data
bone = arm.edit_bones.new('Bone')
bone.head[:] = 0.0000, 0.0000, 0.0000
bone.tail[:] = 0.0000, 0.0000, 1.0000
bone.roll = 0.0000
bone.connected = False
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones['Bone']
pbone['type'] = 'copy'
def metarig_definition(obj, orig_bone_name):
bone = obj.data.bones[orig_bone_name]
return [bone.name]
def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bone_from = definitions[0]
# Options
req_options = ["to", "mesh", "shape_key"]
for option in req_options:
if option not in options:
raise RigifyError("'%s' rig type requires a '%s' option (bone: %s)" % (RIG_TYPE, option, base_names[definitions[0]]))
bone_to = "ORG-" + options["to"]
meshes = options["mesh"].replace(" ", "").split(",")
shape_key_name = options["shape_key"]
if "dmul" in options:
shape_blend_fac = options["dmul"]
else:
shape_blend_fac = 1.0
# Calculate the rotation difference between the bones
rotdiff = (eb[bone_from].matrix.toQuat() * eb[bone_to].matrix.toQuat()) * 2
bpy.ops.object.mode_set(mode='OBJECT')
# For every listed mesh object
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[bone_from]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "ROTATION_DIFF"
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = bone_from
var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = bone_to
# Set fcurve offset, so zero is at the rest distance
mod = fcurve.modifiers[0]
if rotdiff > 0.00001:
mod.coefficients[0] = -shape_blend_fac
mod.coefficients[1] = shape_blend_fac / rotdiff
return (None,)
def control(obj, definitions, base_names, options):
""" options:
mesh: name of mesh object with the shape key
shape_key: name of shape key
to: name of bone to measure distance from
"""
pass
def main(obj, bone_definition, base_names, options):
# Create control rig
#control(obj, bone_definition, base_names, options)
# Create deform rig
deform(obj, bone_definition, base_names, options)
return (None,)

View File

@@ -304,6 +304,9 @@ def main(obj, bone_definition, base_names, options):
mt_chain.update()
ex_chain.update()
rv_chain.update()
# Axis locks
ex.ribcage_copy_p.lock_location = True, True, True
# df.pelvis_p / DEF-wgt_pelvis
con = df.pelvis_p.constraints.new('COPY_LOCATION')
@@ -437,7 +440,10 @@ def main(obj, bone_definition, base_names, options):
# Add bend prop
prop_name = "bend_%.2d" % i
prop = rna_idprop_ui_prop_get(ex.ribcage_copy_p, prop_name, create=True)
ex.ribcage_copy_p[prop_name] = 1.0
if ("bend_%.2d" % i) in options:
ex.ribcage_copy_p[prop_name] = options["bend_%.2d" % i]
else:
ex.ribcage_copy_p[prop_name] = 1.0
prop["soft_min"] = 0.0
prop["soft_max"] = 1.0