diff --git a/CHANGELOG.md b/CHANGELOG.md index 147d314..84935d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +1.0.0 + +- fix: broken algo for extreme keys range detection + 0.9.0 - fix problem with translation calculation when all keys are marked diff --git a/OP_animate_path.py b/OP_animate_path.py index 40f2318..6ae74f2 100644 --- a/OP_animate_path.py +++ b/OP_animate_path.py @@ -42,9 +42,12 @@ def has_extremes(b, act=None): def get_extreme_range(ob, act, b): b_fcurves = [fcu for fcu in act.fcurves if fcu.data_path.split('"')[1] == b.bone.name] - start_frame = end_frame = None - + # for f in b_fcurves: + # print('fc:', f.data_path, f.array_index) + curves = [] for fcu in b_fcurves: + start_frame = end_frame = None + e_ct = 0 encountered_marks = False # flag to stop after last extreme of each fcu for k in fcu.keyframe_points: # if k.select_control_point: # based on selection ? @@ -61,15 +64,37 @@ def get_extreme_range(ob, act, b): end_frame = f if end_frame < f: end_frame = f - - else: - if encountered_marks: - ## means back to other frame type after passed breakdown we stop - ## (for this fcu) + + e_ct += 1 + continue + + # it's a normal keyframe + if encountered_marks: + if e_ct == 1: + # reset (continue scan to next frame range) + e_ct = 0 + start_frame = end_frame = None + encountered_marks = False + + else: + ## means back to other frame type after passed sufficient key + ## (stop for this fcu) break - if start_frame is None or end_frame is None: + + print(fcu.data_path, fcu.array_index, start_frame, end_frame) + if start_frame is None or end_frame is None: + continue + if end_frame - start_frame == 0: # same key + continue + + print('ok') + curves.append(end_frame - start_frame) + + if not curves: return - return end_frame - start_frame + print('curves: ', curves) + curves.sort() + return curves[-1] def find_best_foot(ob): '''Get an armature object and do some wizardry to return best match for foot bone''' @@ -120,17 +145,20 @@ def find_best_foot(ob): return b flipped_contact_range = get_extreme_range(ob, act, flipped) - if not flipped_contact_range: - return b + print('flipped_contact_range: ', flipped_contact_range) bone_contact_range = get_extreme_range(ob, act, b) - if bone_contact_range: - if bone_contact_range < flipped_contact_range: - return flipped - else: - return ('ERROR', f'No Extreme (red keys) on bone "{b.name}" for action "{act.name}"') + print('bone_contact_range: ', bone_contact_range) - return b + if bone_contact_range: + if flipped_contact_range and (bone_contact_range < flipped_contact_range): + return flipped + else: + return b + elif flipped_contact_range: + return flipped + + return ('ERROR', f'No Extreme (red keys) on bone "{b.name}" for action "{act.name}"') def anim_path_from_translate(): @@ -189,8 +217,10 @@ def anim_path_from_translate(): b_fcurves = [fcu for fcu in act.fcurves if fcu.data_path.split('"')[1] == b.bone.name] print('b_fcurves: ', len(b_fcurves)) - start_frame = end_frame = None + # find best fcurve + for fcu in b_fcurves: + start_frame = end_frame = None # skip problematic keys if not len(fcu.keyframe_points): if debug: print(fcu.data_path, fcu.array_index, '>> no keys !') @@ -202,8 +232,8 @@ def anim_path_from_translate(): continue encountered_marks = False # flag to stop after last extreme of each fcu + e_ct = 0 for k in fcu.keyframe_points: - # if k.select_control_point: # based on selection ? if k.type == 'EXTREME': encountered_marks = True @@ -217,15 +247,33 @@ def anim_path_from_translate(): end_frame = f if end_frame < f: end_frame = f - - else: - if encountered_marks: + + e_ct += 1 + continue + + # this is a normal keyframe + if encountered_marks: + if e_ct == 1: + # mean only one extreme has been scanned + # reset and continue de keys scan + e_ct = 0 + start_frame = end_frame = None + encountered_marks = False + else: ## means back to other frame type after passed breakdown we stop ## (for this fcu) break + if start_frame is None or end_frame is None: + continue + if start_frame == end_frame: + continue + + # we have a range and were probably happy with this one. + break + if start_frame is None or end_frame is None: - return ('ERROR', f'No / All / not enough keyframe marked Extreme {ob.name} > {b.name}') + return ('ERROR', f'No / All or not enough keyframe marked Extreme {ob.name} > {b.name}') if start_frame == end_frame: return ('ERROR', f'Only one key detected as extreme (at frame {start_frame}) !\nNeed at least two chained marked keys') diff --git a/__init__.py b/__init__.py index cd2cb4b..bb44d1b 100644 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "Unfold Anim Cycle", "description": "Anim tools to develop walk/run cycles along a curve", "author": "Samuel Bernou", - "version": (0, 9, 1), + "version": (1, 0, 0), "blender": (3, 0, 0), "location": "View3D", "warning": "",