2025-12-01

This commit is contained in:
2026-03-17 14:58:51 -06:00
parent 183e865f8b
commit 4b82b57113
6846 changed files with 954887 additions and 162606 deletions
+211 -119
View File
@@ -3,7 +3,7 @@ from . import anim_layers
from . import subscriptions
from mathutils import Vector, Quaternion
import numpy as np
#import time
# import time
def frame_start_end(scene):
if scene.use_preview_range:
@@ -12,7 +12,7 @@ def frame_start_end(scene):
else:
frame_start = scene.frame_start
frame_end = scene.frame_end
return frame_start, frame_end
return float(frame_start), float(frame_end)
def smart_start_end(smartkeys, frame_start, frame_end):
'''add the first and last frame of the scene if necessery'''
@@ -65,11 +65,11 @@ def smart_repeat(smartkeys, fcu, strip):
#duplicate the keys on the cycle after
keyframes_dup = []
for i in range(1, int(strip.repeat)):
for key in smartkeys[1:]:
keydup = smartkey(key)
keydup.frame += fcu_range*(i)
keydup.frame += round(fcu_range*(i), 2)
#duplicate the tangents tuple values
if hasattr(key, 'handle_left'):
keydup.handle_left = Vector([key.handle_left[0] + fcu_range*(i+1), key.handle_left[1]])
@@ -104,7 +104,6 @@ def smart_cycle(smartkeys, fcu, frame_start, frame_end):
cycle_end_dup = int((mod.frame_end - fcu.range()[1])/fcu_range)+2
#copy the the right handle of the first keyframe to the last, and the left handle from the last keyframe to the first
smartkeys[-1].handle_right_type = smartkeys[0].handle_left_type
smartkeys[0].handle_left_type = smartkeys[-1].handle_right_type
# if smartkeys[-1].interpolation == 'BEZIER':
@@ -113,13 +112,13 @@ def smart_cycle(smartkeys, fcu, frame_start, frame_end):
# if smartkeys[0].interpolation == 'BEZIER':
if hasattr(smartkeys[0], 'handle_left'):
smartkeys[0].handle_left = [smartkeys[-1].handle_left[0] - fcu_range, smartkeys[0].handle_left[1]]
#duplicate the keys on the cycle after
keyframes_dup = []
for key in smartkeys[1:]:
for i in range(cycle_end_dup):
keydup = smartkey(key)
keydup.frame += float(fcu_range*(i+1))
keydup.frame += float(round(fcu_range, 2)*(i+1))
if hasattr(keydup, 'handle_left'):
#duplicate the tangents tuple values
keydup.handle_left = Vector([key.handle_left[0] + fcu_range*(i+1), key.handle_left[1]])
@@ -127,8 +126,8 @@ def smart_cycle(smartkeys, fcu, frame_start, frame_end):
#if it's the last keyframe then the right handle get the value from the first keyframes
keydup.handle_right = Vector([key.handle_right[0] + fcu_range*(i+1), key.handle_right[1]])
if keydup not in keyframes_dup:
keydup.frame = round(keydup.frame, 2)
keyframes_dup.append(keydup)
#if it's an iternal cycle then duplicate the keyframes before the cycle keyframes
if not mod.cycles_before and mod.mode_before != 'None':
cycle_start_dup = int((fcu.range()[0] - frame_start) /fcu_range)+2
@@ -138,37 +137,52 @@ def smart_cycle(smartkeys, fcu, frame_start, frame_end):
cycle_start_dup = mod.cycles_before
if mod.use_restricted_range and mod.frame_start > (fcu.range()[0] + fcu_range * cycle_start_dup):
cycle_start_dup = int((fcu.range()[0]-mod.frame_start)/fcu_range)+2
#duplicate the keys on the cycle before
for key in smartkeys[:-1]:
for i in range(cycle_start_dup):
keydup = smartkey(key)
keydup.frame -= float(fcu_range*(i+1))
keydup.frame -= fcu_range*(i+1)
if hasattr(keydup, 'handle_left'):
#duplicate the tangents
keydup.handle_left = [key.handle_left[0] - fcu_range*(i+1), key.handle_left[1]]
if hasattr(keydup, 'handle_right'):
keydup.handle_right = [key.handle_right[0] - fcu_range*(i+1), key.handle_right[1]]
#if frame_end > key.frame > frame_start:
if keydup not in keyframes_dup:
keydup.frame = round(keydup.frame, 2)
keyframes_dup.append(keydup)
#merge the keyframes from the cycle with the or iginal keyframes
smartkeys.extend(keyframes_dup)
smartkeys = list(set(smartkeys))
smartkeys.sort()
if mod.use_restricted_range:
smartkeys = smart_start_end(smartkeys, mod.frame_start, mod.frame_end)
smartkeys = smart_start_end(smartkeys, mod.frame_start+1, mod.frame_end-1)
return smartkeys
def smart_bake(context):
#record all the keyframes into smartkeys
obj = context.object
frame_start, frame_end = context.scene.als.bake_range
fcu_smartkeys = {}
anim_data = anim_layers.anim_data_type(obj)
# Initialize the progress bar
wm = context.window_manager
total_iterations = 0
for track in anim_data.nla_tracks:
if track.mute:
continue
if len(track.strips) != 1 or track.strips[0].action is None:
continue
fcurves = anim_layers.get_fcurves(obj, track.strips[0].action)
total_iterations += len(fcurves)
wm.progress_begin(0, total_iterations)
processed = 0
for layer, track in zip(obj.Anim_Layers, anim_data.nla_tracks):
if track.mute:
continue
@@ -181,7 +195,8 @@ def smart_bake(context):
for strip_fcu in strip.fcurves:
strip_keyframes = [keyframe for keyframe in strip_fcu.keyframe_points if len(strip_fcu.keyframe_points) and not strip_fcu.mute]
for fcu in strip.action.fcurves:
fcurves = anim_layers.get_fcurves(obj, strip.action)
for fcu in fcurves:
if not fcu.is_valid or fcu.mute or selected_bones_filter(obj, fcu.data_path):
continue
smartkeys = []
@@ -192,9 +207,12 @@ def smart_bake(context):
if strip.blend_type in {'COMBINE', 'REPLACE'}:
keyframe.handle_left = Vector(key.handle_left)
keyframe.handle_right = Vector(key.handle_right)
keyframe.handle_left[0] = strip_start * layer.speed + (keyframe.handle_left[0] - strip_start) * layer.speed + layer.offset
keyframe.handle_right[0] = strip_start * layer.speed + (keyframe.handle_right[0] - strip_start) * layer.speed + layer.offset
#keyframe.frame += layer.offset
keyframe.frame = strip_start * layer.speed + (keyframe.frame - strip_start) * layer.speed + layer.offset
keyframe.frame = strip_start * layer.speed + (keyframe.frame - strip_start) * layer.speed + layer.offset# * layer.speed
keyframe.frame = round(keyframe.frame, 2)
if keyframe not in smartkeys:
smartkeys.append(keyframe)
@@ -210,37 +228,44 @@ def smart_bake(context):
smartkeys.sort()
if len(fcu.modifiers) and obj.als.mergefcurves:
smartkeys = smart_cycle(smartkeys, fcu, frame_start, frame_end)
#apply strip action settings
last_frame = (strip.frame_end - strip.frame_start) / strip.repeat + strip.frame_start
if strip.use_reverse:
for key in smartkeys:
key.frame = last_frame - (key.frame - strip.frame_start)
key.frame = last_frame - (key.frame - strip.frame_start)
if strip.repeat > 1:
smartkeys = smart_start_end(smartkeys, last_frame , last_frame+1) #strip.frame_start
smartkeys = remove_outofrange_keys(smartkeys, strip.frame_start, last_frame+1) #+ layer.offset
smartkeys = smart_repeat(smartkeys, fcu, strip)
if layer.frame_range:
if layer.custom_frame_range:
smartkeys = smart_start_end(smartkeys, strip.frame_start, strip.frame_end)
smartkeys = remove_outofrange_keys(smartkeys, strip.frame_start, strip.frame_end)
#if the strip is cutting with a different strip, then add keyframes in the cut
for layercut in obj.Anim_Layers:
if layercut.mute or not layercut.frame_range or layercut == layer:
if layercut.mute or not layercut.custom_frame_range or layercut == layer:
continue
if strip_start < layercut.frame_start < strip_end:
smartkeys = smart_start_end(smartkeys, (layercut.frame_start-1), strip.frame_end-1)
if strip_start < layercut.frame_end < strip_end:
smartkeys = smart_start_end(smartkeys, (layercut.frame_end+1), strip.frame_end-1)
#if the list of keyframes exists in a different track list then add them
if (fcu.data_path, fcu.array_index) in fcu_smartkeys:
smartkeys = list(set(fcu_smartkeys[(fcu.data_path, fcu.array_index)]+smartkeys))
#Merge all duplicated keyframes
smartkeys = list(set(smartkeys))
smartkeys.sort()
fcu_smartkeys.update({(fcu.data_path, fcu.array_index):smartkeys})
processed += 1
wm.progress_update(processed)
wm.progress_end()
#add inbetweens
for fcu, smartkeys in fcu_smartkeys.items():
if not smartkeys:
@@ -267,11 +292,13 @@ def add_inbetween(smartkeys):
key2 = smartkey()
key2.frame = smartkeys[i].frame + (smartkeys[i+1].frame - smartkeys[i].frame)*2/3
key1.frame = round(key1.frame, 2)
key2.frame = round(key2.frame, 2)
key2.inbetween = True
smartkeys.insert(i+1, key1)
smartkeys.insert(i+2, key2)
i += 3
return smartkeys
class smartkey:
@@ -345,7 +372,8 @@ def mute_modifiers(obj, nla_tracks):
for track in nla_tracks:
if len(track.strips) != 1 or track.strips[0].action is None:
continue
for fcu in track.strips[0].action.fcurves:
fcurves = anim_layers.get_fcurves(obj, track.strips[0].action)
for fcu in fcurves:
if selected_bones_filter(obj, fcu.data_path):
continue
if fcu.extrapolation == 'LINEAR':
@@ -370,7 +398,8 @@ def unmute_modifiers(obj, nla_tracks, modifier_rec):
for track in nla_tracks:
if track.strips[0].action is None:
continue
for fcu in track.strips[0].action.fcurves:
fcurves = anim_layers.get_fcurves(obj, track.strips[0].action)
for fcu in fcurves:
if not fcu.is_valid or selected_bones_filter(obj, fcu.data_path):
continue
if not len(fcu.modifiers):
@@ -398,7 +427,7 @@ def select_keyframed_bones(self, context, obj):
bpy.ops.object.posemode_toggle()
bpy.ops.pose.select_all(action='DESELECT')
for i in range(0, obj.als.layer_index+1):
obj.als.layer_index = i
obj.als['layer_index'] = i
anim_layers.select_layer_bones(self, context)
def mute_constraints(obj):
@@ -422,14 +451,15 @@ def smartbake_apply(obj, nla_tracks, fcu_keys, extrapolations):
# return
# action_range = strip.frame_end - strip.frame_start
for fcu in strip.action.fcurves:
fcurves = anim_layers.get_fcurves(obj, strip.action)
for fcu in fcurves:
if not fcu.is_valid:
continue
if selected_bones_filter(obj, fcu.data_path):
continue
fcu_key = (fcu.data_path, fcu.array_index)
if fcu_key not in fcu_keys.keys():
strip.action.fcurves.remove(fcu)
fcurves.remove(fcu)
continue
#get all the frames of the smart keys
smartkeys = fcu_keys[fcu_key]
@@ -453,34 +483,6 @@ def smartbake_apply(obj, nla_tracks, fcu_keys, extrapolations):
fcu.keyframe_points[-1].co = (smart_key.frame, value)
fcu.update()
#remove unnecessery keyframes
# for i in range(int(strip.action.frame_range[0]),int(strip.action.frame_range[1]+1)):
# if i in smart_frames:
# #get the index of the smart key based on the smart frames + interpolations
# smart_index = (smart_frames.index(i)+1)*3-3
# #if key was founded add the interpolation and handles
# for key in fcu.keyframe_points:
# if key.co[0] != i:
# continue
# key.co[1] = round(key.co[1], 4)
# key.interpolation = smartkeys[smart_index].interpolation
# # key.handle_left_type = smartkeys[smart_index].handle_left_type
# # key.handle_right_type = smartkeys[smart_index].handle_right_type
# key.handle_left_type = 'AUTO_CLAMPED' if smartkeys[smart_index].handle_left_type != 'VECTOR' else 'VECTOR'
# key.handle_right_type = 'AUTO_CLAMPED' if smartkeys[smart_index].handle_right_type != 'VECTOR' else 'VECTOR'
# break
#delete the keys that are not in the list
# else:
# if fcu.data_path.split(".")[-1] in transform_types:
# print('fcu.id_data', fcu.id_data, obj.animation_data.action)
# fcu.keyframe_delete(fcu.data_path.split(".")[-1] ,index = fcu_key[1], frame = i)
# else:
# try:
# fcu.keyframe_delete(fcu.data_path.split(".")[-1], frame = i)
# except TypeError:
# pass
i = 0
while i < len(fcu.keyframe_points):
key = fcu.keyframe_points[i]
@@ -518,7 +520,7 @@ def armature_restore(obj, b_layers, layers_rec, constraint_rec):
def attr_default(obj, fcu_key):
'''Returns the default value or default array value in a list'''
#check if the fcurve source belongs to a bone or obj
if fcu_key[0][:10] == 'pose.bones':
if fcu_key[0][:10] == 'pose.bones':
transform = fcu_key[0].split('.')[-1]
attr = fcu_key[0].split('"')[-2]
bone = fcu_key[0].split('"')[1]
@@ -557,7 +559,7 @@ def attr_default(obj, fcu_key):
attr = fcu_key[0].split('"')[1]
if 'attr' not in locals():
print(fcu_key[0], 'has no attributes returning 0')
# print(fcu_key[0], 'has no attributes returning 0')
return [0]
#since blender 3 access to custom property settings changed
@@ -571,6 +573,7 @@ def attr_default(obj, fcu_key):
return [0]
def selected_bones_filter(obj, fcu_data_path):
'''using obj.als.onlyselected property for the bake'''
if not obj.als.onlyselected:
return False
if obj.mode != 'POSE':
@@ -597,7 +600,6 @@ def evaluate_combine(data_path, added_array, eval_array, array_default, influenc
return eval_array
def frame_evaluation(frame, strip):
frame_eval = frame
#change the frame if the strip is on hold
if frame < strip.frame_start:
@@ -620,6 +622,17 @@ def frame_evaluation(frame, strip):
return frame_eval
def clean_no_user_slots(action):
'''Remove all the slots that are connected to the action and object but not part of the action slot'''
if not hasattr(action, 'slots'):
return
for slot in action.slots:
if slot is None:
continue
if len(slot.users()):
continue
action.slots.remove(slot)
def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, actioncopy, baked_layer = None):
@@ -627,19 +640,37 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
if obj is None:
return
anim_data = anim_layers.anim_data_type(obj)
baked_action = anim_data.action
if obj.als.operator == 'MERGE' and not additive and anim_data.action is not None: #and obj.als.onlyselected
# baked_action = anim_data.action
track = nla_tracks[obj.als.layer_index]
baked_action = track.strips[0].action
clean_no_user_slots(baked_action)
#create the baked fcurve
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
baked_fcurves = baked_channelbag.fcurves
if obj.als.operator == 'MERGE':# and not additive: # and anim_data.action is not None: #and obj.als.onlyselected
#overwrite action
anim_data.use_tweak_mode = False
#create a duplicate of the action on the merged layer to have a clean action in order to not write over the calculation
action_copy = bpy.data.actions[baked_action.name].copy()
nla_tracks[obj.als.layer_index].strips[0].action = action_copy
baked_action.id_root = obj.als.data_type
track.strips[0].action = action_copy
if hasattr(baked_action, 'id_root'):
baked_action.id_root = obj.als.data_type
blend_types = {'ADD' : '+', 'SUBTRACT' : '-', 'MULTIPLY' : '*'}
fcu_paths = []
# Initialize the progress bar
wm = bpy.context.window_manager
fcu_set = {fcu_key[0] for fcu_key in fcu_keys.keys()}
total_iterations = len(fcu_set)
wm.progress_begin(0, total_iterations) # (start, end range)
processed = 0
for fcu_key in fcu_keys.keys():
if fcu_key[0] in fcu_paths:
continue
@@ -674,18 +705,30 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
for track in nla_tracks:
if track.mute:
continue
if not len(track.strips):
continue
if track.strips[0].action is None:
continue
# if track == baked_layer:
# continue
#finding the channel group of array
fcu = track.strips[0].action.fcurves.find(fcu_key[0], index = i)
channelbag = anim_layers.get_channelbag(obj, track.strips[0].action)
if channelbag is None:
continue
fcurves = channelbag.fcurves
fcu = fcurves.find(fcu_key[0], index = i)
# print(f'track {track.name} fcurves {len(fcurves)}')
if fcu is None:
# print('fcu is none', fcu_key[0], track.name)
continue
group = fcu.group if fcu.group is not None else None
if group is not None:
if group.name in baked_action.groups:
group = baked_action.groups[group.name]
if group.name in baked_channelbag.groups:
group = baked_channelbag.groups[group.name]
else:
group = baked_action.groups.new(group.name)
group = baked_channelbag.groups.new(group.name)
#copy and append Modifiers into mod_list. Mute them if turned on
if len(fcu.modifiers) and not obj.als.mergefcurves:
@@ -697,20 +740,22 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
# modifier_rec.append(mod)
mod.mute = True
extrapolation = True if fcu.extrapolation == 'LINEAR' else False
#### Creating or overwritting (during merge) the new baked fcurves####
baked_fcu = ensure_fcurves_bversion(baked_fcurves, fcu_key[0], i)
#create the baked fcurve
baked_fcu = baked_action.fcurves.find(fcu_key[0], index = i)
if baked_fcu is not None:
baked_action.fcurves.remove(baked_fcu)
baked_fcu = baked_action.fcurves.new(fcu_key[0], index = i)
baked_fcu.color_mode = 'AUTO_RGB'
if group is not None:
if baked_fcu.group != group:
baked_fcu.group = group
if extrapolation:
baked_fcu.extrapolation = 'LINEAR'
baked_fcus.append(baked_fcu)
#select smart bake frame range or every frame in the range
if obj.als.smartbake:
#merge all the smartframe arrays
@@ -726,9 +771,15 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
#ITERATE through all the layers to evaluate
for track in nla_tracks:
if not len(track.strips):
continue
if track.mute or track == baked_layer or track.strips[0].action is None:
continue
strip = track.strips[0]
fcurves = anim_layers.get_fcurves(obj, strip.action)
if not len(fcurves):
continue
if (frame < strip.frame_start or frame > strip.frame_end) and strip.extrapolation == 'NOTHING':
layers_count += 1
continue
@@ -750,11 +801,14 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
added_array = []
missing = 0
for i in range(array_length):
fcu = strip.action.fcurves.find(fcu_key[0], index = i)
fcu = fcurves.find(fcu_key[0], index = i)
#if the fcurve is not found then get the default value
if fcu is None:
missing += 1
value = array_default[i] if blend_type in ('REPLACE', 'COMBINE') else 0
#getting the previous value if the fcurve is missing instead of just default
#the other option would be to use an array for the influence as well
value = eval_array[i] if blend_type in ('REPLACE', 'COMBINE') else 0
else:
value = fcu.evaluate(frame_eval)
added_array.append(value)
@@ -773,7 +827,6 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
eval_array = evaluate_combine(fcu_key[0], added_array, eval_array, array_default, influence)
else:
eval_array = eval('eval_array' + blend_types[blend_type] +' added_array' + '*' + str(influence))
#extrapolation = True if fcu.extrapolation == 'LINEAR' else False
layers_count += 1
if not eval_array.size:
@@ -792,18 +845,11 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
smartkey.value = eval_array[i]
if smartkey.inbetween:
continue
# if hasattr(smartkey, 'handle_left') and not additive:
# if not smartkey.handle_left[1]:
# smartkey.handle_left[1] = array_default[i]
# if hasattr(smartkey, 'handle_right') and not additive:
# if not smartkey.handle_right[1]:
# smartkey.handle_right[1] = array_default[i]
baked_fcu.keyframe_points.add(1)
keyframe = baked_fcu.keyframe_points[-1]
keyframe.co = (frame, eval_array[i])
for baked_fcu in baked_fcus:
if not len(baked_fcu.keyframe_points):
continue
@@ -818,12 +864,32 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
#paste the modifiers to the new baked fcurve
if i in mod_list and not len(baked_fcu.modifiers):
anim_layers.paste_modifiers(baked_fcu, mod_list[i])
processed += 1
wm.progress_update(processed)
wm.progress_end()
if not actioncopy and obj.als.operator == 'MERGE':
bpy.data.actions.remove(action_copy)
return baked_action
def ensure_fcurves_bversion(fcurves, data_path, i):
'''Either use ensure in Blender 5.0 and above or use find and new in older version'''
if hasattr(fcurves, 'ensure'):
baked_fcu = fcurves.ensure(data_path, index = i)
else:
baked_fcu = fcurves.find(data_path, index = i)
if baked_fcu is None:
baked_fcu = fcurves.new(data_path, index = i)
if len(baked_fcu.keyframe_points):
baked_fcu.keyframe_points.clear()
return baked_fcu
def non_recalc_handle_type(baked_keys):
handles_type = bpy.context.scene.als.handles_type
@@ -849,7 +915,9 @@ def add_interpolations(baked_fcu, smartkeys, layers_count = 0):
P2index = 2
if len(baked_keys) != len(keys):
print('unequal length of keys ',baked_fcu.data_path, len(baked_keys), len(keys))
print('set difference ', set([key.frame for key in keys]).difference(set([round(key.co[0], 2) for key in baked_keys])))
print('keys ', [key.frame for key in keys])
print('baked keys ', [round(key.co[0], 2) for key in baked_keys])
print('set difference ', set([key.frame for key in keys]).difference(set([key.co[0] for key in baked_keys])))
baked_keys[0].handle_left_type = 'VECTOR'
baked_keys[-1].handle_right_type = 'VECTOR'
@@ -876,7 +944,6 @@ def add_interpolations(baked_fcu, smartkeys, layers_count = 0):
skip = True
if not smartkeys[P1index].inbetween :
# print(baked_fcu.data_path, baked_keys[i].co[0], 'not with inbetween', P1index, P2index, i)
P1index += 1
P2index += 1
continue
@@ -911,11 +978,10 @@ def add_interpolations(baked_fcu, smartkeys, layers_count = 0):
#iterate through the inbetween smartkeys
P1index += 3
P2index += 3
# baked_fcu.update()
#add in-betweener
def apply_handle_types(baked_keys, smartkeys, i):
handles_type = bpy.context.scene.als.handles_type
@@ -933,35 +999,40 @@ def apply_handle_types(baked_keys, smartkeys, i):
def bake_range_type(self, context):
if self.bake_range_type == 'SCENE':
self.bake_range = frame_start_end(bpy.context.scene)
frame_start, frame_end = frame_start_end(context.scene)
self.bake_range = (int(frame_start), int(frame_end))
if self.bake_range_type == 'KEYFRAMES':
obj = context.object
anim_data = anim_layers.anim_data_type(obj)
frame_end = []
frame_start = []
posebones = context.selected_pose_bones
#if baking only selected bones then find the longest fcurves for the range
if obj.als.onlyselected:
posebones = context.selected_pose_bones
if obj.als.onlyselected and posebones:
bonespath = [bone.path_from_id() for bone in posebones]
#get the frame range from
if not bonespath:
return
for track in obj.animation_data.nla_tracks:
if not len(track.strips):
continue
action = track.strips[0].action
for fcu in action.fcurves:
for track in anim_data.nla_tracks:
if not len(track.strips):
continue
action = track.strips[0].action
if obj.als.onlyselected and posebones:
# Get fcurve range from the selected objects
fcurves = anim_layers.get_fcurves(obj, action)
for fcu in fcurves:
#check if the fcurve is in the selected bones
if any(path in fcu.data_path for path in bonespath):
frame_start.append(fcu.range()[0])
frame_end.append(fcu.range()[1])
else:
for track in obj.animation_data.nla_tracks:
if not len(track.strips):
continue
else:
# Get the action range
action = track.strips[0].action
frame_start.append(action.frame_range[0])
frame_end.append(action.frame_range[1])
# Checking for the longest action in all the actions
if frame_start:
self.bake_range = (int(min(frame_start)), int(max(frame_end)))
@@ -1042,10 +1113,23 @@ class MergeAnimLayerDown(bpy.types.Operator):
obj.als.smartbake = False
subscriptions.subscriptions_remove()
#start = time.time()
# start = time.time()
#define the start and end frame of the bake, according to scene or preview length
frame_start, frame_end = context.scene.als.bake_range
# Incase the strips are shorter then the keyframe range (because scene is shorter)
# Then updating the strips length
for layer, track in zip(obj.Anim_Layers, anim_data.nla_tracks):
if layer.custom_frame_range:
continue
if len(track.strips) != 1:
continue
strip = track.strips[0]
strip.frame_start =frame_start
anim_layers.update_action_frame_range(frame_start, frame_end, layer, strip)
strip.scale = layer.speed
strip.frame_end = frame_end
obj.als.view_all_keyframes = False
if context.scene.frame_current > frame_end:
context.scene.frame_current = frame_end
@@ -1054,8 +1138,9 @@ class MergeAnimLayerDown(bpy.types.Operator):
blendings = [track.strips[0].blend_type for track in nla_tracks[layer_index:] if len(track.strips) == 1]
#define if the new baked layer is going to be additive or replace
additive = False
if obj.als.direction == 'UP' and 'REPLACE' not in blendings and obj.als.baketype == 'AL':
additive = False
if obj.als.direction == 'UP' and 'REPLACE' not in blendings and obj.als.baketype == 'AL' and layer_index:
if 'COMBINE' in blendings:
blend = 'COMBINE'
else:
@@ -1063,15 +1148,19 @@ class MergeAnimLayerDown(bpy.types.Operator):
additive = True
else:
blend = 'REPLACE'
mute_rec = mute_unbaked_layers(layer_index, nla_tracks, additive)
fcu_keys = smart_bake(context)
if obj.als.operator == 'MERGE':
if obj.als.direction == 'DOWN':
obj.als.layer_index = 0
baked_layer = None
action = anim_data.nla_tracks[obj.als.layer_index].strips[0].action
strip = anim_data.nla_tracks[obj.als.layer_index].strips[0]
action = strip.action
if hasattr(strip, 'action_slot'):
action_slot = strip.action_slot
if action is not None: action_name = action.name
#if baking to a new layer then setup the new index and layer
@@ -1109,7 +1198,8 @@ class MergeAnimLayerDown(bpy.types.Operator):
for col in obj.data.collections:
layers_rec.update({col : col.is_visible})
col.is_visible = True
# Select the bones from all the layers
self.shift = True
select_keyframed_bones(self, context, obj)
constraint_rec = mute_constraints(obj)
@@ -1123,7 +1213,7 @@ class MergeAnimLayerDown(bpy.types.Operator):
if not obj.select_get():
obj.select_set(True)
bpy.ops.nla.bake(frame_start = frame_start, frame_end = frame_end, only_selected = True, visual_keying=True, clear_constraints=obj.als.clearconstraints, bake_types = bake_type, step = self.step)
anim_data.action.fcurves.update()
# anim_data.action.fcurves.update()
strip = track.strips[0]
old_action = strip.action
@@ -1133,7 +1223,6 @@ class MergeAnimLayerDown(bpy.types.Operator):
track.strips.remove(strip)
strip = track.strips.new(track.name, 0, action)
anim_layers.tweak_mode_upper_stack(context, obj, anim_data, enter = False)
#strip.action = anim_data.action
if obj.als.smartbake:
smartbake_apply(obj, nla_tracks, fcu_keys, extrapolations)
@@ -1141,35 +1230,39 @@ class MergeAnimLayerDown(bpy.types.Operator):
armature_restore(obj, b_layers, layers_rec, constraint_rec)
unmute_modifiers(obj, nla_tracks, modifier_rec)
anim_data.action = None
# anim_data.action = None
#bpy.data.actions.remove(old_action)
if self.actioncopy:
old_action.name = action_name + '_old'
else:
bpy.data.actions.remove(old_action)
strip.action.name = action_name
# strip.action.name = action_name
if blendings.count('COMBINE') == len(blendings) and len(blendings) and obj.als.direction == 'UP':
track.strips[0].blend_type = 'COMBINE'
else: #use anim layers bake
#print(frame_start, frame_end)
action = AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, self.step, self.actioncopy, baked_layer)
#action = AL_bake(self, frame_start, frame_end, nla_tracks, fcu_keys, additive, baked_layer)
anim_layers.tweak_mode_upper_stack(context, obj, anim_data, enter = False)
track.strips.remove(track.strips[0])
strip = track.strips.new(track.name, 0, action)
strip.blend_type = blend
#track.strips[0].action = action
#removing layers after merge
if obj.als.operator == 'MERGE':
if hasattr(strip, 'action_slot'):
if action_slot in strip.action.slots.values():
strip.action_slot = action_slot
else:
# During NLA Bake slot doesn't exist need to find a new on
strip.action_slot = anim_layers.get_obj_slot(obj, action)
#reset layer settings
baked_layer = obj.Anim_Layers[obj.als.layer_index]
baked_layer.repeat, baked_layer.speed, baked_layer.offset = 1, 1, 0
strip.use_sync_length = False
if baked_layer.frame_range:
baked_layer.frame_range = False
if baked_layer.custom_frame_range:
baked_layer.custom_frame_range = False
baked_layer.frame_start = frame_start
baked_layer.frame_end = frame_end
@@ -1210,7 +1303,6 @@ class MergeAnimLayerDown(bpy.types.Operator):
track.mute = True
else:
track.mute = False
action.use_fake_user = True
anim_layers.register_layers(obj, nla_tracks)