Permalink
Find file
df40f7e Jul 10, 2016
193 lines (161 sloc) 8.67 KB
# SUMMARY: Uses an imported BVH from Brekel Kinect Face Pro 2 to
# create drivers to link a armature bones to mesh shape keys. Each
# driver maps an armature bone rotation to a shape key value between
# 0.0 and 1.0.
# COMPATABILITY: Tested with Blender v2.72 and v2.77a
# DOWNLOAD: Go to:
# https://github.com/gwbond/blender/blob/master/Brekel-Kinect-Face-Pro-2-Drivers-Add-On/animation_create_brekel_drivers.py
# and right-click on the 'Raw' button and select 'Save link as...' to
# download the file to your PC/Mac/Linux machine. Save the file as
# "animation_create_brekel_drivers.py"
# INSTALLATION: Install this add-on the usual way via User Preferences
# Addons "Install from File". Select the file you downloaded in the
# previous step. Once installed, this add-on is listed as "Create
# Brekel Kinect Face Pro 2 Drivers" in the "Animation" category.
# USAGE: Before using this add-on, import a Brekel Kinect Face Pro 2
# BVH motion capture file. This will create an armature object. To use
# this add-on, in object mode, select a mesh object with shape keys
# you want to create Brekel drivers for (or shift-select multiple mesh
# objects with shape keys you want to create drivers for). Then,
# shift-select the armature object i.e., the last object to select
# should be the armature. Finally, to create the drivers invoke this
# add-on via the operator search dialog (press spacebar and search for
# "Create Brekel Drivers"). Drivers will only be created for shape
# keys whose name matches an armature bone name. Drivers will not be
# created for shape keys that already have drivers.
# BUGS/ENHANCEMENTS: Feel free report bugs, suggest enhancements or,
# even better, contribute changes to the code. It's hosted on github
# at:
# https://github.com/gwbond/blender/blob/master/Brekel-Kinect-Face-Pro-2-Drivers-Add-On/animation_create_brekel_drivers.py
# LICENSE: GPL v2 or later
bl_info = {
"name": "Create Brekel Kinect Face Pro 2 Drivers",
"version": (1, 0),
"location": 'Press spacebar and search for: "Create Brekel Drivers"',
"category": "Animation",
}
import bpy
class CreateBrekelDrivers( bpy.types.Operator ):
# Tooltip.
""""Create Brekel Kinect Face Pro 2 Drivers"""
# Unique internal identifier
bl_idname = "object.create_brekel_drivers"
# Interface display name.
bl_label = "Create Brekel Drivers"
# Enable "undo".
bl_options = { 'REGISTER', 'UNDO' }
def execute(self, context):
# Error checking.
if len( context.selected_objects ) < 2 :
self.report( { 'ERROR' },
"Must select at least one mesh object and shift-select Brekel armature." )
return { 'CANCELLED' }
if context.active_object.type != 'ARMATURE' :
self.report( { 'ERROR' },
"Must shift-select Brekel armature object last." )
return { 'CANCELLED' }
meshes = [ mesh for mesh in context.selected_objects \
if mesh != context.active_object ]
for mesh in meshes :
if ( 'shape_keys' not in dir( mesh.data ) ) or \
( mesh.data.shape_keys == None ) :
self.report( { 'ERROR' },
"Selected mesh object does not contain shape keys.: %s" % mesh.name )
return { 'CANCELLED' }
# Set rotation mode for armature bones to use same mode that
# Brekel BVH armature bone animation does: Euler ZXY
brekel_armature = context.active_object
for pose_bone in brekel_armature.pose.bones:
pose_bone.rotation_mode = 'ZXY'
# Adding drivers.
driver_counts = []
for mesh in meshes :
driver_count = 0
# Initialize list of mesh's existing driver data
# paths. Driver's data path indicates its associated shape
# key e.g., mesh driver data path
# 'key_blocks["Frown_R"].value' is identified with mesh
# shape key "Frown_R".
mesh_driver_data_paths = []
if mesh.data.shape_keys.animation_data != None and \
mesh.data.shape_keys.animation_data.drivers != None:
mesh_driver_data_paths = [ driver.data_path for driver in
mesh.data.shape_keys.\
animation_data.drivers ]
for bone in brekel_armature.data.bones :
# Don't create driver if mesh doesn't have shape key
# for current bone or if shape key for bone already
# has a driver.
if not ( bone.name in mesh.data.shape_keys.key_blocks ) or \
( 'key_blocks["%s"].value' % bone.name in \
mesh_driver_data_paths ) :
continue
# Add shape key driver.
driver_count = driver_count + 1
new_driver = mesh.data.shape_keys.key_blocks[ bone.name ].\
driver_add( 'value' )
new_driver.extrapolation = 'LINEAR'
# Brekel armature encodes shape key values as bone
# X-axis rotations between 0 and 100 degrees. Blender
# drivers, however, interpret rotation value in
# radians so the driver uses an interpolation curve to
# map input value in interval [ 0, 1.7433 ] radians to
# shape key value in interval [ 0, 1 ].
# Add three no-op Bezier interpolation keyframes at
# min (0 rad = 0 degrees), mid (0.8727 rad = 50
# degrees), and max (1.7433 rad = 100 degrees) shape
# key values in case interpolation control is
# desired. NOTE: To view and manipulate keyframes,
# select a driver in the "Graph Editor" "Drivers"
# window, and either "mute" or delete any driver
# modifiers that appear at the bottom of the driver
# properties window.
new_driver.keyframe_points.add( 3 )
# Keyframe at min value 0.0 radians.
new_driver.keyframe_points[0].co = ( 0.0, 0.0 )
new_driver.keyframe_points[0].handle_right_type = 'VECTOR'
new_driver.keyframe_points[0].handle_left_type = 'VECTOR'
new_driver.keyframe_points[0].handle_left = ( -0.349, -0.2 )
new_driver.keyframe_points[0].handle_right = ( 0.349, 0.2 )
# Keyframe at mid value 0.872665 radians.
new_driver.keyframe_points[1].co = ( 0.872665, 0.5 )
new_driver.keyframe_points[1].handle_right_type = 'VECTOR'
new_driver.keyframe_points[1].handle_left_type = 'VECTOR'
new_driver.keyframe_points[1].handle_left = ( 0.524, 0.3 )
new_driver.keyframe_points[1].handle_right = ( 1.222, 0.7 )
# Keyframe at max value 1.74533 radians.
new_driver.keyframe_points[2].co = ( 1.74533, 1.0 )
new_driver.keyframe_points[2].handle_right_type = 'VECTOR'
new_driver.keyframe_points[2].handle_left_type = 'VECTOR'
new_driver.keyframe_points[2].handle_left = ( 1.396, 0.8 )
new_driver.keyframe_points[2].handle_right = ( 2.094, 1.2 )
# Remove any default modifiers that may have been
# added to the driver because they will override the
# interpolation keyframes added above.
for modifier in new_driver.modifiers:
new_driver.modifiers.remove(modifier)
# Link driver to bone rotation.
new_driver.driver.type = 'AVERAGE'
new_variable = new_driver.driver.variables.new()
new_variable.type = 'TRANSFORMS'
new_variable.targets[0].id = brekel_armature
new_variable.targets[0].bone_target = bone.name
new_variable.targets[0].transform_space = 'LOCAL_SPACE'
new_variable.targets[0].transform_type = 'ROT_X'
driver_counts.append( ( mesh, driver_count ) )
# Report statistics.
count_string = ""
for ( mesh, count ) in driver_counts:
count_string += "%d drivers added to %s. " % ( count, mesh.name )
if count_string == "" :
self.report( { 'INFO' }, "No drivers added to any objects" )
else :
self.report( { 'INFO' }, count_string )
return { 'FINISHED' }
def register():
bpy.utils.register_class( CreateBrekelDrivers )
def unregister():
bpy.utils.unregister_class( CreateBrekelDrivers )
# For manual testing.
if __name__ == "__main__":
register()