To understand the way the filter function callback works, you can register a test function to explore the argument passed by the callback:
If you select for example a Sphere scene node called "Sphere01", the callback will traverse all its sub-anim tracks and call the function multiple times. The function will print all arguments to the Listener.
Let's 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 has been 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 we go one level deeper: The grand parent is the Sphere, the parent is 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 we 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 we 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 3 calls will traverse 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]
We 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 which 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]
We are 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 we 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 we can go on and traverse its subAnim tracks which 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 have been 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]
Our test function always returns true. Now that we know how it is being called, we could change it to perform actual filtering.
See Trackbar Filter Callback Function Examples for some ideas for filter functions incl. a way to limit the number of displayed keys in the trackbar to increase interaction speed with the 3ds MaxUI.