Changeset View
Changeset View
Standalone View
Standalone View
rigify/__init__.py
| Show All 14 Lines | |||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
| # | # | ||||
| #======================= END GPL LICENSE BLOCK ======================== | #======================= END GPL LICENSE BLOCK ======================== | ||||
| # <pep8 compliant> | # <pep8 compliant> | ||||
| bl_info = { | bl_info = { | ||||
| "name": "Rigify", | "name": "Rigify", | ||||
| "version": (0, 5), | "version": (0, 5, 1), | ||||
| "author": "Nathan Vegdahl, Lucio Rossi, Ivan Cappiello", | "author": "Nathan Vegdahl, Lucio Rossi, Ivan Cappiello", | ||||
| "blender": (2, 80, 0), | "blender": (2, 80, 0), | ||||
| "description": "Automatic rigging from building-block components", | "description": "Automatic rigging from building-block components", | ||||
| "location": "Armature properties, Bone properties, View3d tools panel, Armature Add menu", | "location": "Armature properties, Bone properties, View3d tools panel, Armature Add menu", | ||||
| "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/" | "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/" | ||||
| "Scripts/Rigging/Rigify", | "Scripts/Rigging/Rigify", | ||||
| "category": "Rigging"} | "category": "Rigging"} | ||||
| if "bpy" in locals(): | if "bpy" in locals(): | ||||
| import importlib | import importlib | ||||
| importlib.reload(generate) | importlib.reload(generate) | ||||
| importlib.reload(ui) | importlib.reload(ui) | ||||
| importlib.reload(utils) | importlib.reload(utils) | ||||
| importlib.reload(metarig_menu) | importlib.reload(metarig_menu) | ||||
| importlib.reload(rig_lists) | importlib.reload(rig_lists) | ||||
| importlib.reload(feature_sets) | |||||
| else: | else: | ||||
| from . import utils, rig_lists, generate, ui, metarig_menu | from . import (utils, rig_lists, generate, ui, metarig_menu, feature_sets) | ||||
| import bpy | import bpy | ||||
| import sys | import sys | ||||
| import os | import os | ||||
| from bpy.types import AddonPreferences | from bpy.types import AddonPreferences | ||||
| from bpy.props import ( | from bpy.props import ( | ||||
| BoolProperty, | BoolProperty, | ||||
| IntProperty, | IntProperty, | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | def update_legacy(self, context): | ||||
| globals()['utils'] = utils | globals()['utils'] = utils | ||||
| globals()['rig_lists'] = rig_lists | globals()['rig_lists'] = rig_lists | ||||
| globals()['generate'] = generate | globals()['generate'] = generate | ||||
| globals()['ui'] = ui | globals()['ui'] = ui | ||||
| globals()['metarig_menu'] = metarig_menu | globals()['metarig_menu'] = metarig_menu | ||||
| register() | register() | ||||
| def update_external_rigs(self): | |||||
| """Get external feature sets""" | |||||
| if self.legacy_mode: | |||||
| return | |||||
| feature_sets_path = os.path.join(bpy.utils.script_path_user(), 'rigify') | |||||
| if os.path.exists(feature_sets_path): | |||||
| if feature_sets_path not in sys.path: | |||||
| sys.path.append(feature_sets_path) | |||||
| # Reload rigs | |||||
| print('Reloading external rigs...') | |||||
| rig_lists.get_external_rigs(feature_sets_path) | |||||
| # Reload metarigs | |||||
| print('Reloading external metarigs...') | |||||
| metarig_menu.get_external_metarigs(feature_sets_path) | |||||
| legacy_mode: BoolProperty( | legacy_mode: BoolProperty( | ||||
| name='Rigify Legacy Mode', | name='Rigify Legacy Mode', | ||||
| description='Select if you want to use Rigify in legacy mode', | description='Select if you want to use Rigify in legacy mode', | ||||
| default=False, | default=False, | ||||
| update=update_legacy | update=update_legacy | ||||
| ) | ) | ||||
| show_expanded: BoolProperty() | show_expanded: BoolProperty() | ||||
| show_rigs_folder_expanded: BoolProperty() | |||||
| def draw(self, context): | def draw(self, context): | ||||
| layout = self.layout | layout = self.layout | ||||
| column = layout.column() | column = layout.column() | ||||
| box = column.box() | box = column.box() | ||||
| # first stage | # first stage | ||||
| expand = getattr(self, 'show_expanded') | expand = getattr(self, 'show_expanded') | ||||
| icon = 'TRIA_DOWN' if expand else 'TRIA_RIGHT' | icon = 'TRIA_DOWN' if expand else 'TRIA_RIGHT' | ||||
| Show All 10 Lines | def draw(self, context): | ||||
| sub.alignment = 'RIGHT' | sub.alignment = 'RIGHT' | ||||
| sub.prop(self, 'legacy_mode') | sub.prop(self, 'legacy_mode') | ||||
| if expand: | if expand: | ||||
| split = col.row().split(factor=0.15) | split = col.row().split(factor=0.15) | ||||
| split.label(text='Description:') | split.label(text='Description:') | ||||
| split.label(text='When enabled the add-on will run in legacy mode using the old 2.76b feature set.') | split.label(text='When enabled the add-on will run in legacy mode using the old 2.76b feature set.') | ||||
| box = column.box() | |||||
| rigs_expand = getattr(self, 'show_rigs_folder_expanded') | |||||
| icon = 'TRIA_DOWN' if rigs_expand else 'TRIA_RIGHT' | |||||
| col = box.column() | |||||
| row = col.row() | |||||
| sub = row.row() | |||||
| sub.context_pointer_set('addon_prefs', self) | |||||
| sub.alignment = 'LEFT' | |||||
| op = sub.operator('wm.context_toggle', text='', icon=icon, | |||||
| emboss=False) | |||||
| op.data_path = 'addon_prefs.show_rigs_folder_expanded' | |||||
| sub.label(text='{}: {}'.format('Rigify', 'External feature sets')) | |||||
| if rigs_expand: | |||||
| if os.path.exists(os.path.join(bpy.utils.script_path_user(), 'rigify')): | |||||
| feature_sets_path = os.path.join(bpy.utils.script_path_user(), 'rigify') | |||||
| for fs in os.listdir(feature_sets_path): | |||||
| row = col.row() | |||||
| row.label(text=fs) | |||||
| op = row.operator("wm.rigify_remove_feature_set", text="Remove", icon='CANCEL') | |||||
| op.featureset = fs | |||||
| row = col.row(align=True) | |||||
| row.operator("wm.rigify_add_feature_set", text="Install Feature Set from File...", icon='FILEBROWSER') | |||||
| split = col.row().split(factor=0.15) | |||||
| split.label(text='Description:') | |||||
| split.label(text='External feature sets (rigs, metarigs, ui layouts)') | |||||
| row = layout.row() | row = layout.row() | ||||
| row.label(text="End of Rigify Preferences") | row.label(text="End of Rigify Preferences") | ||||
| class RigifyName(bpy.types.PropertyGroup): | class RigifyName(bpy.types.PropertyGroup): | ||||
| name: StringProperty() | name: StringProperty() | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| class RigifyParameters(bpy.types.PropertyGroup): | class RigifyParameters(bpy.types.PropertyGroup): | ||||
| name: StringProperty() | name: StringProperty() | ||||
| # Remember the initial property set | # Remember the initial property set | ||||
| RIGIFY_PARAMETERS_BASE_DIR = set(dir(RigifyParameters)) | RIGIFY_PARAMETERS_BASE_DIR = set(dir(RigifyParameters)) | ||||
| RIGIFY_PARAMETER_TABLE = {'name': ('DEFAULT', StringProperty())} | |||||
| def clear_rigify_parameters(): | def clear_rigify_parameters(): | ||||
| for name in list(dir(RigifyParameters)): | for name in list(dir(RigifyParameters)): | ||||
| if name not in RIGIFY_PARAMETERS_BASE_DIR: | if name not in RIGIFY_PARAMETERS_BASE_DIR: | ||||
| delattr(RigifyParameters, name) | delattr(RigifyParameters, name) | ||||
| if name in RIGIFY_PARAMETER_TABLE: | |||||
| del RIGIFY_PARAMETER_TABLE[name] | |||||
| def format_property_spec(spec): | |||||
| """Turns the return value of bpy.props.SomeProperty(...) into a readable string.""" | |||||
| callback, params = spec | |||||
| param_str = ["%s=%r" % (k, v) for k, v in params.items()] | |||||
| return "%s(%s)" % (callback.__name__, ', '.join(param_str)) | |||||
| class RigifyParameterValidator(object): | |||||
| """ | |||||
| A wrapper around RigifyParameters that verifies properties | |||||
| defined from rigs for incompatible redefinitions using a table. | |||||
| Relies on the implementation details of bpy.props return values: | |||||
| specifically, they just return a tuple containing the real define | |||||
| function, and a dictionary with parameters. This allows comparing | |||||
| parameters before the property is actually defined. | |||||
| """ | |||||
| __params = None | |||||
| __rig_name = '' | |||||
| __prop_table = {} | |||||
| def __init__(self, params, rig_name, prop_table): | |||||
| self.__params = params | |||||
| self.__rig_name = rig_name | |||||
| self.__prop_table = prop_table | |||||
| def __getattr__(self, name): | |||||
| return getattr(self.__params, name) | |||||
| def __setattr__(self, name, val): | |||||
| # allow __init__ to work correctly | |||||
| if hasattr(RigifyParameterValidator, name): | |||||
| return object.__setattr__(self, name, val) | |||||
| if not (isinstance(val, tuple) and callable(val[0]) and isinstance(val[1], dict)): | |||||
| print("!!! RIGIFY RIG %s: INVALID DEFINITION FOR RIG PARAMETER %s: %r\n" % (self.__rig_name, name, val)) | |||||
| return | |||||
| if name in self.__prop_table: | |||||
| cur_rig, cur_info = self.__prop_table[name] | |||||
| if val != cur_info: | |||||
| print("!!! RIGIFY RIG %s: REDEFINING PARAMETER %s AS:\n\n %s\n" % (self.__rig_name, name, format_property_spec(val))) | |||||
| print("!!! PREVIOUS DEFINITION BY %s:\n\n %s\n" % (cur_rig, format_property_spec(cur_info))) | |||||
| # actually defining the property modifies the dictionary with new parameters, so copy it now | |||||
| new_def = (val[0], val[1].copy()) | |||||
| setattr(self.__params, name, val) | |||||
| self.__prop_table[name] = (self.__rig_name, new_def) | |||||
| class RigifyArmatureLayer(bpy.types.PropertyGroup): | class RigifyArmatureLayer(bpy.types.PropertyGroup): | ||||
| def get_group(self): | def get_group(self): | ||||
| if 'group_prop' in self.keys(): | if 'group_prop' in self.keys(): | ||||
| return self['group_prop'] | return self['group_prop'] | ||||
| else: | else: | ||||
| Show All 25 Lines | |||||
| ) | ) | ||||
| def register(): | def register(): | ||||
| from bpy.utils import register_class | from bpy.utils import register_class | ||||
| # Sub-modules. | # Sub-modules. | ||||
| ui.register() | ui.register() | ||||
| feature_sets.register() | |||||
| metarig_menu.register() | metarig_menu.register() | ||||
| # Classes. | # Classes. | ||||
| for cls in classes: | for cls in classes: | ||||
| register_class(cls) | register_class(cls) | ||||
| # Properties. | # Properties. | ||||
| bpy.types.Armature.rigify_layers = CollectionProperty(type=RigifyArmatureLayer) | bpy.types.Armature.rigify_layers = CollectionProperty(type=RigifyArmatureLayer) | ||||
| bpy.types.Armature.active_feature_set = EnumProperty( | |||||
| items=feature_sets.feature_set_items, | |||||
| name="Feature Set", | |||||
| description="Feature set to select from for this bone" | |||||
| ) | |||||
| bpy.types.PoseBone.rigify_type = StringProperty(name="Rigify Type", description="Rig type for this bone") | bpy.types.PoseBone.rigify_type = StringProperty(name="Rigify Type", description="Rig type for this bone") | ||||
| bpy.types.PoseBone.rigify_parameters = PointerProperty(type=RigifyParameters) | bpy.types.PoseBone.rigify_parameters = PointerProperty(type=RigifyParameters) | ||||
| bpy.types.Armature.rigify_colors = CollectionProperty(type=RigifyColorSet) | bpy.types.Armature.rigify_colors = CollectionProperty(type=RigifyColorSet) | ||||
| bpy.types.Armature.rigify_selection_colors = PointerProperty(type=RigifySelectionColors) | bpy.types.Armature.rigify_selection_colors = PointerProperty(type=RigifySelectionColors) | ||||
| bpy.types.Armature.rigify_colors_index = IntProperty(default=-1) | bpy.types.Armature.rigify_colors_index = IntProperty(default=-1) | ||||
| Show All 17 Lines | bpy.types.Armature.rigify_theme_to_add = EnumProperty(items=( | ||||
| ('THEME16', 'THEME16', ''), | ('THEME16', 'THEME16', ''), | ||||
| ('THEME17', 'THEME17', ''), | ('THEME17', 'THEME17', ''), | ||||
| ('THEME18', 'THEME18', ''), | ('THEME18', 'THEME18', ''), | ||||
| ('THEME19', 'THEME19', ''), | ('THEME19', 'THEME19', ''), | ||||
| ('THEME20', 'THEME20', '') | ('THEME20', 'THEME20', '') | ||||
| ), name='Theme') | ), name='Theme') | ||||
| IDStore = bpy.types.WindowManager | IDStore = bpy.types.WindowManager | ||||
| IDStore.rigify_collection = EnumProperty(items=rig_lists.col_enum_list, default="All", | IDStore.rigify_collection = EnumProperty(items=(("All", "All", "All"),), default="All", | ||||
| name="Rigify Active Collection", | name="Rigify Active Collection", | ||||
| description="The selected rig collection") | description="The selected rig collection") | ||||
| IDStore.rigify_types = CollectionProperty(type=RigifyName) | IDStore.rigify_types = CollectionProperty(type=RigifyName) | ||||
| IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type") | IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type") | ||||
| IDStore.rigify_advanced_generation = BoolProperty(name="Advanced Options", | IDStore.rigify_advanced_generation = BoolProperty(name="Advanced Options", | ||||
| description="Enables/disables advanced options for Rigify rig generation", | description="Enables/disables advanced options for Rigify rig generation", | ||||
| Show All 36 Lines | def register(): | ||||
| IDStore.rigify_transfer_end_frame = IntProperty( | IDStore.rigify_transfer_end_frame = IntProperty( | ||||
| name="End Frame", | name="End Frame", | ||||
| description="Last Frame to Transfer", default=0, min= 0) | description="Last Frame to Transfer", default=0, min= 0) | ||||
| # Update legacy on restart or reload. | # Update legacy on restart or reload. | ||||
| if (ui and 'legacy' in str(ui)) or bpy.context.preferences.addons['rigify'].preferences.legacy_mode: | if (ui and 'legacy' in str(ui)) or bpy.context.preferences.addons['rigify'].preferences.legacy_mode: | ||||
| bpy.context.preferences.addons['rigify'].preferences.legacy_mode = True | bpy.context.preferences.addons['rigify'].preferences.legacy_mode = True | ||||
| bpy.context.preferences.addons['rigify'].preferences.update_external_rigs() | |||||
| # Add rig parameters | # Add rig parameters | ||||
| if bpy.context.preferences.addons['rigify'].preferences.legacy_mode: | |||||
| for rig in rig_lists.rig_list: | for rig in rig_lists.rig_list: | ||||
| r = utils.get_rig_type(rig) | r = utils.get_rig_type(rig) | ||||
| try: | try: | ||||
| r.add_parameters(RigifyParameters) | r.add_parameters(RigifyParameterValidator(RigifyParameters, rig, RIGIFY_PARAMETER_TABLE)) | ||||
| except AttributeError: | |||||
| pass | |||||
| else: | |||||
| for rig in rig_lists.rigs: | |||||
| r = rig_lists.rigs[rig]['module'] | |||||
| try: | |||||
| r.add_parameters(RigifyParameterValidator(RigifyParameters, rig, RIGIFY_PARAMETER_TABLE)) | |||||
| except AttributeError: | except AttributeError: | ||||
| pass | pass | ||||
| def unregister(): | def unregister(): | ||||
| from bpy.utils import unregister_class | from bpy.utils import unregister_class | ||||
| # Properties. | # Properties on PoseBones and Armature. | ||||
| del bpy.types.PoseBone.rigify_type | del bpy.types.PoseBone.rigify_type | ||||
| del bpy.types.PoseBone.rigify_parameters | del bpy.types.PoseBone.rigify_parameters | ||||
| ArmStore = bpy.types.Armature | |||||
| del ArmStore.rigify_layers | |||||
| del ArmStore.active_feature_set | |||||
| del ArmStore.rigify_colors | |||||
| del ArmStore.rigify_selection_colors | |||||
| del ArmStore.rigify_colors_index | |||||
| del ArmStore.rigify_colors_lock | |||||
| del ArmStore.rigify_theme_to_add | |||||
| IDStore = bpy.types.WindowManager | IDStore = bpy.types.WindowManager | ||||
| del IDStore.rigify_collection | del IDStore.rigify_collection | ||||
| del IDStore.rigify_types | del IDStore.rigify_types | ||||
| del IDStore.rigify_active_type | del IDStore.rigify_active_type | ||||
| del IDStore.rigify_advanced_generation | del IDStore.rigify_advanced_generation | ||||
| del IDStore.rigify_generate_mode | del IDStore.rigify_generate_mode | ||||
| del IDStore.rigify_force_widget_update | del IDStore.rigify_force_widget_update | ||||
| del IDStore.rigify_target_rig | del IDStore.rigify_target_rig | ||||
| Show All 9 Lines | def unregister(): | ||||
| for cls in classes: | for cls in classes: | ||||
| unregister_class(cls) | unregister_class(cls) | ||||
| clear_rigify_parameters() | clear_rigify_parameters() | ||||
| # Sub-modules. | # Sub-modules. | ||||
| metarig_menu.unregister() | metarig_menu.unregister() | ||||
| ui.unregister() | ui.unregister() | ||||
| feature_sets.unregister() | |||||