Changeset View
Changeset View
Standalone View
Standalone View
rigify/generate.py
| Show All 18 Lines | |||||
| # <pep8 compliant> | # <pep8 compliant> | ||||
| import bpy | import bpy | ||||
| import re | import re | ||||
| import time | import time | ||||
| import traceback | import traceback | ||||
| import sys | import sys | ||||
| from rna_prop_ui import rna_idprop_ui_prop_get | from rna_prop_ui import rna_idprop_ui_prop_get | ||||
| from collections import OrderedDict | |||||
| from .utils import MetarigError, new_bone, get_rig_type | from .utils import MetarigError, new_bone | ||||
| from .utils import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NAME, make_original_name | from .utils import MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NAME, make_original_name | ||||
| from .utils import RIG_DIR | |||||
| from .utils import create_root_widget | from .utils import create_root_widget | ||||
| from .utils import ensure_widget_collection | from .utils.collections import ensure_widget_collection | ||||
| from .utils import random_id | from .utils import random_id | ||||
| from .utils import copy_attributes | from .utils import copy_attributes | ||||
| from .utils import gamma_correct | from .utils import gamma_correct | ||||
| from .rig_ui_template import UI_SLIDERS, layers_ui, UI_REGISTER | from . import rig_lists | ||||
| from . import rig_ui_template | |||||
| RIG_MODULE = "rigs" | RIG_MODULE = "rigs" | ||||
| ORG_LAYER = [n == 31 for n in range(0, 32)] # Armature layer that original bones should be moved to. | ORG_LAYER = [n == 31 for n in range(0, 32)] # Armature layer that original bones should be moved to. | ||||
| MCH_LAYER = [n == 30 for n in range(0, 32)] # Armature layer that mechanism bones should be moved to. | MCH_LAYER = [n == 30 for n in range(0, 32)] # Armature layer that mechanism bones should be moved to. | ||||
| DEF_LAYER = [n == 29 for n in range(0, 32)] # Armature layer that deformation bones should be moved to. | DEF_LAYER = [n == 29 for n in range(0, 32)] # Armature layer that deformation bones should be moved to. | ||||
| ROOT_LAYER = [n == 28 for n in range(0, 32)] # Armature layer that root bone should be moved to. | ROOT_LAYER = [n == 28 for n in range(0, 32)] # Armature layer that root bone should be moved to. | ||||
| ▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | def generate_rig(context, metarig): | ||||
| # Select generated rig object | # Select generated rig object | ||||
| metarig.select_set(False) | metarig.select_set(False) | ||||
| obj.select_set(True) | obj.select_set(True) | ||||
| view_layer.objects.active = obj | view_layer.objects.active = obj | ||||
| # Remove wgts if force update is set | # Remove wgts if force update is set | ||||
| wgts_group_name = "WGTS_" + (rig_old_name or obj.name) | wgts_group_name = "WGTS_" + (rig_old_name or obj.name) | ||||
| if wgts_group_name in scene.objects and id_store.rigify_force_widget_update: | if wgts_group_name in scene.objects and id_store.rigify_force_widget_update: | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | |||||
| bpy.ops.object.select_all(action='DESELECT') | bpy.ops.object.select_all(action='DESELECT') | ||||
| for wgt in bpy.data.objects[wgts_group_name].children: | for wgt in bpy.data.objects[wgts_group_name].children: | ||||
| wgt.select_set(True) | wgt.select_set(True) | ||||
| bpy.ops.object.delete(use_global=False) | bpy.ops.object.delete(use_global=False) | ||||
| if rig_old_name: | if rig_old_name: | ||||
| bpy.data.objects[wgts_group_name].name = "WGTS_" + obj.name | bpy.data.objects[wgts_group_name].name = "WGTS_" + obj.name | ||||
| wgts_group_name = "WGTS_" + obj.name | wgts_group_name = "WGTS_" + obj.name | ||||
| ▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | def generate_rig(context, metarig): | ||||
| obj.data.edit_bones[root_bone].roll = 0 | obj.data.edit_bones[root_bone].roll = 0 | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| obj.data.bones[root_bone].layers = ROOT_LAYER | obj.data.bones[root_bone].layers = ROOT_LAYER | ||||
| # Put the rig_name in the armature custom properties | # Put the rig_name in the armature custom properties | ||||
| rna_idprop_ui_prop_get(obj.data, "rig_id", create=True) | rna_idprop_ui_prop_get(obj.data, "rig_id", create=True) | ||||
| obj.data["rig_id"] = rig_id | obj.data["rig_id"] = rig_id | ||||
| t.tick("Create root bone: ") | |||||
| # Create/find widge collection | # Create/find widge collection | ||||
| widget_collection = ensure_widget_collection(context) | widget_collection = ensure_widget_collection(context) | ||||
| # Create Group widget | # Create Group widget | ||||
| # wgts_group_name = "WGTS" | # wgts_group_name = "WGTS" | ||||
| if wgts_group_name not in scene.objects: | if wgts_group_name not in scene.objects: | ||||
| if wgts_group_name in bpy.data.objects: | if wgts_group_name in bpy.data.objects: | ||||
| bpy.data.objects[wgts_group_name].user_clear() | bpy.data.objects[wgts_group_name].user_clear() | ||||
| Show All 15 Lines | try: | ||||
| rigs = [] | rigs = [] | ||||
| for bone in bones_sorted: | for bone in bones_sorted: | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| rigs += get_bone_rigs(obj, bone) | rigs += get_bone_rigs(obj, bone) | ||||
| t.tick("Initialize rigs: ") | t.tick("Initialize rigs: ") | ||||
| # Generate all the rigs. | # Generate all the rigs. | ||||
| ui_scripts = [] | ui_scripts = [] | ||||
| ui_imports = rig_ui_template.UI_IMPORTS.copy() | |||||
| ui_utilities = rig_ui_template.UI_UTILITIES.copy() | |||||
| ui_register = rig_ui_template.UI_REGISTER.copy() | |||||
| noparent_bones = [] | |||||
| for rig in rigs: | for rig in rigs: | ||||
| # Go into editmode in the rig armature | # Go into editmode in the rig armature | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| context.view_layer.objects.active = obj | context.view_layer.objects.active = obj | ||||
| obj.select_set(True) | obj.select_set(True) | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| scripts = rig.generate() | scripts = rig.generate() | ||||
| if scripts is not None: | if isinstance(scripts, dict): | ||||
| if 'script' in scripts: | |||||
| ui_scripts += scripts['script'] | |||||
| if 'imports' in scripts: | |||||
| ui_imports += scripts['imports'] | |||||
| if 'utilities' in scripts: | |||||
| ui_utilities += scripts['utilities'] | |||||
| if 'register' in scripts: | |||||
| ui_register += scripts['register'] | |||||
| if 'noparent_bones' in scripts: | |||||
| noparent_bones += scripts['noparent_bones'] | |||||
| elif scripts is not None: | |||||
| ui_scripts += [scripts[0]] | ui_scripts += [scripts[0]] | ||||
| t.tick("Generate rigs: ") | t.tick("Generate rigs: ") | ||||
| except Exception as e: | except Exception as e: | ||||
| # Cleanup if something goes wrong | # Cleanup if something goes wrong | ||||
| print("Rigify: failed to generate rig.") | print("Rigify: failed to generate rig.") | ||||
| metarig.data.pose_position = rest_backup | metarig.data.pose_position = rest_backup | ||||
| obj.data.pose_position = 'POSE' | obj.data.pose_position = 'POSE' | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| # Continue the exception | # Continue the exception | ||||
| raise e | raise e | ||||
| #---------------------------------- | #---------------------------------- | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| # Get a list of all the bones in the armature | # Get a list of all the bones in the armature | ||||
| bones = [bone.name for bone in obj.data.bones] | bones = [bone.name for bone in obj.data.bones] | ||||
| # Parent any free-floating bones to the root excluding bones with child of constraint. | # Parent any free-floating bones to the root excluding noparent_bones | ||||
| pbones = obj.pose.bones | noparent_bones = dict.fromkeys(noparent_bones) | ||||
| ik_follow_drivers = [] | |||||
| if obj.animation_data: | |||||
| for drv in obj.animation_data.drivers: | |||||
| for var in drv.driver.variables: | |||||
| if 'IK_follow' == var.name: | |||||
| ik_follow_drivers.append(drv.data_path) | |||||
| noparent_bones = [] | |||||
| for bone in bones: | |||||
| # if 'IK_follow' in pbones[bone].keys(): | |||||
| # noparent_bones += [bone] | |||||
| for d in ik_follow_drivers: | |||||
| if bone in d: | |||||
| noparent_bones += [bone] | |||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| for bone in bones: | for bone in bones: | ||||
| if bone in noparent_bones: | if bone in noparent_bones: | ||||
| continue | continue | ||||
| elif obj.data.edit_bones[bone].parent is None: | elif obj.data.edit_bones[bone].parent is None: | ||||
| obj.data.edit_bones[bone].use_connect = False | obj.data.edit_bones[bone].use_connect = False | ||||
| obj.data.edit_bones[bone].parent = obj.data.edit_bones[root_bone] | obj.data.edit_bones[bone].parent = obj.data.edit_bones[root_bone] | ||||
| ▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | def generate_rig(context, metarig): | ||||
| rig_ui_old_name = "" | rig_ui_old_name = "" | ||||
| if id_store.rigify_rig_basename: | if id_store.rigify_rig_basename: | ||||
| rig_ui_old_name = script.name | rig_ui_old_name = script.name | ||||
| script.name = id_store.rigify_rig_basename + "_rig_ui.py" | script.name = id_store.rigify_rig_basename + "_rig_ui.py" | ||||
| id_store.rigify_rig_ui = script.name | id_store.rigify_rig_ui = script.name | ||||
| script.write(UI_SLIDERS % rig_id) | for s in OrderedDict.fromkeys(ui_imports): | ||||
| script.write(s + "\n") | |||||
| script.write(rig_ui_template.UI_BASE_UTILITIES % rig_id) | |||||
| for s in OrderedDict.fromkeys(ui_utilities): | |||||
| script.write(s + "\n") | |||||
| script.write(rig_ui_template.UI_SLIDERS) | |||||
| for s in ui_scripts: | for s in ui_scripts: | ||||
| script.write("\n " + s.replace("\n", "\n ") + "\n") | script.write("\n " + s.replace("\n", "\n ") + "\n") | ||||
| script.write(layers_ui(vis_layers, layer_layout)) | script.write(rig_ui_template.layers_ui(vis_layers, layer_layout)) | ||||
| script.write(UI_REGISTER) | script.write("\ndef register():\n") | ||||
| ui_register = OrderedDict.fromkeys(ui_register) | |||||
| for s in ui_register: | |||||
| script.write(" bpy.utils.register_class("+s+");\n") | |||||
| script.write("\ndef unregister():\n") | |||||
| for s in ui_register: | |||||
| script.write(" bpy.utils.unregister_class("+s+");\n") | |||||
| script.write("\nregister()\n") | |||||
| script.use_module = True | script.use_module = True | ||||
| # Run UI script | # Run UI script | ||||
| exec(script.as_string(), {}) | exec(script.as_string(), {}) | ||||
| # Create Selection Sets | # Create Selection Sets | ||||
| create_selection_sets(obj, metarig) | create_selection_sets(obj, metarig) | ||||
| # Create Bone Groups | # Create Bone Groups | ||||
| create_bone_groups(obj, metarig) | create_bone_groups(obj, metarig) | ||||
| # Add rig_ui to logic | # Add rig_ui to logic | ||||
| create_persistent_rig_ui(obj, script) | create_persistent_rig_ui(obj, script) | ||||
| # Do final gluing | |||||
| for rig in rigs: | |||||
| if hasattr(rig, "glue"): | |||||
| # update glue_bone rigs | |||||
| bpy.ops.object.mode_set(mode='EDIT') | |||||
| rig = rig.__class__(rig.obj, rig.base_bone, rig.params) | |||||
| rig.glue() | |||||
| t.tick("Glue pass") | |||||
| t.tick("The rest: ") | t.tick("The rest: ") | ||||
| #---------------------------------- | #---------------------------------- | ||||
| # Deconfigure | # Deconfigure | ||||
| bpy.ops.object.mode_set(mode='OBJECT') | bpy.ops.object.mode_set(mode='OBJECT') | ||||
| metarig.data.pose_position = rest_backup | metarig.data.pose_position = rest_backup | ||||
| obj.data.pose_position = 'POSE' | obj.data.pose_position = 'POSE' | ||||
| # Restore parent to bones | # Restore parent to bones | ||||
| ▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | def get_bone_rigs(obj, bone_name, halt_on_missing=False): | ||||
| if rig_type == "": | if rig_type == "": | ||||
| pass | pass | ||||
| else: | else: | ||||
| # Gather parameters | # Gather parameters | ||||
| params = obj.pose.bones[bone_name].rigify_parameters | params = obj.pose.bones[bone_name].rigify_parameters | ||||
| # Get the rig | # Get the rig | ||||
| try: | try: | ||||
| rig = get_rig_type(rig_type).Rig(obj, bone_name, params) | rig = rig_lists.rigs[rig_type]["module"] | ||||
| except ImportError: | rig = rig.Rig(obj, bone_name, params) | ||||
| except (KeyError, ImportError): | |||||
| message = "Rig Type Missing: python module for type '%s' not found (bone: %s)" % (rig_type, bone_name) | message = "Rig Type Missing: python module for type '%s' not found (bone: %s)" % (rig_type, bone_name) | ||||
| if halt_on_missing: | if halt_on_missing: | ||||
| raise MetarigError(message) | raise MetarigError(message) | ||||
| else: | else: | ||||
| print(message) | print(message) | ||||
| print('print_exc():') | print('print_exc():') | ||||
| traceback.print_exc(file=sys.stdout) | traceback.print_exc(file=sys.stdout) | ||||
| else: | else: | ||||
| Show All 27 Lines | |||||