To understand how the filter function callback works, you can register a test function to explore the argument passed by the callback:
For example, if you select a Sphere scene node called "Sphere01", the callback traverses all its sub-anim tracks and calls the function multiple times. The function prints all arguments to the Listener.
You can take a look at some of them for better understanding:
theAnimatable: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theParent: undefined theSubAnimIndex: 1 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
In this case, the scene node Sphere01 is being filtered. There is no grand parent, there is no parent either, the animatable to be filtered is the node itself, the subAnim Index is 1. This is the "top level" of the node.
theAnimatable: Controller:Bezier_Float theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 1 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
In this case, there is no grand parent, the parent is the sphere node itself, the animatable to be filtered is the subAnim with Index 1, which is the Bezier Controller of the Visibility track. This shows that the visibility of this sphere is animated. Otherwise, theAnimatable would be undefined.
theAnimatable: undefined theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 2 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
In this case, there is no grand parent, the parent is the sphere node itself, the animatable to be filtered is the subAnim with Index 2, which is undefined. Track 2 of every node is the Space_Warps subAnim track. You can verify by typing in the Listener:
$Sphere01[2] $Sphere01[2].controller --results: SubAnim:Space_Warps undefined theAnimatable: Controller:Position_Rotation_Scale theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 3 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
In this case, there is no grand parent, the parent is the sphere node itself, the animatable to be filtered is the subAnim with Index 3, which is the Transformation controller (in this case a Position_Rotation_Scale controller).
theAnimatable: Controller:Position_XYZ theParent: Controller:Position_Rotation_Scale theSubAnimIndex: 1 theGrandParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Now, go one level deeper. The grand parent is the Sphere, the parent is the Transformation controller (Position_Rotation_Scale), the subAnim index inside the parent is 1, which corresponds to the Position track (in this case a Position_XYZ controller). For comparison, try typing in the Listener:
$Sphere01[3][1].controller Controller:Position_XYZ theAnimatable: Controller:Bezier_Float theParent: Controller:Position_XYZ theSubAnimIndex: 1 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Now, go even deeper. The grand parent is the node Transformation track (the PRS controller), the parent is the Position track (the Position_XYZ), the animatable to be filtered is the subAnim with Index 1, which is the Bezier controller assigned to the X axis of the node position.
theAnimatable: Controller:Bezier_Float theParent: Controller:Position_XYZ theSubAnimIndex: 2 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: Controller:Bezier_Float theParent: Controller:Position_XYZ theSubAnimIndex: 3 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Same with these two tracks, which are the Y and Z sub-controllers of the Position track with indices 2 and 3 respectively. This is the same as accessing
$Sphere01[3][1][3].controller --result Controller:Bezier_Float theAnimatable: Controller:Euler_XYZ theParent: Controller:Position_Rotation_Scale theSubAnimIndex: 2 theGrandParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Now, go back one level and get to the second subAnim index of the PRS controller, which is the Rotation track. It has an Euler_XYZ controller assigned. The following three calls traverses the X, Y, and Z sub-controllers of the rotation:
theAnimatable: Controller:Bezier_Float theParent: Controller:Euler_XYZ theSubAnimIndex: 1 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: Controller:Bezier_Float theParent: Controller:Euler_XYZ theSubAnimIndex: 2 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: Controller:Bezier_Float theParent: Controller:Euler_XYZ theSubAnimIndex: 3 theGrandParent: Controller:Position_Rotation_Scale theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Go back one level again and get to the third subAnim index of the PRS controller, which is the Scale track. It has a Bezier_Scale controller assigned that does not have sub-controllers:
theAnimatable: Controller:Bezier_Scale theParent: Controller:Position_Rotation_Scale theSubAnimIndex: 3 theGrandParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: Sphere theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 4 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Go back to the Sphere object level and check the 4 th subAnim index, which is the Sphere object.
$Sphere01[4] $Sphere01[4].controller --results: SubAnim:Object__Sphere undefined theAnimatable: ReferenceTarget:ParamBlock theParent: Sphere theSubAnimIndex: 1 theGrandParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
Now, you are inside the ParamBlock of the sphere. The grand parent is the Sphere node itself, the parent is the sphere, the subAnim index is 1 and the animatable track is the Parameter Block. It does not have any keys, so you can go on and traverse its subAnim tracks that contain the animatable parameters of the Sphere
theAnimatable: undefined theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 1 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
This is the first subAnim of the ParamBlock, which is the Radius of the sphere. The radius of this sphere was not animated, so there is no controller assigned - theAnimatable parameter is passed as undefined.
$Sphere01[4][1] $Sphere01[4][1].controller --results: SubAnim:Radius undefined theAnimatable: Controller:Bezier_Float theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 2 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
This is the second subAnim of the ParamBlock, which is the Segments count of the sphere. The Segments of this sphere are animated, so there is a Bezier_Float controller assigned.
This following calls traverse the remaining tracks of the ParamBlock and of the Sphere itself, but do not find any controllers assigned - they all return undefined as theAnimatable:
theAnimatable: undefined theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 3 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 4 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 5 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: ReferenceTarget:ParamBlock theSubAnimIndex: 6 theGrandParent: Sphere theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 5 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 6 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theAnimatable: undefined theParent: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000] theSubAnimIndex: 7 theGrandParent: undefined theNode: $Sphere:Sphere01 @ [-40.683792,-17.994026,0.000000]
The test function always returns true. Now, that you know how it is being called, you can change it to perform actual filtering.
See Trackbar Filter Callback Function Examples for some ideas for filter functions including a way to limit the number of displayed keys in the trackbar to increase interaction speed with the 3ds Max UI.