The getClassInstances function available in 3ds Max 7 and higher returns an array of all instances of a specified class that exist in a scene.
It was previously available through the Avguard DLX 3rd party MAXScript extension.
Until 3ds Max 2011, the function was looking for the class instances by enumerating the animatable tree. There are many cases where the subAnims of an object are a subset of the references held by an object, so instances present in the scene were being missed.
Starting with 3ds Max 2011, getClassInstances()
can search for class instances in a variety of ways depending on its arguments, including the two new ones: processAllAnimatables:
and processChildren:
.
The syntax is:
getClassInstances <MAXClass> processAllAnimatables:<boolean> target:<MAXObject> asTrackViewPick:<boolean> processChildren:<boolean>
<MAXClass>
specifies the class whose instances are being searched for.
If processAllAnimatables:true
is specified in 3ds Max 2011 or higher, all existing objects, even those not present in the scene, are tested to see if they are instances of the specified class. These objects include, for example, objects held only by MAXscript values.
When processAllAnimatables:true
is specified, no other keyword parameters are applicable and are ignored.
The default value for this parameter is false
.
If target
: is specified, only the hierarchy for that target is searched.
If target
: is not specified, the entire scene under the scene root is searched. The scene in this case refers not only to the node hierarchy, but also the Material Editor, Track View, and others.
If asTrackViewPick:true
is specified, each use of a class instance is returned as a TrackViewPick value.
If asTrackViewPick:true is specified, the hierarchy that is searched is the Animatable tree under the target. There are lots of cases where the subAnims of an object are a subset of the references held by an object, so class instances present in the scene might be missed. The Animatable tree is the tree shown in TrackView.
If asTrackViewPick:false
is specified or not supplied, each class instance is returned, and the hierarchy that is searched is the Reference tree under the target.
The default value for this parameter is false
.
If processChildren:true
is specified in 3ds Max 2011 or higher, children scene nodes are also searched as part of the Animatable or Reference hierarchy.
The default value for this parameter is false
unless no target is specified, the scene root node (rootNode) is specified, or the scene root (rootScene) is specified, in which case the default is true
.
EXAMPLE
--Create two spheres, and an instance of one of the spheres: resetMaxFile #noPrompt s1 = sphere() s2 = sphere pos:[100,0,0] s3 = instance s1 s3.pos = [-100,0,0]
OUTPUT:
OK $Sphere:Sphere01 @ [0.000000,0.000000,0.000000] $Sphere:Sphere02 @ [100.000000,0.000000,0.000000] $Sphere:Sphere03 @ [0.000000,0.000000,0.000000] [-100,0,0]
EXECUTE:
tvps=getClassInstances sphere asTrackViewPick:true for tvp in tvps do ( print tvp.anim print tvp.client print tvp.subNum print tvp.name print tvp.client[tvp.subNum] )
OUTPUT:
#(TrackViewPick:"Object (Sphere)", TrackViewPick:"Object (Sphere)", TrackViewPick:"Object (Sphere)") Sphere $Sphere:Sphere001 @ [0.000000,0.000000,0.000000] 4 "Object (Sphere)" SubAnim:Object__Sphere Sphere $Sphere:Sphere002 @ [100.000000,0.000000,0.000000] 4 "Object (Sphere)" SubAnim:Object__Sphere Sphere $Sphere:Sphere003 @ [-100.000000,0.000000,0.000000] 4 "Object (Sphere)" SubAnim:Object__Sphere OK
NOW EXECUTE:
objs=getClassInstances sphere for obj in objs do print (refs.dependents obj) #nomap
OUTPUT:
#(Sphere, Sphere) #($Sphere:Sphere003 @ [-100.000000,0.000000,0.000000], $Sphere:Sphere001 @ [0.000000,0.000000,0.000000], ReferenceTarget:NodeRefMgr) #($Sphere:Sphere002 @ [100.000000,0.000000,0.000000]) OK
CONCLUSION:
As one of the spheres is instanced, three TrackViewPick values are returned, but only two class instances are returned.
EXPLORING ARGUMENT COMBINATIONS:
t1 = bitmaptex filename:"t1.bmp" name:#Sphere_DiffuseMap t2 = bitmaptex filename:"t2.bmp" name:#Teapot_DiffuseMap t3 = bitmaptex filename:"t3.bmp" name:#Displace t4 = bitmaptex filename:"t4.bmp" name:#VolSelect t5 = bitmaptex filename:"t5.bmp" name:#HairDens t6 = bitmaptex filename:"t6.bmp" name:#NoWhere t7 = bitmaptex filename:"t7.bmp" name:#MEdit t8 = bitmaptex filename:"t8.bmp" name:#NodeCustAttrib t9 = bitmaptex filename:"t9.bmp" name:#ObjCustAttrib s = sphere material:(standard showInViewport:true) t = teapot material:(standard showInViewport:true) pos:[0,50,0] parent:s s.material.diffusemap = t1 s.material.specularmap = t1 t.material.diffusemap = mix mask:t2 addModifier s (displace map:t3 strength:10) addModifier t (volumeSelect texture:t4) addModifier s (HairMod()) s.modifiers[1].maps[1] = t5 s.modifiers[1].mapEnables[1] = true meditmaterials[1] = t7 g=geosphere() testCADef = attributes testCA ( parameters main ( map type:#texturemap ) ) CustAttributes.add g testCADef BaseObject:false CustAttributes.add g testCADef BaseObject:true g.testCA.map = t8 g.baseobject.testCA.map = t9
OUTPUT:
Sphere_DiffuseMap:Bitmap Teapot_DiffuseMap:Bitmap Displace:Bitmap VolSelect:Bitmap HairDens:Bitmap NoWhere:Bitmap medit:Bitmap NodeCustAttrib:Bitmap ObjCustAttrib:Bitmap $Sphere:Sphere001 @ [0.000000,0.000000,0.000000] $Teapot:Teapot001 @ [0.000000,50.000000,0.000000] Sphere_DiffuseMap:Bitmap Sphere_DiffuseMap:Bitmap Mix:Mix OK OK OK HairDens:Bitmap true medit:Bitmap $GeoSphere:GeoSphere001 @ [0.000000,0.000000,0.000000] <AttributeDef:testCA> true true NodeCustAttrib:Bitmap ObjCustAttrib:Bitmap
TEST 1:
for b in getClassInstances bitmaptex do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 1 OUTPUT
Name : medit, Texture --> Name : t7.bmp , Affected Nodes : #() Name : Sphere_DiffuseMap, Texture --> Name : t1.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Teapot_DiffuseMap, Texture --> Name : t2.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : VolSelect, Texture --> Name : t4.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Displace , Texture --> Name : t3.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : HairDens, Texture --> Name : t5.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : ObjCustAttrib, Texture name : t9.bmp, Affected Nodes : #() Name : NodeCustAttrib, Texture name : t8.bmp, Affected Nodes : #($GeoSphere:GeoSphere001 @ [0.000000,0.000000,0.000000])
TEST 2
for b in getClassInstances bitmaptex target:rootnode do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 2 OUTPUT
Name : VolSelect, Texture --> Name : t4.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Teapot_DiffuseMap, Texture --> Name : t2.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Displace, Texture --> Name : t3.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : HairDens, Texture --> Name : t5.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture --> Name : t1.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : ObjCustAttrib, Texture name : t9.bmp, Affected Nodes : #() Name : NodeCustAttrib, Texture name : t8.bmp, Affected Nodes : #($GeoSphere:GeoSphere001 @ [0.000000,0.000000,0.000000])
TEST 3
for b in getClassInstances bitmaptex target:s do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 3 OUTPUT
Name : Displace, Texture --> Name : t3.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : HairDens, Texture --> Name : t5.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture --> Name : t1.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000])
TEST 4
for b in getClassInstances bitmaptex target:s processChildren:true do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 4 OUTPUT
Name : VolSelect, Texture --> Name : t4.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Teapot_DiffuseMap, Texture --> Name : t2.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Displace, Texture --> Name : t3.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : HairDens, Texture --> Name : t5.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture --> Name : t1.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000])
TEST 5
for b in getClassInstances bitmaptex target:g do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 5 OUTPUT
Name : ObjCustAttrib, Texture name : t9.bmp, Affected Nodes : #() Name : NodeCustAttrib, Texture name : t8.bmp, Affected Nodes : #($GeoSphere:GeoSphere001 @ [0.000000,0.000000,0.000000])
TEST 6
for b in getClassInstances bitmaptex processAllAnimatables:true do format "Name : %, Texture name : %, Affected Nodes : %\n" b.name b.filename (refs.dependentNodes b)
TEST 6 OUTPUT
Name : Sphere_DiffuseMap, Texture --> Name : t1.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Teapot_DiffuseMap, Texture --> Name : t2.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : Displace, Texture --> Name : t3.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : VolSelect, Texture --> Name : t4.bmp, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : HairDens, Texture --> Name : t5.bmp, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : NoWhere, Texture --> Name : t6.bmp, Affected Nodes : #() Name : medit, Texture --> Name : t7.bmp, Affected Nodes : #() Name : ObjCustAttrib, Texture name : t9.bmp, Affected Nodes : #() Name : NodeCustAttrib, Texture name : t8.bmp, Affected Nodes : #($GeoSphere:GeoSphere001 @ [0.000000,0.000000,0.000000])
TEST 7
for b in getClassInstances bitmaptex asTrackViewPick:true do format "Name : %, Texture name : %, Client: %, subAnim: %, Affected Nodes : %" b.anim.name b.anim.filename b.client b.subnum (refs.dependentNodes b.anim)
TEST 7 OUTPUT
Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 4 , Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 6 , Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Teapot_DiffuseMap, Texture name : t2.bmp, Client: Mix:Mix, subAnim: 4, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000]) Name : medit, Texture name : t7.bmp, Client: #meditMaterials(), subAnim: 1, Affected Nodes : #() Name : Displace, Texture name : t3.bmp, Client: Displace:Displace, subAnim: 3, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000])
TEST 8
for b in getClassInstances bitmaptex target:s asTrackViewPick:true do format "Name : %, Texture name : %, Client: %, subAnim: %, Affected Nodes : %\n" b.anim.name b.anim.filename b.client b.subnum (refs.dependentNodes b.anim)
TEST 8 OUTPUT
Name : Displace, Texture name : t3.bmp, Client: Displace:Displace, subAnim: 3 , Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 4 , Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 6 , Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000])
TEST 9
for b in getClassInstances bitmaptex target:s processChildren:true asTrackViewPick:true do format "Name : %, Texture name : %, Client: %, subAnim: %, Affected Nodes : %\n" b.anim.name b.anim.filename b.client b.subnum (refs.dependentNodes b.anim)
TEST 9 OUTPUT
Name : Displace, Texture name : t3.bmp, Client: Displace:Displace, subAnim: 3, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 4, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Sphere_DiffuseMap, Texture name : t1.bmp, Client: ReferenceTarget:ReferenceTarget, subAnim: 6, Affected Nodes : #($Object:Sphere001 @ [0.000000,0.000000,0.000000]) Name : Teapot_DiffuseMap, Texture name : t2.bmp, Client: Mix:Mix, subAnim: 4, Affected Nodes : #($Editable_Mesh:Teapot001 @ [0.000000,50.000000,0.000000])
The getClassCounts()
function, available in 3ds Max 2018 and higher, returns array of DataPair instances, where v1 is a maxclass and v2 is the number of instances of the corresponding class that exist in the scene. The syntax is:
<array of datapair(maxclass,count)>getClassCounts()