[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25139] trunk/blender/release/scripts/ modules/rigify: split up metarig hierarchy evaluation and modifying the metarig into 2 steps ,

Campbell Barton ideasman42 at gmail.com
Sat Dec 5 20:26:28 CET 2009


Revision: 25139
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25139
Author:   campbellbarton
Date:     2009-12-05 20:26:28 +0100 (Sat, 05 Dec 2009)

Log Message:
-----------
split up metarig hierarchy evaluation and modifying the metarig into 2 steps,
original bone names cant be changed anymore but this means the bones can be re-parented without confusing scripts that run after the rig is modified.
support for defining a bone to have multiple types and  automatically blending between 2 generated rigs

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/rigify/__init__.py
    trunk/blender/release/scripts/modules/rigify/arm.py
    trunk/blender/release/scripts/modules/rigify/delta.py
    trunk/blender/release/scripts/modules/rigify/finger.py
    trunk/blender/release/scripts/modules/rigify/leg.py
    trunk/blender/release/scripts/modules/rigify/neck.py
    trunk/blender/release/scripts/modules/rigify/palm.py
    trunk/blender/release/scripts/modules/rigify/spine.py

Modified: trunk/blender/release/scripts/modules/rigify/__init__.py
===================================================================
--- trunk/blender/release/scripts/modules/rigify/__init__.py	2009-12-05 19:05:21 UTC (rev 25138)
+++ trunk/blender/release/scripts/modules/rigify/__init__.py	2009-12-05 19:26:28 UTC (rev 25139)
@@ -91,6 +91,7 @@
 
         new_slot_ls.append(attr)
         from_name_ls.append(bone_name)
+        bone_name_orig = bone_name_orig.replace("ORG-", "") # XXX - we need a better way to do this
         new_name_ls.append(to_prefix + bone_name_orig)
         
     new_bones = copy_bone_simple_list(self.obj.data, from_name_ls, new_name_ls, True)
@@ -103,8 +104,10 @@
 
     return new_bc
 
+def _bone_class_instance_names(self):
+    return [getattr(self, attr) for attr in self.attr_names]
 
-def _bone_class_instance_blend(self, from_bc, to_bc, target_bone=None, target_prop="blend", use_loc=True, use_rot=True):
+def _bone_class_instance_blend(self, from_bc, to_bc, target_bone=None, target_prop="blend"):
     '''
     Use for blending bone chains.
     
@@ -113,78 +116,19 @@
     
     XXX - toggles editmode, need to re-validate all editbones :(
     '''
+
     if self.attr_names != from_bc.attr_names or self.attr_names != to_bc.attr_names:
         raise Exception("can only blend between matching chains")
-
-    obj = self.obj
     
-    if obj.mode == 'EDIT':
-        raise Exception("blending cant be called in editmode")
+    apply_bones = [getattr(self, attr) for attr in self.attr_names]
+    from_bones = [getattr(from_bc, attr) for attr in from_bc.attr_names]
+    to_bones = [getattr(to_bc, attr) for attr in to_bc.attr_names]
     
-    # setup the blend property
-    if target_bone is None:
-        target_bone = self.attr_names[-1]
+    blend_bone_list(self.obj, apply_bones, from_bones, to_bones, target_bone, target_prop)
 
