diff --git a/rigify/generate.py b/rigify/generate.py index 73552442044516ab3ae8d75dadc40c278f53c57e..a2ac6f7a77c97e93b54f927daef965e63ee0f3ba 100644 --- a/rigify/generate.py +++ b/rigify/generate.py @@ -17,6 +17,7 @@ #======================= END GPL LICENSE BLOCK ======================== import bpy +import re import time import traceback import sys @@ -26,6 +27,7 @@ from rigify.utils import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NA from rigify.utils import RIG_DIR from rigify.utils import create_root_widget from rigify.utils import random_id +from rigify.utils import copy_attributes from rigify.rig_ui_template import UI_SLIDERS, layers_ui, UI_REGISTER from rigify import rigs @@ -158,25 +160,53 @@ def generate_rig(context, metarig): # Constraints for con1 in bone.constraints: con2 = bone_gen.constraints.new(type=con1.type) - - # Copy attributes - keys = dir(con1) - for key in keys: - if not key.startswith("_") \ - and not key.startswith("error_") \ - and key != "is_valid" \ - and key != "rna_type" \ - and key != "type" \ - and key != "bl_rna": - try: - setattr(con2, key, getattr(con1, key)) - except AttributeError: - print("Could not write to constraint attribute '%s'" % key) + copy_attributes(con1, con2) # Set metarig target to rig target - if "target" in keys: - if getattr(con2, "target") == metarig: - setattr(con2, "target", obj) + if "target" in dir(con2): + if con2.target == metarig: + con2.target = obj + + # Copy drivers + for d1 in metarig.animation_data.drivers: + d2 = obj.driver_add(d1.data_path) + copy_attributes(d1, d2) + copy_attributes(d1.driver, d2.driver) + + # Remove default modifiers, variables, etc. + for m in d2.modifiers: + d2.modifiers.remove(m) + for v in d2.driver.variables: + d2.driver.variables.remove(v) + + # Copy modifiers + for m1 in d1.modifiers: + m2 = d2.modifiers.new(type=m1.type) + copy_attributes(m1, m2) + + # Copy variables + for v1 in d1.driver.variables: + v2 = d2.driver.variables.new() + copy_attributes(v1, v2) + for i in range(len(v1.targets)): + copy_attributes(v1.targets[i], v2.targets[i]) + # Switch metarig targets to rig targets + if v2.targets[i].id == metarig: + v2.targets[i].id = obj + + # Mark targets that may need to be altered after rig generation + tar = v2.targets[i] + # If a custom property + if v2.type == 'SINGLE_PROP' \ + and re.match('^pose.bones\["[^"\]]*"\]\["[^"\]]*"\]$', tar.data_path): + tar.data_path = "RIGIFY-" + tar.data_path + + # Copy key frames + for i in range(len(d1.keyframe_points)): + d2.keyframe_points.add() + k1 = d1.keyframe_points[i] + k2 = d2.keyframe_points[i] + copy_attributes(k1, k2) t.tick("Duplicate rig: ") #---------------------------------- @@ -267,6 +297,18 @@ def generate_rig(context, metarig): else: obj.data.bones[bone].use_deform = False + # Alter marked driver targets + for d in obj.animation_data.drivers: + for v in d.driver.variables: + for tar in v.targets: + if tar.data_path.startswith("RIGIFY-"): + temp, bone, prop = tuple([x.strip('"]') for x in tar.data_path.split('["')]) + if bone in obj.data.bones \ + and prop in obj.pose.bones[bone].keys(): + tar.data_path = tar.data_path[7:] + else: + tar.data_path = 'pose.bones["%s"]["%s"]' % (make_original_name(bone), prop) + # Move all the original bones to their layer. for bone in original_bones: obj.data.bones[bone].layers = ORG_LAYER diff --git a/rigify/utils.py b/rigify/utils.py index 4add7a15052315c1893629cf15dee219b0ed7f69..44f3e2498a56db5c8d241471cc93bb584ee72dfb 100644 --- a/rigify/utils.py +++ b/rigify/utils.py @@ -375,6 +375,19 @@ def create_root_widget(rig, bone_name): # Misc #============================================= +def copy_attributes(a, b): + keys = dir(a) + for key in keys: + if not key.startswith("_") \ + and not key.startswith("error_") \ + and key != "is_valid" \ + and key != "rna_type" \ + and key != "bl_rna": + try: + setattr(b, key, getattr(a, key)) + except AttributeError: + pass + def get_rig_type(rig_type): """ Fetches a rig module by name, and returns it.