[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [4279] trunk/py/scripts/addons/rigify: Rigify: the pre-built metarigs that appear in the add armature menu

Nathan Vegdahl cessen at cessen.com
Fri Feb 15 19:02:03 CET 2013


Revision: 4279
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=4279
Author:   cessen
Date:     2013-02-15 18:02:02 +0000 (Fri, 15 Feb 2013)
Log Message:
-----------
Rigify: the pre-built metarigs that appear in the add armature menu
are now dynamically pulled from python files in the metarigs
directory.  This makes adding new metarigs pretty painless.

Modified Paths:
--------------
    trunk/py/scripts/addons/rigify/metarig_menu.py
    trunk/py/scripts/addons/rigify/utils.py

Modified: trunk/py/scripts/addons/rigify/metarig_menu.py
===================================================================
--- trunk/py/scripts/addons/rigify/metarig_menu.py	2013-02-15 15:30:45 UTC (rev 4278)
+++ trunk/py/scripts/addons/rigify/metarig_menu.py	2013-02-15 18:02:02 UTC (rev 4279)
@@ -18,40 +18,108 @@
 
 # <pep8 compliant>
 
+import os
+from string import capwords
+
 import bpy
-from rigify.metarigs import human
+from . import utils
 
 
-class AddHuman(bpy.types.Operator):
-    """Add an advanced human metarig base"""
-    bl_idname = "object.armature_human_advanced_add"
-    bl_label = "Add Humanoid (advanced metarig)"
-    bl_options = {'REGISTER', 'UNDO'}
+def get_metarig_list(path):
+    """ Searches for metarig modules, and returns a list of the
+        imported modules.
+    """
+    metarigs = []
+    MODULE_DIR = os.path.dirname(__file__)
+    METARIG_DIR_ABS = os.path.join(MODULE_DIR, utils.METARIG_DIR)
+    SEARCH_DIR_ABS = os.path.join(METARIG_DIR_ABS, path)
+    files = os.listdir(SEARCH_DIR_ABS)
+    files.sort()
 
+    for f in files:
+        # Is it a directory?
+        if os.path.isdir(os.path.join(SEARCH_DIR_ABS, f)):
+            continue
+        elif not f.endswith(".py"):
+            continue
+        elif f == "__init__.py":
+            continue
+        else:
+            module_name = f[:-3]
+            try:
+                metarigs += [utils.get_metarig_module(module_name)]
+            except (ImportError):
+                pass
+    return metarigs
+
+
+def make_metarig_add_execute(m):
+    """ Create an execute method for a metarig creation operator.
+    """
     def execute(self, context):
+        # Add armature object
         bpy.ops.object.armature_add()
         obj = context.active_object
-        mode_orig = obj.mode
-        bpy.ops.object.mode_set(mode='EDIT')  # grr, remove bone
+        obj.name = "metarig"
+        
+        # Remove default bone
+        bpy.ops.object.mode_set(mode='EDIT')
         bones = context.active_object.data.edit_bones
         bones.remove(bones[0])
-        human.create(obj)
-        bpy.ops.object.mode_set(mode=mode_orig)
+        
+        # Create metarig
+        m.create(obj)
+        
+        bpy.ops.object.mode_set(mode='OBJECT')
         return {'FINISHED'}
+    return execute
 
 
-# Add to a menu
-menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname,
-                    icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)"))
+def make_metarig_menu_func(bl_idname, text):
+    """ For some reason lambda's don't work for adding multiple menu
+        items, so we use this instead to generate the functions.
+    """
+    def metarig_menu(self, context):
+        self.layout.operator(bl_idname, icon='OUTLINER_OB_ARMATURE', text=text)
+    return metarig_menu
 
 
+
+# Get the metarig modules
+metarigs = get_metarig_list("")
+
+# Create metarig add Operators
+metarig_ops = []
+for m in metarigs:
+    name = m.__name__.rsplit('.', 1)[1]
+    
+    # Dynamically construct an Operator
+    T = type("Add_" + name + "_Metarig", (bpy.types.Operator,), {})
+    T.bl_idname = "object.armature_" + name + "_metarig_add"
+    T.bl_label = "Add " + name.replace("_", " ").capitalize() + " (metarig)"
+    T.bl_options = {'REGISTER', 'UNDO'}
+    T.execute = make_metarig_add_execute(m)
+        
+    metarig_ops.append((T, name))
+
+# Create menu functions
+menu_funcs = []
+for mop, name in metarig_ops:
+    text = capwords(name.replace("_", " ")) + " (Meta-Rig)"
+    
+    menu_funcs += [make_metarig_menu_func(mop.bl_idname, text)]
+
+
 def register():
-    bpy.utils.register_class(AddHuman)
+    for mop, name in metarig_ops:
+        bpy.utils.register_class(mop)
 
-    bpy.types.INFO_MT_armature_add.append(menu_func)
+    for mf in menu_funcs:
+        bpy.types.INFO_MT_armature_add.append(mf)
 
-
 def unregister():
-    bpy.utils.unregister_class(AddHuman)
+    for mop in metarig_ops:
+        bpy.utils.unregister_class(mop)
 
-    bpy.types.INFO_MT_armature_add.remove(menu_func)
+    for mf in menu_funcs:
+        bpy.types.INFO_MT_armature_add.remove(mf)

Modified: trunk/py/scripts/addons/rigify/utils.py
===================================================================
--- trunk/py/scripts/addons/rigify/utils.py	2013-02-15 15:30:45 UTC (rev 4278)
+++ trunk/py/scripts/addons/rigify/utils.py	2013-02-15 18:02:02 UTC (rev 4279)
@@ -26,6 +26,7 @@
 from rna_prop_ui import rna_idprop_ui_prop_get
 
 RIG_DIR = "rigs"  # Name of the directory where rig types are kept
+METARIG_DIR = "metarigs"  # Name of the directory where metarigs are kept
 
 ORG_PREFIX = "ORG-"  # Prefix of original bones.
 MCH_PREFIX = "MCH-"  # Prefix of mechanism bones.
@@ -421,6 +422,18 @@
     return submod
 
 
+def get_metarig_module(metarig):
+    """ Fetches a rig module by name, and returns it.
+    """
+    #print("%s.%s.%s" % (__package__,METARIG_DIR,metarig))
+    name="%s.%s.%s" % (MODULE_NAME, METARIG_DIR, metarig)
+    submod = __import__(name)
+    for c in (name.split("."))[1:]:
+        submod = getattr(submod, c)
+    imp.reload(submod)
+    return submod
+
+
 def connected_children_names(obj, bone_name):
     """ Returns a list of bone names (in order) of the bones that form a single
         connected chain starting with the given bone as a parent.



More information about the Bf-extensions-cvs mailing list