-    prop_pbone = obj.pose.bones[target_bone]
-    if prop_pbone.get(target_bone, None) is None:
-        prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True)
-        prop_pbone[target_prop] = 0.5
-        prop["soft_min"] = 0.0
-        prop["soft_max"] = 1.0
-
-    driver_path = prop_pbone.path_to_id() + ('["%s"]' % target_prop)
-
-    def blend_target(driver):
-        tar = driver.targets.new()
-        tar.name = target_bone
-        tar.id_type = 'OBJECT'
-        tar.id = obj
-        tar.rna_path = driver_path
-
-    for attr in self.attr_names:
-        new_pbone = getattr(self, attr + "_p")
-        from_bone_name = getattr(from_bc, attr)
-        to_bone_name = getattr(to_bc, attr)
-        
-        if from_bone_name == to_bone_name:
-            raise Exception("Matching from/to bone names:" + from_bone_name)
-        
-        if use_loc:
-            con = new_pbone.constraints.new('COPY_LOCATION')
-            con.target = obj
-            con.subtarget = from_bone_name
-
-            con = new_pbone.constraints.new('COPY_LOCATION')
-            con.target = obj
-            con.subtarget = to_bone_name
-            
-            fcurve = con.driver_add("influence", 0)
-            driver = fcurve.driver
-            driver.type = 'AVERAGE'
-            fcurve.modifiers.remove(0) # grr dont need a modifier
-
-            blend_target(driver)
-        
-        if use_rot:
-            con = new_pbone.constraints.new('COPY_ROTATION')
-            con.target = obj
-            con.subtarget = from_bone_name
-
-            con = new_pbone.constraints.new('COPY_ROTATION')
-            con.target = obj
-            con.subtarget = to_bone_name
-            
-            fcurve = con.driver_add("influence", 0)
-            driver = fcurve.driver
-            driver.type = 'AVERAGE'
-            fcurve.modifiers.remove(0) # grr dont need a modifier
-
-            blend_target(driver)
-
-
 def bone_class_instance(obj, slots, name="BoneContainer"):
     attr_names = tuple(slots) # dont modify the original
-    slots = slots[:] # dont modify the original
+    slots = list(slots) # dont modify the original
     for i in range(len(slots)):
         member = slots[i]
         slots.append(member + "_b") # bone bone
@@ -196,6 +140,7 @@
         "attr_names":attr_names, \
         "update":_bone_class_instance_update, \
         "rename":_bone_class_instance_rename, \
+        "names":_bone_class_instance_names, \
         "copy":_bone_class_instance_copy, \
         "blend":_bone_class_instance_blend, \
     }
@@ -254,7 +199,79 @@
     
     return copy_bones
 
+def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, target_prop="blend"):
+    
+    if obj.mode == 'EDIT':
+        raise Exception("blending cant be called in editmode")
+    
+    # setup the blend property
+    if target_bone is None:
+        target_bone = apply_bones[-1] # default to the last bone
 
