getClassInstances

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.

processAllAnimatables:

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 .

target:

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.

asTrackViewPick:

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 .

processChildren:

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])

getClassCounts()

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()