diff --git a/CHANGELOG.md b/CHANGELOG.md index 44c2c7f..35d42e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +1.3.4 + +- fixed: bake keys with better cycle compatibility + 1.3.3 - changed: `Set Time Keys` in NLA do not remove keys if exists but offset to match start of strip (if has moved) to resync diff --git a/OP_expand_cycle_step.py b/OP_expand_cycle_step.py index b126e2b..592ff6d 100644 --- a/OP_expand_cycle_step.py +++ b/OP_expand_cycle_step.py @@ -10,6 +10,8 @@ from time import time def bake_cycle(on_selection=True, end=None): print(fn.helper()) end = end or bpy.context.scene.frame_end + end += 20 # add an hardcoded margin ! + print('end: ', end) debug = fn.get_addon_prefs().debug obj = bpy.context.object if obj.type != 'ARMATURE': @@ -28,6 +30,12 @@ def bake_cycle(on_selection=True, end=None): ct = 0 ct_no_cycle = 0 + ## TODO calculate offset only once to avoid errors ! + all_keys = [k.co.x for fc in act.fcurves if not '.offset' in fc.data_path for k in fc.keyframe_points] + first = int(min(all_keys)) + last = int(max(all_keys)) + offset = last - first + for fcu in act.fcurves: ## if a curve is not cycled don't touch @@ -69,13 +77,17 @@ def bake_cycle(on_selection=True, end=None): k_dic['type'] = k.type fcu_kfs.append(k_dic) - first = fcu_kfs[0]['co'][0] + ## not used # second = fcu_kfs[1]['co'][0] # before_last= fcu_kfs[-2]['co'][0] - last = fcu_kfs[-1]['co'][0] # first_offset = second - first - - current_offset = offset = last - first + + ## old + # first = fcu_kfs[0]['co'][0] + # last = fcu_kfs[-1]['co'][0] + # current_offset = offset = last - first + + current_offset = offset keys_num = len(fcu_kfs) if debug >= 2: print(keys_num) @@ -84,8 +96,12 @@ def bake_cycle(on_selection=True, end=None): if debug >= 2: print(b_name, f'{keys_num} key') continue - ## ! important: delete last after computing offset IF cycle have first frame repeatead as last ! - fcu_kfs.pop() + ## delete last after computing offset IF cycle have first frame repeatead as last ! + + # fcu_kfs_without_last = fcu_kfs.copy() + # fcu_kfs_without_last.pop() + + # last_kf = fcu_kfs.pop() (or just iterate with slicing [:-1]) # print('offset: ', offset) if debug >= 2: print('keys', len(fcu_kfs)) @@ -93,11 +109,21 @@ def bake_cycle(on_selection=True, end=None): # maybe add possibility define target manually ? - end += 20 # add an hardcoded margin ! - iterations = ((end - last) // offset) + 1 + iterations = int( ((end - last) // offset) + 1 ) if debug >= 2: print('iterations: ', iterations) - for _i in range(int(iterations)): - for kf in fcu_kfs: + + for i in range(iterations): + # if i == iterations - 1: # last + # kfs = fcu_kfs + # else: + # kfs = fcu_kfs_without_last + # for kf in kfs: + + for count, kf in enumerate(fcu_kfs): + if count == keys_num and i < iterations - 1: + # last key of fcurves, to use only if on last iteration + continue + # create a new key, adding offset to keys fcu.keyframe_points.add(1) new = fcu.keyframe_points[-1] @@ -107,6 +133,9 @@ def bake_cycle(on_selection=True, end=None): else: setattr(new, att, val) current_offset += offset + + # FIXME on last cycle - re-add last keyframe to "close" the cycle + ct += 1 @@ -268,7 +297,7 @@ class AW_OT_bake_cycle_and_step(bpy.types.Operator): def execute(self, context): - err = bake_cycle(context.scene.anim_cycle_settings.expand_on_selected_bones, end=self.endframe) + err = bake_cycle(context.scene.anim_cycle_settings.expand_on_selected_bones, end=self.end_frame) if err: self.report({err[0]}, err[1]) if err[0] == 'ERROR': diff --git a/__init__.py b/__init__.py index 2dca564..17c9be7 100644 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "Auto Walk", "description": "Develop a walk/run cycles along a curve and pin feets", "author": "Samuel Bernou", - "version": (1, 3, 2), + "version": (1, 3, 4), "blender": (3, 0, 0), "location": "View3D", "warning": "",