Exploring the Trackbar Filter Callback Functions

To understand the way the filter function callback works, you can register a test function to explore the argument passed by the callback:

Script:

fn testCallbackFilterFunction theAnimatable theParent theSubAnimIndex theGrandParent theNode = (

format "theAnimatable: %\n" theAnimatable

format "theParent: %\n" theParent

format "theSubAnimIndex: %\n" theSubAnimIndex

format "theGrandParent: %\n" theGrandParent

format "theNode: %\n\n" theNode

true ) --always returns true, means show all keys

fn testCallbackAdditionFunction arg1 arg2 = (true)

theInterface = maxOps.trackbar

theIndex = theInterface.registerFilter testCallbackFilterFunction callbackAdditionFunction "Test Filter" 8 active:true stopTraversal:false

 

 

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 4th subAnim index which is the Sphere object.

Try this in the Listener:

$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.

Compare to the Listener:

$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!

Compare to the Listener:

$Sphere01[4][2]

$Sphere01[4][2].controller

--results:

SubAnim:Segments

Controller:Bezier_Float

 

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 Max UI.

See also

Trackbar Filter Callback Function Examples

Trackbar Interface