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:
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?
Solved! Go to Solution.
Solved by miauuuu. Go to Solution.
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:"" )
Remove lines 1, 3 and 33 and then execute the code. The real code is between line 5 and 31.
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
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.
I try but when I put the name of my material I have this error message:
--Unknow property: "materialList" in undefined
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.
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_01
test_02
test_03
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
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.
Sorry I'm probably poorly expressed but this is a picture of what I want to do (in a multi/subobject material)
This is not possible?
Maybe it is better to uplad this material so we can download it use it to modify the script.
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.
Can't find what you're looking for? Ask the community or share your knowledge.