33from mathutils import Vector
44from mathutils .bvhtree import BVHTree
55from typing import Any , Tuple , List , Union , Set , TYPE_CHECKING
6+ from bpy_extras import anim_utils
67
78if TYPE_CHECKING :
89 from ..data_structures import ObjectShapeKey
@@ -32,7 +33,13 @@ def FCurvesFromObject(obj: bpy.types.Object) -> List[bpy.types.FCurve]:
3233 if obj .animation_data is None : return []
3334 if obj .animation_data .action is None : return []
3435
35- return list (obj .animation_data .action .fcurves )
36+ if bpy .app .version < (5 , 0 , 0 ):
37+ return list (obj .animation_data .action .fcurves )
38+ else :
39+ anim_data = obj .animation_data
40+ channelbag = anim_utils .action_get_channelbag_for_slot (anim_data .action , anim_data .action_slot )
41+ return list (channelbag .fcurves ) if channelbag else []
42+
3643
3744def shapeKeyFCurvesFromObject (obj : bpy .types .Object ) -> List [bpy .types .FCurve ]:
3845 """Gets shape key (`bpy.types.ShapeKey`) FCurves from a object (`bpy.types.Object`).
@@ -44,7 +51,12 @@ def shapeKeyFCurvesFromObject(obj: bpy.types.Object) -> List[bpy.types.FCurve]:
4451 if obj .data .shape_keys is None : return []
4552 if obj .data .shape_keys .animation_data .action is None : return []
4653
47- return list (obj .data .shape_keys .animation_data .action .fcurves )
54+ if bpy .app .version < (5 , 0 , 0 ):
55+ return list (obj .data .shape_keys .animation_data .action .fcurves )
56+ else :
57+ anim_data = obj .data .shape_keys .animation_data
58+ channelbag = anim_utils .action_get_channelbag_for_slot (anim_data .action , anim_data .action_slot )
59+ return list (channelbag .fcurves ) if channelbag else []
4860 return []
4961
5062def validateFCurves (noteOnFCurves : List [Union [bpy .types .FCurve , 'ObjectShapeKey' ]], noteOffFCurves : List [Union [bpy .types .FCurve , 'ObjectShapeKey' ]], haveSorted : bool = False ) -> bool :
@@ -87,12 +99,31 @@ def cleanKeyframes(obj: bpy.types.Object, channels: Set={"all_channels"}):
8799 """
88100 fCurves = FCurvesFromObject (obj )
89101
90- for fCurve in fCurves :
91- if {fCurve .data_path , "all_channels" }.intersection (channels ):
92- obj .animation_data .action .fcurves .remove (fCurve )
93-
94- for fCurve in shapeKeyFCurvesFromObject (obj ):
95- obj .data .shape_keys .animation_data .action .fcurves .remove (fCurve )
102+ if bpy .app .version < (5 , 0 , 0 ):
103+ for fCurve in fCurves :
104+ if {fCurve .data_path , "all_channels" }.intersection (channels ):
105+ obj .animation_data .action .fcurves .remove (fCurve )
106+
107+ for fCurve in shapeKeyFCurvesFromObject (obj ):
108+ obj .data .shape_keys .animation_data .action .fcurves .remove (fCurve )
109+ else :
110+ # Object fcurves
111+ anim_data = obj .animation_data
112+ if anim_data and anim_data .action :
113+ channelbag = anim_utils .action_get_channelbag_for_slot (anim_data .action , anim_data .action_slot )
114+ if channelbag :
115+ for fCurve in fCurves :
116+ if {fCurve .data_path , "all_channels" }.intersection (channels ):
117+ channelbag .fcurves .remove (fCurve )
118+
119+ # Shape key fcurves
120+ if obj .data .shape_keys and obj .data .shape_keys .animation_data :
121+ sk_anim_data = obj .data .shape_keys .animation_data
122+ if sk_anim_data .action :
123+ sk_channelbag = anim_utils .action_get_channelbag_for_slot (sk_anim_data .action , sk_anim_data .action_slot )
124+ if sk_channelbag :
125+ for fCurve in shapeKeyFCurvesFromObject (obj ):
126+ sk_channelbag .fcurves .remove (fCurve )
96127
97128def secToFrames (sec : float ) -> float :
98129 """converts (using the Blender scene's FPS) specified time (in seconds) to frames
0 commit comments