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
@@ -2101,6 +2101,9 @@ def smartbake(context, org_action, posebones, ids):
for fcu in fcurves:
if path not in fcu.data_path:
continue
#apply the bake only to the transformation channels
if fcu.data_path.split('"].')[-1] not in transformations:
continue
if Tools.filter_properties(context.scene.animtoolbox, fcu):
continue
if posebone.btc.setup in {'TRACK_TO', 'TRACK_TO_EMPTY'} and 'rotation' not in fcu.data_path:
@@ -2108,6 +2111,8 @@ def smartbake(context, org_action, posebones, ids):
if scene.btc.from_origin:
smartfcurve = get_smartfcurve(fcu, smartfcus, posebone, fcu.data_path, fcu.array_index, scene.btc.smartbake)
if smartfcurve is None:
continue
#if it's not the original action then create a new fcurve in org_action where it's baked to and assign it to smartfcurve
#Usefull especially when working inside a new empty layer
if action != org_action and (fcu.data_path, fcu.array_index) not in org_action_fcus:
@@ -2201,7 +2206,7 @@ def smartbake(context, org_action, posebones, ids):
smartfcurve.modifiers.append(mod)
#Remove frames to not include in the bake, in case of custom frame range
if frames_remove:
if frames_remove and smartfcurve:
smartframes = {frame for frame in smartframes if round(frame) not in frames_remove}
smartfcurve.frames = [frame for frame in smartfcurve.frames if round(frame) not in frames_remove]
smartfcurve.interpolations = {frame : interpolation for frame, interpolation in smartfcurve.interpolations.items() if round(frame) not in frames_remove}
@@ -2367,6 +2372,7 @@ def remove_constraints(context, ids, controllers, controlled_objs):
ctrls = list(controllers) + [ctrl.children[0] for ctrl in controllers if ctrl.children]
scene = context.scene
for obj in controlled_objs:
if obj.type != 'ARMATURE':
continue
@@ -2378,16 +2384,17 @@ def remove_constraints(context, ids, controllers, controlled_objs):
#check if the bone has anything assigned to it
if not bone.btc.setup_id:
continue
#reset the setup_id
bone.btc.setup_id = 0
bone.btc.org_id = 0
bone.btc.org = bone.btc.setup ='NONE'
for con in bone.constraints:
if not hasattr(con, 'target'):
continue
if con.target not in ctrls:
continue
#reset the setup_id
bone.btc.setup_id = 0
bone.btc.org_id = 0
bone.btc.org = bone.btc.setup ='NONE'
con_path = con.path_from_id()
#Removing target because of a bug in Blender 4.4, otherwise it crashes when switching mode
con.target = None
@@ -2481,6 +2488,13 @@ def get_controllers_controlled(context):
controlled_objs = {item.controlled for item in scene.btc.ctrl_items if item.controlled}
controllers = {item.controller for item in scene.btc.ctrl_items if item.controller}
#In case controlled objs are not found and there are still bones with ids
#The add the object of this bones to reset them
if not controlled_objs and context.selected_pose_bones:
for bone in context.selected_pose_bones:
if bone.btc.setup_id or bone.btc.org_id:
controlled_objs.add(bone.id_data)
return controllers, controlled_objs
def unhide_org(obj):
@@ -2652,9 +2666,9 @@ def get_bone_ids(context, id = 'setup_id'):
if select_filter == 'ALL':
#get ids from All the controller rigs and bones
# org_ids = {bone.btc.org_id for obj in scene.objects if obj.animtoolbox.controlled for bone in obj.pose.bones if bone.btc.org_id}
for obj in scene.objects:
if not obj.animtoolbox.controlled:
if not obj.animtoolbox.controlled and obj not in context.selected_objects:
#still checking selected objects in case animtoolbox.controlled is empty
continue
if obj.type == 'ARMATURE':
for bone in obj.pose.bones:
@@ -2663,11 +2677,6 @@ def get_bone_ids(context, id = 'setup_id'):
elif obj.type == 'EMPTY' and id == 'setup_id':
if getattr(obj.animtoolbox, id):
ids.add(getattr(obj.animtoolbox, id))
# ids = {getattr(bone.btc, id) for obj in scene.objects if obj.animtoolbox.controlled and obj.type == 'ARMATURE'
# for bone in obj.pose.bones if getattr(bone.btc, id)}
# if id == 'setup_id':
# ids = {getattr(obj.animtoolbox, id) for obj in scene.objects
# if obj.animtoolbox.controlled and getattr(obj.animtoolbox, id)}
return ids
@@ -2814,14 +2823,7 @@ def rebake_connection_ctrls(self, context, obj, rebake_bones, parent, root_name
# constraints_clear(ctrls)
#remove extra channels from the temporary ctrls before removing them
action = obj.animation_data.action
ctrl_paths = [ctrl.path_from_id() for ctrl in ctrls]
fcurves = Tools.get_fcurves_channelbag(obj, action)
for fcu in fcurves:
path = fcu.data_path.split('"].')[0] + ('"]')
if path in ctrl_paths:
fcurves.remove(fcu)
remove_tempctrls_channels(obj, ctrls)
#removing the temporary ctrls
bpy.ops.object.mode_set(mode = 'EDIT')
@@ -2840,6 +2842,22 @@ def rebake_connection_ctrls(self, context, obj, rebake_bones, parent, root_name
return
def remove_tempctrls_channels(obj, ctrls):
#remove extra channels from the temporary ctrls before removing them
if not obj.animation_data:
return
if not obj.animation_data.action:
return
action = obj.animation_data.action
ctrl_paths = [ctrl.path_from_id() for ctrl in ctrls]
fcurves = Tools.get_fcurves_channelbag(obj, action)
for fcu in fcurves:
path = fcu.data_path.split('"].')[0] + ('"]')
if path in ctrl_paths:
fcurves.remove(fcu)
def get_rebake_bones(rig, ids):
#get all the bones with connection (Ctrls and their children)
rebake_bones = []
@@ -2967,8 +2985,8 @@ class Cleanup(bpy.types.Operator):
scene = context.scene
ids = get_bone_ids(context)
controllers, controlled_objs = get_controllers_controlled(context)
if not scene.btc.clean_constraints:
return {'FINISHED'}
#in case the controllers are empties add their ids and if the root is selected
@@ -2977,7 +2995,6 @@ class Cleanup(bpy.types.Operator):
continue
ids.add(ctrl.animtoolbox.setup_id)
controllers_remove_child(ctrl, controllers)
remove_constraints(context, ids, controllers, controlled_objs)
if not scene.btc.clean_ctrls: