Community
3ds Max Programming
Welcome to Autodesk’s 3ds Max Forums. Share your knowledge, ask questions, and explore popular 3ds Max SDK, Maxscript and Python topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Script to condense material ID

18 REPLIES 18
SOLVED
Reply
Message 1 of 19
Anonymous
5008 Views, 18 Replies

Script to condense material ID

Hi all!

 

I'm a 3D artist (I don't know scripting unfortunetly) and I search a script to condense ID of multi/subobject material which share the same name material.

 

I found this script via scriptspot:

http://www.scriptspot.com/forums/3ds-max/scripts-wanted/req-material-id-condense-by-part-of-material...

 

pattern = "*woo*"
mtl = -- your multi-material goes here
mtls = mtl.materialList
mat = undefined
for i=1 to mtls.count where mtls[i] != undefined do (    
    if matchPattern mtls[i].name pattern:pattern do (        
        if mat == undefined then mat = mtls[i] else (        
            if mat != mtls[i] do mtls[i] = mat
        )
    ) 
)

 

but I have a error message:

--Unknow property: "materialList" in undefined

 

 Someone can help me to make this script work please?

18 REPLIES 18
Message 2 of 19
miauuuu
in reply to: Anonymous

Select some objects and run the code below. The script will check each of the selected object and if the object have multimaterial applied it will condense the IDs

 

(
    selObjsArr = selection as array
    if selObjsArr.count != 0 then
    (
        pattern = "*woo*"
        for o in selObjsArr do
        (                        
            if classOf (mtl = o.material) == Multimaterial do
            (
                mtls = mtl.materialList
                mat = undefined
                for i=1 to mtls.count where mtls[i] != undefined do
                (    
                    if matchPattern mtls[i].name pattern:pattern do
                    (        
                        if mat == undefined then mat = mtls[i] else
                        (
                            if mat != mtls[i] do mtls[i] = mat
                        )
                    )
                )
            )
        )
    )
    else
        messagebox "Empty selection" title:""
)

 

https://miauu-maxscript.com/
Message 3 of 19
Anonymous
in reply to: miauuuu

Hi Miauuu,

 

Thanks for your answer!

I tested it this morning but I have this error message.

 

2018-10-26 08_44_58-map_niveau_03_00.max - Autodesk 3ds Max 2018.png

Message 4 of 19
miauuuu
in reply to: Anonymous

Remove lines 1, 3 and 33 and then execute the code. The real code is between line 5 and 31.

https://miauu-maxscript.com/
Message 5 of 19
Anonymous
in reply to: miauuuu

Ok miauuu, thanks for your indulgence.

I test it but nothing happen, maybe I forget something ...

 

This is how I proceed:

- select my mesh

- Open the script

- Run the script

 

 

2018-10-26 16_50_36-C__Program Files_Autodesk_3ds Max 2018_scripts_condense_ID_05.ms - MAXScript.png

Message 6 of 19
miauuuu
in reply to: Anonymous

 The script works using a pattern for the name of the materials that will be condensed. Currently the pattern is "*woo*". Maybe you have to edit it to fit your needs.

https://miauu-maxscript.com/
Message 7 of 19
Anonymous
in reply to: miauuuu

I try but when I put the name of my material I have this error message:

 

--Unknow property: "materialList" in undefined

Message 8 of 19
miauuuu
in reply to: Anonymous

You have to replace only this line:

 

pattern = "*woo*"

 

with the name of your material. For example

 

pattern = "*glass*"

 

so when the script find a submaterials with names that contain word glass it will condense their IDs.

 

 

https://miauu-maxscript.com/
Message 9 of 19
Anonymous
in reply to: miauuuu

Ok, I retry but I'm sorry, I can't make it work T_T

 

The name of my multimaterial is:

Material #348600

The name of my material is:

Material__304649

 

I made few test ...

test_01test_01test_02test_02test_03test_03

 

 

Message 10 of 19
miauuuu
in reply to: Anonymous

Use the code that I post. I

You use the code incorrectly. The mtl variable is set incorrectly.

Try this:

[code]

(
    selObjsArr = selection as array
    if selObjsArr.count != 0 then
    (
        pattern = "*Material__304649*"
        for o in selObjsArr do
        (                        
            if classOf (mtl = o.material) == Multimaterial do
            (
                mtls = mtl.materialList
                mat = undefined
                for i=1 to mtls.count where mtls[i] != undefined do
                (    
                    if matchPattern mtls[i].name pattern:pattern do
                    (        
                        if mat == undefined then mat = mtls[i] else
                        (
                            if mat != mtls[i] do mtls[i] = mat
                        )
                    )
                )
            )
        )
    )
    else
        messagebox "Empty selection" title:""
)

[/code]

 

As you can see in my code the mtl varibale holds the material of the object:

 

mtl = o.material

https://miauu-maxscript.com/
Message 11 of 19
Anonymous
in reply to: miauuuu

Sorry, nothing happen ...

 

test_04.png

Message 12 of 19
miauuuu
in reply to: Anonymous

The name of your material is Material__304649, but what are the naems of submaterials?

The script check the names of the sumbaterials, not the name of the "main multiSubobject" material. So, for example you have an object with name object_01 and with applied Multimaterial with name Material__304649. It have 5 submaterials with names:

glass_01

wood_03

glass02

stone

in_glass

 

If you want all submaterials that contains "glass" in its names to be condensed select the object_01 and run this:

 

