How do I Sort a MultiMaterial By Material ID?

MAXScript Frequently Asked Questions

Since 3ds Max 4, material IDs can be specified independently from the sub-material order inside a MultMaterial. The material IDs can get messy after a long process of adding sub-materials. Especially when giving a scene to other people, it might be a good idea to reorder the sub-materials by sorting the Material IDs in ascending order for easier access.

The following function performs this operation using a simple bubble sort algorithm without using the built-in sort or qsort functions provided by MAXScript.

A bubble sort algorithm compares two values and switches their places when their order is not right. It repeats this process until no changes are required anymore. The name of the method is based on the fact that entries with low values tend to float up "to the surface" while higher values fall down "to the bottom".

The function sets a flag variable and repeats a while loop until the flag is set to true. The flag will be set to false whenever two materials have switched places denoting that the sorting is not over yet. Inside the while loop, a for loop will run through the sub-materials and compare pairs of neighbor Material ID values. When the current value is higher than the following one, then their IDs, the respective sub-materials, the names and the enable switches have to change places.

Script:

fn sortMultiSubById m =

(

if classof m == MultiMaterial then --make sure the material is MultiMaterial

(

local sorted = false --initialize a local variable as a sort status flag

while not sorted do --repeat until the flag is set to true

(

sorted = true --set the flag to true in the beginning

--loop though all sub-materials except the last one:

for i = 1 to m.numsubs-1 do

(

--if the MatID of the current sub-material is greater than the next one...

if m.materialIDList[i] != undefined and m.materialIDList[i+1] and m.materialIDList[i] > m.materialIDList[i+1] then

(

--store the current material in a temp. variable

tmp = m.materialList [i]

--copy the next material into the current one

m.materialList [i] = m.materialList[i+1]

--copy the current material into the next one using the temp var.

m.materialList[i+1] = tmp

--do the same with the material IDs

tmp = m.materialIDList[i]

m.materialIDList[i] = m.materialIDList[i+1]

m.materialIDList[i+1] = tmp

--then copy the states of the enable checkboxes

tmp = m.mapEnabled[i]

m.mapEnabled[i] = m.mapEnabled[i+1]

m.mapEnabled[i+1] = tmp

--and finally switch the places of the user-defined names.

tmp = m.names[i]

m.names[i] = m.names[i+1]

m.names[i+1] = tmp 

--set the flag to false as we switched places, ergo sorting goes on

sorted = false

)--end if 

)--end for

)--end while

)--end if

)--end fn

 

-- Sample usage:

sortMultiSubById $Box01.material

 

See also

MultiMaterial : Material

Frequently Asked Questions