Changeset View
Changeset View
Standalone View
Standalone View
rigify/metarig_menu.py
| Show All 31 Lines | class ArmatureSubMenu(bpy.types.Menu): | ||||
| def draw(self, context): | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| layout.label(text=self.bl_label) | layout.label(text=self.bl_label) | ||||
| for op, name in self.operators: | for op, name in self.operators: | ||||
| text = capwords(name.replace("_", " ")) + " (Meta-Rig)" | text = capwords(name.replace("_", " ")) + " (Meta-Rig)" | ||||
| layout.operator(op, icon='OUTLINER_OB_ARMATURE', text=text) | layout.operator(op, icon='OUTLINER_OB_ARMATURE', text=text) | ||||
| def get_metarig_list(path, depth=0): | def get_metarigs(base_path, path, depth=0): | ||||
| """ Searches for metarig modules, and returns a list of the | """ Searches for metarig modules, and returns a list of the | ||||
| imported modules. | imported modules. | ||||
| """ | """ | ||||
| metarigs = [] | |||||
| metarigs_dict = dict() | metarigs = {} | ||||
| MODULE_DIR = os.path.dirname(__file__) | |||||
| METARIG_DIR_ABS = os.path.join(MODULE_DIR, utils.METARIG_DIR) | files = os.listdir(os.path.join(base_path, path)) | ||||
| SEARCH_DIR_ABS = os.path.join(METARIG_DIR_ABS, path) | |||||
| files = os.listdir(SEARCH_DIR_ABS) | |||||
| files.sort() | files.sort() | ||||
| for f in files: | for f in files: | ||||
| # Is it a directory? | is_dir = os.path.isdir(os.path.join(base_path, path, f)) # Whether the file is a directory | ||||
| complete_path = os.path.join(SEARCH_DIR_ABS, f) | |||||
| if os.path.isdir(complete_path) and depth == 0: | # Stop cases | ||||
| if f[0] != '_': | if f[0] in [".", "_"]: | ||||
| metarigs_dict[f] = get_metarig_list(f, depth=1) | |||||
| else: | |||||
| continue | |||||
| elif not f.endswith(".py"): | |||||
| continue | continue | ||||
| elif f == "__init__.py": | if f.count(".") >= 2 or (is_dir and "." in f): | ||||
| print("Warning: %r, filename contains a '.', skipping" % os.path.join(path, f)) | |||||
| continue | continue | ||||
| else: | |||||
| module_name = f[:-3] | if is_dir: # Check directories | ||||
| try: | # Check for sub-metarigs | ||||
| metarigs[f] = get_metarigs(base_path, os.path.join(path, f, ""), depth=1) # "" adds a final slash | |||||
| elif f.endswith(".py"): | |||||
| # Check straight-up python files | |||||
| f = f[:-3] | |||||
| module_name = os.path.join(path, f).replace(os.sep, ".") | |||||
| metarig_module = utils.get_resource(module_name, base_path=base_path) | |||||
| if depth == 1: | if depth == 1: | ||||
| metarigs += [utils.get_metarig_module(module_name, utils.METARIG_DIR + '.' + path)] | metarigs[f] = metarig_module | ||||
| else: | else: | ||||
| metarigs += [utils.get_metarig_module(module_name, utils.METARIG_DIR)] | metarigs[utils.METARIG_DIR] = {f: metarig_module} | ||||
| except (ImportError): | |||||
| pass | |||||
| if depth == 1: | |||||
| return metarigs | return metarigs | ||||
| metarigs_dict[utils.METARIG_DIR] = metarigs | |||||
| return metarigs_dict | |||||
| def make_metarig_add_execute(m): | def make_metarig_add_execute(m): | ||||
| """ Create an execute method for a metarig creation operator. | """ Create an execute method for a metarig creation operator. | ||||
| """ | """ | ||||
| def execute(self, context): | def execute(self, context): | ||||
| # Add armature object | # Add armature object | ||||
| bpy.ops.object.armature_add() | bpy.ops.object.armature_add() | ||||
| obj = context.active_object | obj = context.active_object | ||||
| Show All 24 Lines | |||||
| def make_submenu_func(bl_idname, text): | def make_submenu_func(bl_idname, text): | ||||
| def metarig_menu(self, context): | def metarig_menu(self, context): | ||||
| self.layout.menu(bl_idname, icon='OUTLINER_OB_ARMATURE', text=text) | self.layout.menu(bl_idname, icon='OUTLINER_OB_ARMATURE', text=text) | ||||
| return metarig_menu | return metarig_menu | ||||
| # Get the metarig modules | # Get the metarig modules | ||||
| metarigs_dict = get_metarig_list("") | def get_internal_metarigs(): | ||||
| armature_submenus = [] | MODULE_DIR = os.path.dirname(os.path.dirname(__file__)) | ||||
| # Create metarig add Operators | metarigs.update(get_metarigs(MODULE_DIR, os.path.join(os.path.basename(os.path.dirname(__file__)), utils.METARIG_DIR, ''))) | ||||
| metarigs = {} | |||||
| metarig_ops = {} | metarig_ops = {} | ||||
| for metarig_class in metarigs_dict: | armature_submenus = [] | ||||
| metarig_ops[metarig_class] = [] | menu_funcs = [] | ||||
| for m in metarigs_dict[metarig_class]: | |||||
| get_internal_metarigs() | |||||
| def create_metarig_ops(dic=metarigs): | |||||
| """Create metarig add Operators""" | |||||
| for metarig_category in dic: | |||||
| if metarig_category == "external": | |||||
| create_metarig_ops(dic[metarig_category]) | |||||
| continue | |||||
| if not metarig_category in metarig_ops: | |||||
| metarig_ops[metarig_category] = [] | |||||
| for m in dic[metarig_category].values(): | |||||
| name = m.__name__.rsplit('.', 1)[1] | name = m.__name__.rsplit('.', 1)[1] | ||||
| # Dynamically construct an Operator | # Dynamically construct an Operator | ||||
| T = type("Add_" + name + "_Metarig", (bpy.types.Operator,), {}) | T = type("Add_" + name + "_Metarig", (bpy.types.Operator,), {}) | ||||
| T.bl_idname = "object.armature_" + name + "_metarig_add" | T.bl_idname = "object.armature_" + name + "_metarig_add" | ||||
| T.bl_label = "Add " + name.replace("_", " ").capitalize() + " (metarig)" | T.bl_label = "Add " + name.replace("_", " ").capitalize() + " (metarig)" | ||||
| T.bl_options = {'REGISTER', 'UNDO'} | T.bl_options = {'REGISTER', 'UNDO'} | ||||
| T.execute = make_metarig_add_execute(m) | T.execute = make_metarig_add_execute(m) | ||||
| metarig_ops[metarig_class].append((T, name)) | metarig_ops[metarig_category].append((T, name)) | ||||
| menu_funcs = [] | |||||
| def create_menu_funcs(): | |||||
| global menu_funcs | |||||
| for mop, name in metarig_ops[utils.METARIG_DIR]: | for mop, name in metarig_ops[utils.METARIG_DIR]: | ||||
| text = capwords(name.replace("_", " ")) + " (Meta-Rig)" | text = capwords(name.replace("_", " ")) + " (Meta-Rig)" | ||||
| menu_funcs += [make_metarig_menu_func(mop.bl_idname, text)] | menu_funcs += [make_metarig_menu_func(mop.bl_idname, text)] | ||||
| metarigs_dict.pop(utils.METARIG_DIR) | def create_armature_submenus(dic=metarigs): | ||||
| global menu_funcs | |||||
| metarig_classes = list(metarigs_dict.keys()) | metarig_categories = list(dic.keys()) | ||||
| metarig_classes.sort() | metarig_categories.sort() | ||||
| for metarig_class in metarig_classes: | for metarig_category in metarig_categories: | ||||
| # Create menu functions | # Create menu functions | ||||
| if metarig_category == "external": | |||||
| create_armature_submenus(dic=metarigs["external"]) | |||||
| continue | |||||
| if metarig_category == utils.METARIG_DIR: | |||||
| continue | |||||
| armature_submenus.append(type('Class_' + metarig_class + '_submenu', (ArmatureSubMenu,), {})) | armature_submenus.append(type('Class_' + metarig_category + '_submenu', (ArmatureSubMenu,), {})) | ||||
| armature_submenus[-1].bl_label = metarig_class + ' (submenu)' | armature_submenus[-1].bl_label = metarig_category + ' (submenu)' | ||||
| armature_submenus[-1].bl_idname = 'ARMATURE_MT_%s_class' % metarig_class | armature_submenus[-1].bl_idname = 'ARMATURE_MT_%s_class' % metarig_category | ||||
| armature_submenus[-1].operators = [] | armature_submenus[-1].operators = [] | ||||
| menu_funcs += [make_submenu_func(armature_submenus[-1].bl_idname, metarig_class)] | menu_funcs += [make_submenu_func(armature_submenus[-1].bl_idname, metarig_category)] | ||||
| for mop, name in metarig_ops[metarig_class]: | for mop, name in metarig_ops[metarig_category]: | ||||
| arm_sub = next((e for e in armature_submenus if e.bl_label == metarig_class + ' (submenu)'), '') | arm_sub = next((e for e in armature_submenus if e.bl_label == metarig_category + ' (submenu)'), '') | ||||
| arm_sub.operators.append((mop.bl_idname, name,)) | arm_sub.operators.append((mop.bl_idname, name,)) | ||||
| create_metarig_ops() | |||||
| create_menu_funcs() | |||||
| create_armature_submenus() | |||||
| ### Registering ### | ### Registering ### | ||||
| def register(): | def register(): | ||||
| from bpy.utils import register_class | from bpy.utils import register_class | ||||
| for cl in metarig_ops: | for cl in metarig_ops: | ||||
| for mop, name in metarig_ops[cl]: | for mop, name in metarig_ops[cl]: | ||||
| register_class(mop) | register_class(mop) | ||||
| for arm_sub in armature_submenus: | for arm_sub in armature_submenus: | ||||
| register_class(arm_sub) | register_class(arm_sub) | ||||
| for mf in menu_funcs: | for mf in menu_funcs: | ||||
| bpy.types.VIEW3D_MT_armature_add.append(mf) | bpy.types.VIEW3D_MT_armature_add.append(mf) | ||||
| def unregister(): | def unregister(): | ||||
| from bpy.utils import unregister_class | from bpy.utils import unregister_class | ||||
| for cl in metarig_ops: | for cl in metarig_ops: | ||||
| for mop, name in metarig_ops[cl]: | for mop, name in metarig_ops[cl]: | ||||
| unregister_class(mop) | unregister_class(mop) | ||||
| for arm_sub in armature_submenus: | for arm_sub in armature_submenus: | ||||
| unregister_class(arm_sub) | unregister_class(arm_sub) | ||||
| for mf in menu_funcs: | for mf in menu_funcs: | ||||
| bpy.types.VIEW3D_MT_armature_add.remove(mf) | bpy.types.VIEW3D_MT_armature_add.remove(mf) | ||||
| def get_external_metarigs(feature_sets_path): | |||||
| unregister() | |||||
| # Clear and fill metarigs public variables | |||||
| metarigs.clear() | |||||
| get_internal_metarigs() | |||||
| metarigs['external'] = {} | |||||
| for feature_set in os.listdir(feature_sets_path): | |||||
| if feature_set: | |||||
| utils.get_resource(os.path.join(feature_set, '__init__'), base_path=feature_sets_path) | |||||
| metarigs['external'].update(get_metarigs(feature_sets_path, os.path.join(feature_set, utils.METARIG_DIR))) | |||||
| metarig_ops.clear() | |||||
| armature_submenus.clear() | |||||
| menu_funcs.clear() | |||||
| create_metarig_ops() | |||||
| create_menu_funcs() | |||||
| create_armature_submenus() | |||||
| register() | |||||