[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