import bpy import re def get_addon_prefs(): ''' function to read current addon preferences properties access with : get_addon_prefs().super_special_option ''' import os addon_name = os.path.splitext(__name__)[0] preferences = bpy.context.preferences addon_prefs = preferences.addons[addon_name].preferences return (addon_prefs) def helper(name: str = '') -> str: '''Return name and arguments from calling obj as str :name: - replace definition name by your own str ''' if not get_addon_prefs().debug: return import inspect func = inspect.currentframe().f_back name = name or f'def {func.f_code.co_name}' args = inspect.getargvalues(func).locals arguments = ', '.join([f'{k}={v}' for k, v in args.items()]) return(f'{name}({arguments})') def get_gnd(): for o in bpy.context.scene.objects: if o.type == 'MESH' and o.name.lower() in ('ground', 'gnd'): return o # nothing found print('ERROR', 'No "gnd" object found') def get_follow_curve_from_armature(arm): """Return curve and constraint or a tuple of string ('error', 'message') """ pref = get_addon_prefs() name = pref.tgt_bone parents = [] root = b.id_data.pose.bones.get(name) for c in root.constraints: if c.type == 'FOLLOW_PATH': const = c if c.type == 'CHILD_OF': print(f'found child-of on {name}') if c.target: parents.append(c.target) if not const: for p in parents: for c in p.constraints: if c.type == 'FOLLOW_PATH': print('INFO', f'follow_path found on "{p.name}" parent object') const = c break if not const: return ('ERROR', 'No constraints founds') curve = const.target if not curve: return ('ERROR', f'no target set for {curve.name}') return curve, const def get_obj_action(obj): print(helper()) act = obj.animation_data if not act: print('ERROR', f'no animation data on {obj.name}') return act = act.action if not act: print('ERROR', f'no action on {obj.name}') return return act def set_generated_action(obj): '''Backup object action and return a new action suffixed '_autogen' associated with the object ''' print(helper()) act = get_obj_action(obj) if not act: return regen = re.compile(r'_autogen\.?\d{0,3}$') if regen.search(act.name): # is an autogenerated one org_action_name = regen.sub('', act.name) org_action = bpy.data.actions.get(org_action_name) if not org_action: print('ERROR', f'{org_action_name} not found') return obj.animation_data.action = org_action bpy.data.actions.remove(act) act = org_action # backup action before doing anything crazy act.use_fake_user = True new_act = act.copy() new_act.name = act.name + '_autogen' obj.animation_data.action = new_act return new_act def get_curve_length(ob): dg = bpy.context.evaluated_depsgraph_get() obeval = ob.evaluated_get(dg)#.copy() baked_me = obeval.to_mesh(preserve_all_data_layers=False, depsgraph=dg) mat = obeval.matrix_world total_length = 0 for i, _v in enumerate(baked_me.vertices): if i == 0: continue total_length += ((mat @ baked_me.vertices[i-1].co) - (mat @ baked_me.vertices[i].co)).length print("total_length", total_length)#Dbg return total_length