+    prop_pbone = obj.pose.bones[target_bone]
+    if prop_pbone.get(target_bone, None) is None:
+        prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True)
+        prop_pbone[target_prop] = 0.5
+        prop["soft_min"] = 0.0
+        prop["soft_max"] = 1.0
+
+    driver_path = prop_pbone.path_to_id() + ('["%s"]' % target_prop)
+
+    def blend_target(driver):
+        tar = driver.targets.new()
+        tar.name = target_bone
+        tar.id_type = 'OBJECT'
+        tar.id = obj
+        tar.rna_path = driver_path
+    
+    def blend_location(new_pbone, from_bone_name, to_bone_name):
+        con = new_pbone.constraints.new('COPY_LOCATION')
+        con.target = obj
+        con.subtarget = from_bone_name
+
+        con = new_pbone.constraints.new('COPY_LOCATION')
+        con.target = obj
+        con.subtarget = to_bone_name
+        
+        fcurve = con.driver_add("influence", 0)
+        driver = fcurve.driver
+        driver.type = 'AVERAGE'
+        fcurve.modifiers.remove(0) # grr dont need a modifier
+
+        blend_target(driver)
+
+    def blend_rotation(new_pbone, from_bone_name, to_bone_name):
+        con = new_pbone.constraints.new('COPY_ROTATION')
+        con.target = obj
+        con.subtarget = from_bone_name
+
+        con = new_pbone.constraints.new('COPY_ROTATION')
+        con.target = obj
+        con.subtarget = to_bone_name
+        
+        fcurve = con.driver_add("influence", 0)
+        driver = fcurve.driver
+        driver.type = 'AVERAGE'
+        fcurve.modifiers.remove(0) # grr dont need a modifier
+
+        blend_target(driver)
+
+    for i, new_bone_name in enumerate(apply_bones):
+        from_bone_name = from_bones[i]
+        to_bone_name = to_bones[i]
+        
+        # allow skipping some bones by having None in the list
+        if None in (new_bone_name, from_bone_name, to_bone_name):
+            continue
+
+        new_pbone = obj.pose.bones[new_bone_name]
+
+        if not new_pbone.bone.connected:
+            blend_location(new_pbone, from_bone_name, to_bone_name)
+        
+        blend_rotation(new_pbone, from_bone_name, to_bone_name)
+
+
 def add_stretch_to(obj, from_name, to_name, name):
     '''
     Adds a bone that stretches from one to another
@@ -342,8 +359,9 @@
     return poll_name
 
 
-def generate_rig(context, ob):
-    
+def generate_rig(context, obj_orig, prefix="ORG-"):
+    from collections import OrderedDict
+
     global_undo = context.user_preferences.edit.global_undo
     context.user_preferences.edit.global_undo = False
 
@@ -351,50 +369,118 @@
     
     
     # copy object and data
-    ob.selected = False
-    ob_new = ob.copy()
-    ob_new.data = ob.data.copy()
+    obj_orig.selected = False
+    obj = obj_orig.copy()
+    obj.data = obj_orig.data.copy()
     scene = context.scene
-    scene.objects.link(ob_new)
-    scene.objects.active = ob_new
-    ob_new.selected = True
+    scene.objects.link(obj)
+    scene.objects.active = obj
+    obj.selected = True
     
-    # enter armature editmode
+    arm = obj.data
     
-    # Only reference bones that have a type, means we can rename any others without lookup errors
-    pose_names = [pbone.name for pbone in ob_new.pose.bones if "type" in pbone]
+    # original name mapping
+    base_names = {}
     
-    #for pbone_name in ob_new.pose.bones.keys():
-    for pbone_name in pose_names:
+    bpy.ops.object.mode_set(mode='EDIT')
+    for bone in arm.edit_bones:
+        bone_name = bone.name
+        bone.name = prefix + bone_name
+        base_names[bone.name] = bone_name # new -> old mapping
+    bpy.ops.object.mode_set(mode='OBJECT')
     
-        bone_type = ob_new.pose.bones[pbone_name].get("type", "")
+    # key: bone name
+    # value: {type:definition, ...}
+    #    where type is the submodule name - leg, arm etc
+    #    and definition is a list of bone names 
+    bone_definitions = {}
+    
+    # key: bone name
+    # value: [functions, ...]
+    #    each function is from the module. eg leg.ik, arm.main
+    bone_typeinfos = {}
+    
+    # inspect all bones and assign their definitions before modifying
+    for pbone in obj.pose.bones:
+        bone_name = pbone.name
+        bone_type = obj.pose.bones[bone_name].get("type", "")
+        bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
 
-        if bone_type == "":
-        	continue
+        for bone_type in bone_type_list:
+            type_pair = bone_type.split(".")
+            
+            # 'leg.ik' will look for an ik function in the leg module
+            # 'leg' will look up leg.main
+            if len(type_pair) == 1:
+                type_pair = type_pair[0], "main"
+            
+            submod_name, func_name = type_pair
+            
+            # from rigify import leg
+            submod = __import__(name="%s.%s" % (__package__, submod_name), fromlist=[submod_name])
+            reload(submod)
+            
+            bone_def_dict = bone_definitions.setdefault(bone_name, {})
 
-        # submodule = getattr(self, bone_type)
-        # exec("from rigify import %s as submodule")
-        submodule = __import__(name="%s.%s" % (__package__, bone_type), fromlist=[bone_type])
+            # Only calculate bone definitions once
+            if submod_name not in bone_def_dict:
+                metarig_definition_func = getattr(submod, "metarig_definition")
+                bone_def_dict[submod_name] = metarig_definition_func(obj, bone_name)
+            
+            
+            bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
+            type_func = getattr(submod, func_name)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list