(
    selObjsArr = selection as array
    if selObjsArr.count != 0 then
    (
        pattern = "*glass*"
        for o in selObjsArr do
        (                        
            if classOf (mtl = o.material) == Multimaterial do
            (
                mtls = mtl.materialList
                mat = undefined
                for i=1 to mtls.count where mtls[i] != undefined do
                (    
                    if matchPattern mtls[i].name pattern:pattern do
                    (        
                        if mat == undefined then mat = mtls[i] else
                        (
                            if mat != mtls[i] do mtls[i] = mat
                        )
                    )
                )
            )
        )
    )
    else
        messagebox "Empty selection" title:""
)

 

The script should condense those materials:

glass_01, glass02 and in_glass

becaue all of them have "glass" in their names.

 

https://miauu-maxscript.com/
Message 13 of 19
Anonymous
in reply to: miauuuu

Sorry I'm probably poorly expressed but this is a picture of what I want to do (in a multi/subobject material)

 

ID.pngThis is not possible?

Message 14 of 19
miauuuu
in reply to: Anonymous

Maybe it is better to uplad this material so we can download it use it to modify the script.

https://miauu-maxscript.com/
Message 15 of 19
Anonymous
in reply to: miauuuu

How Can I share a fbx in this forums? 

Message 16 of 19
miauuuu
in reply to: Anonymous

A link to gdrive, dropbox, etc.

https://miauu-maxscript.com/
Message 17 of 19
Anonymous
in reply to: miauuuu

I test with wetransfer:

https://we.tl/t-bW7sIflPPN

 

 

Message 18 of 19
miauuuu
in reply to: Anonymous

Try this:

 

global CondenseMaterialIDs
try(destroyDialog CondenseMaterialIDs)catch()
rollout CondenseMaterialIDs "Condense Material IDs"
(
	local collapseBy = "Name"
	local poSetFaceMatID = polyOp.setFaceMatID
	
	radioButtons CollapseByRadioButtons "Collapse By:" labels:#("Name", "Diffuse Texture Name") default:1
	
	on CollapseByRadioButtons changed state do
	(
		collapseBy = case CollapseByRadioButtons.state of
		(
			1: "Name"
			2: "TextureName"
			default: "Name"
		)
	)
	
	fn getTextureName mat =
	(
		local textureName = mat.name
		try
		(
			diffuseTextureMap = mat.diffusemap
-- 			print (classof diffuseTextureMap)
			if classof diffuseTextureMap == Bitmaptexture do
			(
				textureName = getFileNameFile diffuseTextureMap.bitmap.filename
			)
		)
		catch()
		textureName
	)
	
	button CondenseMaterialIDsButton "Condense Material IDs"
	
	on CondenseMaterialIDsButton pressed do
	(
		setWaitCursor()
		sel = selection as array
		for obj in sel where classof obj == Editable_Poly  and obj.material != undefined and classof obj.material == MultiMaterial do
		(
-- 			for originalMaterial in obj.material.materialList do
-- 			(
-- 				print (getTextureName originalMaterial)
-- 			)
			materialIDList = obj.material.materialIDList
			materialMap = #()
			append materialMap (findItem materialIDList 1)
			materialList = #(obj.material.materialList[materialMap[1]])
			for i = 2 to materialIDList.count do
			(
				index = (findItem materialIDList i)
				mat = obj.material.materialList[index]
				notFound = true
				newIndex = 0
				for j = 1 to materialList.count while notFound do
				(
					otherMat = materialList[j]
					if collapseBy == "Name" then
					(
						if mat.name == otherMat.name do 
						(
							notFound = false
						)
					)
					else 
					(
						if collapseBy == "TextureName" do
						(
							if (getTextureName mat) == (getTextureName otherMat) do
							(
								notFound = false
							)
						)
					)
					if not notFound do 
					(
						newIndex = j
					)
				)
				if notFound do
				(
					append materialList mat
					newIndex = materialList.count
				)
				append materialMap newIndex;
			)
			
			if materialList.count != obj.material.materialList.count do
			(
				newMat = MultiMaterial numSubs:materialList.count
				materialFaces = #()
				for i = 1 to newMat.materialList.count do
				(
					newMat.materialList[i] = materialList[i]
					newMat.materialIDList[i] = i
					newMat.names[i] = materialList[i].name
					append materialFaces #()
				)
				obj.material = newMat
				for i = 1 to obj.GetNumFaces() do
				(
					oldMaterialID = obj.GetFaceMaterial i
					oldMaterialIndex = findItem materialIDList oldMaterialID
					newMaterialID = materialMap[oldMaterialIndex]
					if oldMaterialID != newMaterialID do
					(
						append materialFaces[newMaterialID] i
					)
				)
				
				for i = 1 to materialFaces.count where materialFaces[i].count > 0 do
				(
					poSetFaceMatID obj materialFaces[i] i
				)				
			)
		)
		setArrowCursor()
	)
)
createDialog CondenseMaterialIDs

The original script is here: http://www.scriptspot.com/3ds-max/scripts/material-id-condense

I have made some little modification and now it is run as standard rollout, not as utility.

Works only with editable poly objects, so you have to convert your objects to editable poly.

The object you have uploaded starts with 120 sub-materials. After the script is used only 40 sub-materials remains.

https://miauu-maxscript.com/
Message 19 of 19
Anonymous
in reply to: miauuuu

Hi  miauuuu!

IT WORKS! Thanks you so much for your time!

It's a Monday that starts well 😉

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report