[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [26582] trunk/blender/release/scripts/ modules/rigify/shape_key_transforms.py: Added a new rig type " shape_key_transforms" that drives shape keys based on the local transforms of a single bone.
joe
joeedh at gmail.com
Thu Feb 4 01:35:29 CET 2010
A field for an offset might be nice too, for shape keys driving
multiple keys (looks like you could drive 2 keys with this, by
negating the multiplier, but not more then that).
Joe
On Wed, Feb 3, 2010 at 7:40 AM, Nathan Vegdahl <cessen at cessen.com> wrote:
> Revision: 26582
> http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=26582
> Author: cessen
> Date: 2010-02-03 16:40:56 +0100 (Wed, 03 Feb 2010)
>
> Log Message:
> -----------
> Added a new rig type "shape_key_transforms" that drives shape keys based on the local transforms of a single bone. Quite useful in a variety of situations.
>
> Required options:
> mesh: name of mesh object(s) to add/get shapekeys to/from
> (if multiple objects, make a comma-separated list)
> Optional options:
> loc_<x/y/z>: name of the shape key to tie to translation of the bone
> loc_<x/y/z>_fac: default multiplier of the bone influence on the shape key
> rot_<x/y/z>: name of the shape key to tie to rotation of the bone
> rot_<x/y/z>_fac: default multiplier of the bone influence on the shape key
> scale_<x/y/z>: name of the shape key to tie to scale of the bone
> scale_<x/y/z>_fac: default multiplier of the bone influence on the shape key
>
> Added Paths:
> -----------
> trunk/blender/release/scripts/modules/rigify/shape_key_transforms.py
>
> Added: trunk/blender/release/scripts/modules/rigify/shape_key_transforms.py
> ===================================================================
> --- trunk/blender/release/scripts/modules/rigify/shape_key_transforms.py (rev 0)
> +++ trunk/blender/release/scripts/modules/rigify/shape_key_transforms.py 2010-02-03 15:40:56 UTC (rev 26582)
> @@ -0,0 +1,263 @@
> +# ##### 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 rigify import RigifyError
> +from rigify_utils import copy_bone_simple
> +from rna_prop_ui import rna_idprop_ui_prop_get
> +
> +#METARIG_NAMES = ("cpy",)
> +RIG_TYPE = "shape_key_transforms"
> +
> +
> +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
> + new = False
> + 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'
> + new = True
> +
> + return fcurve, new
> +
> +
> +# TODO:
> +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'
> + pass
> +
> +
> +def metarig_definition(obj, orig_bone_name):
> + bone = obj.data.bones[orig_bone_name]
> + return [bone.name]
> +
> +
> +def main(obj, definitions, base_names, options):
> + """ A rig that drives shape keys with the local transforms of a single bone.
> +
> + Required options:
> + mesh: name of mesh object(s) to add/get shapekeys to/from
> + (if multiple objects, make a comma-separated list)
> + Optional options:
> + loc_<x/y/z>: name of the shape key to tie to translation of the bone
> + loc_<x/y/z>_fac: default multiplier of the bone influence on the shape key
> + rot_<x/y/z>: name of the shape key to tie to rotation of the bone
> + rot_<x/y/z>_fac: default multiplier of the bone influence on the shape key
> + scale_<x/y/z>: name of the shape key to tie to scale of the bone
> + scale_<x/y/z>_fac: default multiplier of the bone influence on the shape key
> + """
> +
> + bpy.ops.object.mode_set(mode='EDIT')
> + eb = obj.data.edit_bones
> + pb = obj.pose.bones
> +
> + org_bone = definitions[0]
> +
> + # 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]]))
> +
> + meshes = options["mesh"].replace(" ", "").split(",")
> +
> + bone = copy_bone_simple(obj.data, org_bone, base_names[org_bone], parent=True).name
> +
> + bpy.ops.object.mode_set(mode='OBJECT')
> +
> + # Set rotation mode and axis locks
> + pb[bone].rotation_mode = pb[org_bone].rotation_mode
> + pb[bone].lock_location = tuple(pb[org_bone].lock_location)
> + pb[bone].lock_rotation = tuple(pb[org_bone].lock_rotation)
> + pb[bone].lock_rotation_w = pb[org_bone].lock_rotation_w
> + pb[bone].lock_rotations_4d = pb[org_bone].lock_rotations_4d
> + pb[bone].lock_scale = tuple(pb[org_bone].lock_scale)
> +
> + # List of rig options for specifying shape keys
> + # Append '_fac' to the end for the name of the correspond 'factor default'
> + # option for that shape
> + shape_key_options = ["loc_x",
> + "loc_y",
> + "loc_z",
> + "rot_x",
> + "rot_y",
> + "rot_z",
> + "scale_x",
> + "scale_y",
> + "scale_z"]
> +
> + driver_paths = {"loc_x":".location[0]",
> + "loc_y":".location[1]",
> + "loc_z":".location[2]",
> + "rot_x":".rotation_euler[0]",
> + "rot_y":".rotation_euler[1]",
> + "rot_z":".rotation_euler[2]",
> + "qrot_x":".rotation_quaternion[1]",
> + "qrot_y":".rotation_quaternion[2]",
> + "qrot_z":".rotation_quaternion[3]",
> + "scale_x":".scale[0]",
> + "scale_y":".scale[1]",
> + "scale_z":".scale[2]"}
> +
> + # Create the shape keys and drivers
> + shape_info = []
> + for option in shape_key_options:
> + if option in options:
> + shape_name = options[option]
> +
> + var_name = bone + "_" + option
> + # Different paths for euler vs quat
> + if option in shape_key_options[3:6] and pb[bone].rotation_mode == 'QUATERNION':
> + var_path = driver_paths['q' + option]
> + else:
> + var_path = driver_paths[option]
> +
> + fac_name = option + "_factor"
> + if (option+"_fac") in options:
> + fac_default = options[option+"_fac"]
> + else:
> + fac_default = 1.0
> +
> + # Different expressions for loc/rot/scale
> + if option in shape_key_options[:3]:
> + expression = var_name + " * " + fac_name
> + elif option in shape_key_options[:6]:
> + # Different expressions for euler vs quats
> + if pb[bone].rotation_mode == 'QUATERNION':
> + expression = "2 * asin(" + var_name + ") * " + fac_name
> + else:
> + expression = var_name + " * " + fac_name
> + else:
> + expression = "(1.0 - " + var_name + ") * " + fac_name + " * -2"
> +
> + create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, fac_name, fac_default, expression)
> +
> + return (None,)
> +
> +
> +def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, fac_name, fac_default, expression):
> + """ Creates/gets a shape key and sets up a driver for it.
> +
> + obj = armature object
> + bone = driving bone name
> + meshes = list of meshes to create the shapekey/driver on
> + shape_name = name of the shape key
> + var_name = name of the driving variable
> + var_path = path to the property on the bone to drive with
> + fac_name = name of the "factor" custom property on the bone
> + fac_default = default starting value of the factor property
> + expression = python expression for the driver
> + """
> + pb = obj.pose.bones
> + bpy.ops.object.mode_set(mode='OBJECT')
> +
> + # Set up the "factor" custom property on the bone
> + prop = rna_idprop_ui_prop_get(pb[bone], fac_name, create=True)
> + pb[bone][fac_name] = fac_default
> + prop["min"] = -1000.0
> + prop["max"] = 1000.0
> + prop["soft_min"] = -1000.0
> + prop["soft_max"] = 1000.0
> +
> + for mesh_name in meshes:
> + mesh_obj = bpy.data.objects[mesh_name]
> +
> + # Add/get the shape key
> + shape = addget_shape_key(mesh_obj, name=shape_name)
> +
> + # Add/get the shape key driver
> + fcurve, a = addget_shape_key_driver(mesh_obj, name=shape_name)
> +
> + # Set up the driver
> + driver = fcurve.driver
> + driver.type = 'SCRIPTED'
> + driver.expression = expression
> +
> + # Get the variable, or create it if it doesn't already exist
> + if var_name in driver.variables:
> + var = driver.variables[var_name]
> + else:
> + var = driver.variables.new()
> + var.name = var_name
> +
> + # Get the fac variable, or create it if it doesn't already exist
> + if fac_name in driver.variables:
> + var_fac = driver.variables[fac_name]
> + else:
> + var_fac = driver.variables.new()
> + var_fac.name = fac_name
> +
> + # Set up the variable
> + var.type = "SINGLE_PROP"
> + var.targets[0].id_type = 'OBJECT'
> + var.targets[0].id = obj
> + var.targets[0].data_path = 'pose.bones["' + bone + '"]' + var_path
> +
> + # Set up the fac variable
> + var_fac.type = "SINGLE_PROP"
> + var_fac.targets[0].id_type = 'OBJECT'
> + var_fac.targets[0].id = obj
> + var_fac.targets[0].data_path = 'pose.bones["' + bone + '"]["' + fac_name + '"]'
> +
> +
> +def main(obj, bone_definition, base_names, options):
> + control(obj, bone_definition, base_names, options)
> +
> +
> + return (None,)
> +
>
>
> _______________________________________________
> Bf-blender-cvs mailing list
> Bf-blender-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>
More information about the Bf-committers
mailing list