[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [28072] trunk/blender/release/scripts/ modules/rigify: Added tongue and neck rigs.

Nathan Vegdahl cessen at cessen.com
Wed Apr 7 16:46:06 CEST 2010


Revision: 28072
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=28072
Author:   cessen
Date:     2010-04-07 16:46:06 +0200 (Wed, 07 Apr 2010)

Log Message:
-----------
Added tongue and neck rigs.  The neck rig is quite solid, I think, and is working well in production on Durian.  The tongue rig is a bit hacky, but I'm adding it for now since we're using it in Durian.
Also added pupil dilation to the eye rig type, and made the finger rig type work with two-digit fingers.

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/rigify/eye_balls.py
    trunk/blender/release/scripts/modules/rigify/finger_curl.py

Added Paths:
-----------
    trunk/blender/release/scripts/modules/rigify/neck.py
    trunk/blender/release/scripts/modules/rigify/tongue.py

Modified: trunk/blender/release/scripts/modules/rigify/eye_balls.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/eye_balls.py	2010-04-07 14:01:59 UTC (rev 28071)
+++ trunk/blender/release/scripts/modules/rigify/eye_balls.py	2010-04-07 14:46:06 UTC (rev 28072)
@@ -27,6 +27,85 @@
 #METARIG_NAMES = ("cpy",)
 RIG_TYPE = "eye_balls"
 
+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
+   
+    
+def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, 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
+        expression = python expression for the driver
+    """
+    pb = obj.pose.bones
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    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
+
+        # 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
+
+
 def mark_actions():
     for action in bpy.data.actions:
         action.tag = True
@@ -120,6 +199,12 @@
     head = definitions[0]
     eye_target = definitions[1]
 
+    # Get list of pupil mesh objects
+    if "mesh" in options:
+        pupil_meshes = options["mesh"].replace(" ", "").split(",")
+    else:
+        pupil_meshes = []
+
     # Get list of eyes
     if "eyes" in options:
         eye_base_names = options["eyes"].replace(" ", "").split(",")
@@ -246,9 +331,53 @@
         con.minimum = 0.0
         con.maximum = 2.0
         con.target_space = 'LOCAL'
+    
+    
+    # Get/create the shape keys and drivers for pupil dilation
+    shape_names = ["PUPILS-dilate_wide", "PUPILS-dilate_narrow"]
+    slider_name = "pupil_dilate"
+    
+    # Set up the custom property on the bone
+    prop = rna_idprop_ui_prop_get(pb[target_ctrl], slider_name, create=True)
+    pb[target_ctrl][slider_name] = 0.0
+    prop["min"] = 0.0
+    prop["max"] = 1.0
+    prop["soft_min"] = 0.0
+    prop["soft_max"] = 1.0
+    if len(shape_names) > 1:
+        prop["min"] = -1.0
+        prop["soft_min"] = -1.0
 
+    # Add the shape drivers
+    # Positive
+    if shape_names[0] != "":
+        # Set up the variables for creating the shape key driver
+        shape_name = shape_names[0]
+        var_name = slider_name.replace(".", "_").replace("-", "_")
+        var_path = '["' + slider_name + '"]'
+        if slider_name + "_fac" in options:
+            fac = options[slider_name + "_fac"]
+        else:
+            fac = 1.0
+        expression = var_name + " * " + str(fac)
+        # Create the shape key driver
+        create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
+    # Negative
+    if shape_names[0] != "" and len(shape_names) > 1:
+        # Set up the variables for creating the shape key driver
+        shape_name = shape_names[1]
+        var_name = slider_name.replace(".", "_").replace("-", "_")
+        var_path = '["' + slider_name + '"]'
+        if slider_name + "_fac" in options:
+            fac = options[slider_name + "_fac"]
+        else:
+            fac = 1.0
+        expression = var_name + " * " + str(fac) + " * -1"
+        # Create the shape key driver
+        create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
 
 
+
     # Set layers
     #layer = list(bb[definitions[2]].layer)
     #bb[lid1].layer = layer

Modified: trunk/blender/release/scripts/modules/rigify/finger_curl.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/finger_curl.py	2010-04-07 14:01:59 UTC (rev 28071)
+++ trunk/blender/release/scripts/modules/rigify/finger_curl.py	2010-04-07 14:46:06 UTC (rev 28072)
@@ -57,31 +57,20 @@
 def metarig_definition(obj, orig_bone_name):
     '''
     The bone given is the first in a chain
-    Expects a chain of at least 2 children.
+    Expects a chain with at least 1 child of the same base name.
     eg.
-        finger -> finger_01 -> finger_02
+        finger_01 -> finger_02
     '''
 
-    bone_definition = []
-
     orig_bone = obj.data.bones[orig_bone_name]
 
-    bone_definition.append(orig_bone.name)
-
-    bone = orig_bone
-    chain = 0
-    while chain < 2: # first 2 bones only have 1 child
-        children = bone.children
-
-        if len(children) != 1:
-            raise RigifyError("expected the chain to have 2 children from bone '%s' without a fork" % orig_bone_name)
-        bone = children[0]
-        bone_definition.append(bone.name) # finger_02, finger_03
-        chain += 1
-
-    if len(bone_definition) != len(METARIG_NAMES):
-        raise RigifyError("internal problem, expected %d bones" % len(METARIG_NAMES))
-
+    bone_definition = [orig_bone.name]
+    
+    bone_definition.extend([child.name for child in orig_bone.children_recursive_basename])
+    
+    if len(bone_definition) < 2:
+        raise RigifyError("expected the chain to have at least 1 child from bone '%s' without the same base name" % orig_bone_name)
+    
     return bone_definition
 
 
@@ -90,6 +79,8 @@
     """
     bpy.ops.object.mode_set(mode='EDIT')
 
+    three_digits = True if len(definitions) > 2 else False
+
     # Create base digit bones: two bones, each half of the base digit.
     f1a = copy_bone_simple(obj.data, definitions[0], "DEF-%s.01" % base_names[definitions[0]], parent=True)
     f1b = copy_bone_simple(obj.data, definitions[0], "DEF-%s.02" % base_names[definitions[0]], parent=True)
@@ -102,13 +93,15 @@
 
     # Create the other deform bones.
     f2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s" % base_names[definitions[1]], parent=True)
-    f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True)
+    if three_digits:
+        f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True)
 
     # Store names before leaving edit mode
     f1a_name = f1a.name
     f1b_name = f1b.name
     f2_name = f2.name
