As an alternative to using named property accesses, you can access in an object any animatable property that is visible as a track in Track View by indexing the 3ds Max object value as though it were an array.
This simplifies such tasks as iterating over all the animatable properties in an object and accessing sub-controllers that don't have unique names, such as within list controllers.
Properties
<maxwrapper_object>.numSubs : Integer, read-only
Yields the number of accessible sub-animatables, or tracks, in an object. This is the number of immediate children subAnims, and may include as yet invisible tracks in the track view, such as visibility tracks on a node or yet-to-be animated vertices in an FFD. This property operates on any MAXWrapper subclass.
Methods
getSubAnimName <maxwrapper_object> <index> [asString:<bool>] [localizedName:<bool>]
Returns the name of the indexed subAnimin the supplied MAXWrapper.
If the optional asString
keyword is supplied and set to true
, the name is returned as a string. If false
or not specified, a Name Value is returned.
When the localizedName
keyword parameter is true
(the default), the name as it appears in the UI is returned. Otherwise the non-localized name is returned. Available in in 3ds Max 2022 and later
getSubAnimNames <maxwrapper_object> [localizedNames:<bool>]
Returns an array of names in subAnim index order.
When the localizedNames
keyword parameter is true
(the default), the names as they appear in the UI is returned. Otherwise the non-localized names are returned. Available in in 3ds Max 2022 and later
getSubAnim <maxwrapper_object> <index>
Returns the indexed subAnim. See the index operator below.
Operators
<maxwrapper_object>[<index_number>|<subanim_name>]
Returns the subAnim with the specified index or name. You can apply the index operator, [<index_number>]
, to any MAXWrapper object (nodes, modifiers, controllers, materials, etc.) to access a numbered subAnim.
FOR EXAMPLE:
for i in 1 to $foo.numSubs do print $foo[i] -- iterate them $bar.position.controller[3] -- third subAnim in a position list controller ffd_mod[i].value -- position of i'th FFD control point
You cannot set subAnims with the index operator, this is a read-only access.
In place of an index, you can also use a subanim name. It can be any expression that yields a string or name value. So, whereas in releases prior 3ds Max 4, getting at the position subAnim in a node require you to remember index 3 for the transform subanim and 1 for its position subanim, in other words
$foo[3][1] -- position within transform within node
you can use instead:
$foo[#transform][#position]
The names you can use are those seen in the track view or retrieved with the functions getSubAnimName()
or getSubAnimNames().
MAXScript defines a SubAnim
class, instances of which provide a general representation for sub-animatables. Whenever you use the index operator on a 3ds Max object, it returns a SubAnim instance.
FOR EXAMPLE:
$box01[3] -> SubAnim:Transform
The third subAnim in a node is typically the transform track.
Properties
<subAnim>.name : String, read-only
Returns the name of the track subAnim as shown in TrackView.
<subAnim>.parent : Node, read-only
Returns the true owner of the subAnim.
The true object owning the subAnim can be different than what was originally specified when creating the subAnim, and MAXScript automatically hides certain types of subAnims, automatically promoting the subAnims within them.
FOR EXAMPLE:
s=sphere() sa = s.baseobject[1] --> SubAnim:Radius sa.parent --> ReferenceTarget:ParamBlock sa.index --> 1 --The actual owner of the Radius subAnim is the sphere's parameter block.
<subAnim>.index : Integer, read-only
Returns the index of the subAnim.
<subAnim>.value : Value
The current value of the track subAnim, equivalent to <controller>.value
. Returns undefined
if no appropriate value exists or the track has not yet been assigned a controller. The .value
property yields the value at the current MAXScript time. You can assign to this value to set the track's value at that time.
<subAnim>.controller : Controller
The controller for the track SubAnim. Returns undefined
if a controller has not yet been assigned or if the SubAnim is not animatable. You can assign a new controller to a track by assigning to the .controller
property of its subAnim.
<subAnim>.keys : KeyArray, read-only
Yields the key array for that track or undefined
if not keyable or a controller has not yet been assigned. This property is read-only.
<subAnim>.isAnimated : Boolean, read-only
Yields true
if there is an animated controller present. This property is read-only.
<subAnim>.object : MAXWrapper, read-only
Yields the subAnim object, or undefined
if not assigned. This property is read-only. The .object
property may return any kind of MAXWrapper object, depending on what the parent object decides to put there. For example, <node>[1].object
is the visibility controller or undefined
if not yet assigned, <node>[2].object
contains the bindings of any space warps bound to the node, or undefined
if none have been bound, <node>[3].object
is the transform controller, <node>[4].object
is the node's object, either the modified object if there are modifiers present or the base object if not, <node>[5].object
is the material assigned to the node or undefined
if no material has been assigned, and <node>[6].object
is the Image Motion Blur Multiplier controller or undefined
if not yet assigned.
EXAMPLE
b = box() b[4].object -- returns a reference to the Box base object
<subAnim>.numSubs : Integer, read-only
The number of immediate subAnim children.
If you attempt to access subAnim properties, such as .value
, .numSubs
, .category
, etc., on certain subAnims that had yet to be assigned controllers, such as scene node visibility tracks, these properties return null values such as 0, or undefined
, as appropriate.
Methods
getSubAnim <subAnim> <index>
Returns the indexed subAnim. See the index operator below.
Operators
<subAnim>[<index_number>]
Returns the indexed subAnim. You can work down through nested subAnims (nested tracks) by indexing into subAnims themselves.
EXAMPLE
$box01[3][2]
yields the rotation track subAnim since
[3] is always the transform track and the second track in it is always the rotation track. Indexing a SubAnim always yields another SubAnim. For those familiar with SubAnims in the 3ds Max SDK, it should be noted that MAXScript SubAnims descend automatically through 'hidden' subAnim levels, reflecting the structure seen in Track View.
You can get at the base object's Track View parameters by indexing into the base object:
b=box()
getSubAnimNames b[4] -- returns #(#length, #width, #height, ...)
b[4][2].value -- returns current width value
i = 3
b[4][i].controller = float_list() -- assign height controller