From 7e8663fcbcadbf0095a046d931ead6a817528508 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 2 Jul 2020 17:37:13 +0300 Subject: Rigify: add a few utilities for working with existing custom properties. --- rigify/utils/mechanism.py | 100 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) (limited to 'rigify/utils') diff --git a/rigify/utils/mechanism.py b/rigify/utils/mechanism.py index 33c098dc..3e7b2990 100644 --- a/rigify/utils/mechanism.py +++ b/rigify/utils/mechanism.py @@ -19,8 +19,10 @@ # import bpy +import re -from rna_prop_ui import rna_idprop_ui_create +from rna_prop_ui import rna_idprop_ui_create, rna_idprop_ui_prop_get +from rna_prop_ui import rna_idprop_quote_path as quote_property #============================================= # Constraint creation utilities @@ -143,14 +145,21 @@ def _init_driver_target(drv_target, var_info, target_id): if isinstance(subtarget, str): subtarget = target_id.pose.bones[subtarget] + if subtarget == target_id: + path = '' + else: + path = subtarget.path_from_id() + # Use ".foo" type path items verbatim, otherwise quote - path = subtarget.path_from_id() for item in refs: if isinstance(item, str): - path += item if item[0] == '.' else '["'+item+'"]' + path += item if item[0] == '.' else quote_property(item) else: path += '[%r]' % (item) + if path[0] == '.': + path = path[1:] + drv_target.id = target_id drv_target.data_path = path @@ -298,6 +307,91 @@ def driver_var_transform(target, bone=None, *, type='LOC_X', space='WORLD', rota return { 'type': 'TRANSFORMS', 'targets': [ target_map ] } +#============================================= +# Custom property management +#============================================= + +def deactivate_custom_properties(obj, *, reset=True): + """Disable drivers on custom properties and reset values to default.""" + + prefix = '["' + + if obj != obj.id_data: + prefix = obj.path_from_id() + prefix + + adt = obj.id_data.animation_data + if adt: + for fcu in adt.drivers: + if fcu.data_path.startswith(prefix): + fcu.mute = True + + if reset: + for key, value in obj.items(): + valtype = type(value) + if valtype in {int, float}: + info = rna_idprop_ui_prop_get(obj, key, False) or {} + obj[key] = valtype(info.get("default", 0)) + + +def reactivate_custom_properties(obj): + """Re-enable drivers on custom properties.""" + + prefix = '["' + + if obj != obj.id_data: + prefix = obj.path_from_id() + prefix + + adt = obj.id_data.animation_data + if adt: + for fcu in adt.drivers: + if fcu.data_path.startswith(prefix): + fcu.mute = False + + +def copy_custom_properties(src, dest, *, prefix='', dest_prefix='', link_driver=False): + """Copy custom properties with filtering by prefix. Optionally link using drivers.""" + res = [] + + for key, value in src.items(): + if key.startswith(prefix): + new_key = dest_prefix + key[len(prefix):] + + dest[new_key] = value + + info = rna_idprop_ui_prop_get(src, key, False) + if info: + info2 = rna_idprop_ui_prop_get(dest, new_key, True) + for ki, vi in info.items(): + info2[ki] = vi + + if link_driver: + make_driver(src, quote_property(key), variables=[(dest.id_data, dest, new_key)]) + + res.append((key, new_key, value, info)) + + return res + + +def copy_custom_properties_with_ui(rig, src, dest_bone, *, ui_controls=None, **options): + """Copy custom properties, and create rig UI for them.""" + if isinstance(src, str): + src = rig.get_bone(src) + + bone = rig.get_bone(dest_bone) + mapping = copy_custom_properties(src, bone, **options) + + if mapping: + panel = rig.script.panel_with_selected_check(rig, ui_controls or rig.bones.ctrl.flatten()) + + for key,new_key,value,info in mapping: + name = re.sub(r'[_.-]', ' ', new_key).title() + slider = type(value) is float and info and info.get("min", None) == 0 and info.get("max", None) == 1 + + panel.custom_prop(dest_bone, new_key, text=name, slider=slider) + + return mapping + + #============================================= # Utility mixin #============================================= -- cgit v1.2.3