-    f3_name = f3.name
+    if three_digits:
+        f3_name = f3.name
 
     # Leave edit mode
     bpy.ops.object.mode_set(mode='OBJECT')
@@ -117,7 +110,8 @@
     f1a = obj.pose.bones[f1a_name]
     f1b = obj.pose.bones[f1b_name]
     f2 = obj.pose.bones[f2_name]
-    f3 = obj.pose.bones[f3_name]
+    if three_digits:
+        f3 = obj.pose.bones[f3_name]
 
     # Constrain the base digit's bones
     con = f1a.constraints.new('DAMPED_TRACK')
@@ -141,15 +135,18 @@
     con.target = obj
     con.subtarget = definitions[1]
 
-    con = f3.constraints.new('COPY_TRANSFORMS')
-    con.name = "copy_transforms"
-    con.target = obj
-    con.subtarget = definitions[2]
+    if three_digits:
+        con = f3.constraints.new('COPY_TRANSFORMS')
+        con.name = "copy_transforms"
+        con.target = obj
+        con.subtarget = definitions[2]
 
 
 def main(obj, bone_definition, base_names, options):
     # *** EDITMODE
     bpy.ops.object.mode_set(mode='EDIT')
+    
+    three_digits = True if len(bone_definition) > 2 else False
 
     # get assosiated data
     arm = obj.data
@@ -159,7 +156,8 @@
 
     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
+    if three_digits:
+        org_f3 = bone_definition[2] # Original finger bone 03
 
     # Check options
     if "bend_ratio" in options:
@@ -179,7 +177,10 @@
 
     # 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
+    if three_digits:
+        tot_len = eb[org_f1].length + eb[org_f2].length + eb[org_f3].length
+    else:
+        tot_len = eb[org_f1].length + eb[org_f2].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
@@ -188,26 +189,30 @@
     # 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

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list