Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Script to condense material ID

Script to condense material ID

Anonymous
Not applicable
6,050 Views
18 Replies
Message 1 of 19

Script to condense material ID

Anonymous
Not applicable

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?

0 Likes
Accepted solutions (1)
6,051 Views
18 Replies
Replies (18)
Message 2 of 19

miauuuu
Collaborator
Collaborator

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/
0 Likes
Message 3 of 19

Anonymous
Not applicable

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

0 Likes
Message 4 of 19

miauuuu
Collaborator
Collaborator

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

https://miauu-maxscript.com/
0 Likes
Message 5 of 19

Anonymous
Not applicable

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

0 Likes
Message 6 of 19

miauuuu
Collaborator
Collaborator

 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/
0 Likes
Message 7 of 19

Anonymous
Not applicable

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

 

--Unknow property: "materialList" in undefined

0 Likes
Message 8 of 19

miauuuu
Collaborator
Collaborator

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/
0 Likes
Message 9 of 19

Anonymous
Not applicable

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

 

 

0 Likes
Message 10 of 19

miauuuu
Collaborator
Collaborator

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/
0 Likes
Message 11 of 19

Anonymous
Not applicable

Sorry, nothing happen ...

 

test_04.png

0 Likes
Message 12 of 19

miauuuu
Collaborator
Collaborator

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/
0 Likes
Message 13 of 19

Anonymous
Not applicable

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?

0 Likes
Message 14 of 19

miauuuu
Collaborator
Collaborator

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

https://miauu-maxscript.com/
0 Likes
Message 15 of 19

Anonymous
Not applicable

How Can I share a fbx in this forums? 

0 Likes
Message 16 of 19

miauuuu
Collaborator
Collaborator

A link to gdrive, dropbox, etc.

https://miauu-maxscript.com/
0 Likes
Message 17 of 19

Anonymous
Not applicable

I test with wetransfer:

https://we.tl/t-bW7sIflPPN

 

 

0 Likes
Message 18 of 19

miauuuu
Collaborator
Collaborator
Accepted solution

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
Not applicable

Hi  miauuuu!

IT WORKS! Thanks you so much for your time!

It's a Monday that starts well 😉

0 Likes