diff --git a/rigify/utils/bones.py b/rigify/utils/bones.py index 9002d083b6f135319e1c3c189da0448b2c6e383e..a8e55f9af883583d75039c3ec489606188cfc974 100644 --- a/rigify/utils/bones.py +++ b/rigify/utils/bones.py @@ -24,7 +24,7 @@ from mathutils import Vector, Matrix, Color from rna_prop_ui import rna_idprop_ui_prop_get from .errors import MetarigError -from .naming import strip_org, make_mechanism_name, insert_before_lr +from .naming import make_derived_name #======================= # Bone collection @@ -256,8 +256,8 @@ def make_nonscaling_child(obj, bone_name, location, child_name_postfix=""): if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE': # Create desired names for bones - name1 = make_mechanism_name(strip_org(insert_before_lr(bone_name, child_name_postfix + "_ns_ch"))) - name2 = make_mechanism_name(strip_org(insert_before_lr(bone_name, child_name_postfix + "_ns_intr"))) + name1 = make_derived_name(bone_name, 'mch', child_name_postfix + "_ns_ch") + name2 = make_derived_name(bone_name, 'mch', child_name_postfix + "_ns_intr") # Create bones child = copy_bone(obj, bone_name, name1) diff --git a/rigify/utils/mechanism.py b/rigify/utils/mechanism.py index 62d86154ea9a9f23b10d7259753a5b642d0a14e7..ffec8a4ce85d5b7c367788c735f8a365d6f84fe3 100644 --- a/rigify/utils/mechanism.py +++ b/rigify/utils/mechanism.py @@ -52,8 +52,10 @@ def make_constraint( """ con = owner.constraints.new(type) - if target is not None and subtarget is not None: + if target is not None and hasattr(con, 'target'): con.target = target + + if subtarget is not None: con.subtarget = subtarget if space is not None: @@ -130,10 +132,12 @@ def _init_driver_target(drv_target, var_info, target_id): else: # { 'id': ..., ... } + target_id = var_info.get('id', target_id) + if target_id is not None: drv_target.id = target_id - for tp, tv in tdata.items(): + for tp, tv in var_info.items(): setattr(drv_target, tp, tv) @@ -237,6 +241,29 @@ def make_driver(owner, prop, *, index=-1, type='SUM', expression=None, variables return fcu + +def driver_var_transform(target, bone=None, *, type='LOC_X', space='WORLD'): + """ + Create a Transform Channel driver variable specification. + + Usage: + make_driver(..., variables=[driver_var_transform(...)]) + """ + + assert space in {'WORLD', 'TRANSFORM', 'LOCAL'} + + target_map = { + 'id': target, + 'transform_type': type, + 'transform_space': space + '_SPACE', + } + + if bone is not None: + target_map['bone_target'] = bone + + return { 'type': 'TRANSFORMS', 'targets': [ target_map ] } + + #============================================= # Utility mixin #============================================= diff --git a/rigify/utils/naming.py b/rigify/utils/naming.py index 3af3d85177cd973c7514bc98fdb36e0f5e9cea2b..3983704a4ce4635de2730ffac5b3681b52a43343 100644 --- a/rigify/utils/naming.py +++ b/rigify/utils/naming.py @@ -37,6 +37,10 @@ def strip_trailing_number(s): return s[0:-4] if m else s +def strip_prefix(name): + return re.sub(r'^(?:ORG|MCH|DEF)-', '', name) + + def unique_name(collection, base_name): base_name = strip_trailing_number(base_name) count = 1 @@ -116,11 +120,27 @@ def deformer(name): make_deformer_name = deformer +_prefix_functions = { 'org': org, 'mch': mch, 'def': deformer, 'ctrl': lambda x: x } + + def insert_before_lr(name, text): - if name[-1] in ['l', 'L', 'r', 'R'] and name[-2] in ['.', '-', '_']: - return name[:-2] + text + name[-2:] - else: - return name + text + name_parts = re.match(r'^(.*?)((?:[._-][lLrR](?:\.\d+)?)?)$', name) + name_base, name_suffix = name_parts.groups() + return name_base + text + name_suffix + + +def make_derived_name(name, subtype, suffix=None): + """ Replaces the name prefix, and optionally adds the suffix (before .LR if found). + """ + assert(subtype in _prefix_functions) + + name = strip_prefix(name) + + if suffix: + name = insert_before_lr(name, suffix) + + return _prefix_functions[subtype](name) + def random_id(length=8): """ Generates a random alphanumeric id string.