Notifications
Clear all

[Closed] assigned material switch

Hi,

I’m trying to write a script to remove unused materials from the scene.
However I’m not able to find the “object_assigned” command anywhere in the manual.
the script should be something like this:


 for i =1 in sceneMaterials.count do
 (
 	foo = sceneMaterials[i].OBJECT--command?
 	 if foo == undefined then
 	 (
 		 sceneMaterials[i] = noMaterial
 	 )
  )	 
 	 --end loop
 

how can I find which object(s) have certain material assigned?
thanks.
~sion

5 Replies

If the material is unused (not applied to any object, and not in the material editor, for example) it will be removed automatically.

Hey dude thanks for the reply.
I’m aware of that, but I need to “illude” someone so to speak.
Plus, I seriously need the command, I can’t find it anywhere.
~sion

Well, the material is applied to the object: not the other way around. Because a material can be applied to multiple objects, there is no “material.object”.

You could iterate through all the objects in the scene and collect their materials in an array. 
That would be something like this (real quick messy code):

    theArray = #()
    
    for m in objects do
    (
    	if theArray.count == 0 then append theArray #(m.material, m)
    	else
    	(
    		findInArray = 0
    		
    		for x in 1 to theArray.count do
    		(
    			if (findItem theArray[x] m.material) != 0 then findInArray = x
    		)
    			
    		if findInArray == 0 then 
    		(
    			append theArray #(m.material, m)
    		)	
    		else
    		(
    			append theArray[findInArray] (m)
    		)
    	)
    )
    
    print theArray
    

This way you’d have an array of arrays, where array[x][1] would be the material and array[x][2 and higher] would be the objects that have this material.

And then you can compare scenematerials to the objects in this array. This seems a bit useless to me though: what is it that you want to accomplish exactly? Hope this helps you in the right direction.

I wouldn’t rely on <object>.material; what if the material you’re checking for is part of a Blend / Multi-sub material?

Better – but not perfect – would be using refs.dependents:


a = meditmaterials[1]
myMaterial:Standard
for o in objects where (o.material == a) collect ( o )
#($GeoSphere:GeoSphere01 @ [-60.000000,-0.000002,50.000000])
for o in (refs.dependents a) where ( isKindOf o GeometryClass ) collect ( o )
#($GeoSphere:GeoSphere01 @ [-60.000000,-0.000002,50.000000], $GeoSphere:GeoSphere02 @ [30.000000,-0.000003,60.000000])

or, in 2008+, use refs.dependentNodes:


refs.dependentNodes a
#($GeoSphere:GeoSphere01 @ [-60.000000,-0.000002,50.000000], $GeoSphere:GeoSphere02 @ [30.000000,-0.000003,60.000000])
 

However, that still means you may miss the material being used elsewhere – for example, in a renderer, volumetric effect, etc. refs.dependents does give the full output:


print (refs.dependents meditmaterials[1])
ReferenceTarget:ParamBlock2
ReferenceTarget:Render_Pass_Parameter_Block_Holder
ReferenceTarget:Brazil_Main_Renderer
ReferenceTarget:Brazil_TV_Node
ReferenceTarget:ReferenceTarget
Brazil_r_s_Pro_Beta_Edition_v2_0__build_16xx:Brazil_r_s_Pro_Beta_Edition_v2_0__build_16xx
Brazil_r_s_Pro_Beta_Edition_v2_0__build_16xx:Brazil_r_s_Pro_Beta_Edition_v2_0__build_16xx
RenderEnvironment:(null)
ReferenceTarget:Scene
ReferenceTarget:Material_Editor

But obviously there’s a bunch of fluff in there that you might want to ignore (such as ParamBlock2). A completely unassigned material gives (in 3ds Max 2009):


ReferenceTarget:Material_Editor
ReferenceTarget:Scene

The first one’s obvious, the second one points to a Scene reference – which itself contains, among other, the .medit_materials reference.

That turned up way more complicated than I thought.
In the material editor, there is “Select By Material” button, if there is no reflection of that button in maxscript it is quite absurd if you ask me.
Thank you guys a lot for the info I’ll have to examine your posts with a cup of coffee maybe I can write something.
~sion