[Closed] MAXScript: How to find duplicate texturemap names via maxscript?
I have a large scene that uses a huge number of texturemap (bitmap, mix, composite etc. etc.), but many different texturemap have the same name, although they are different texturemap (not instances). How can I find texturemap with duplicate names and assign a new name to such a texturemap?
I tried different methods using uniqueName, but this did not give the desired result – some texturemap are renamed again and still have the same names, although they are different texturemap. Is there some quick and reliable way to do this?
Here is one of the methods I tried, but it didn’t give the desired result:
here mapsArray – all texturemaps array from scene
fn renMapsName mapsArray = (
uniques = #()
dups = #()
for i in mapsArray where not (appendifunique uniques i.name) do (
appendIfUnique dups i
)
for n in dups do (
n.name=uniqueName n.name
)
)
renMapsName mapsArray
I don’t have a good scene to test it so can’t really tell how bad it performs cause it renames all the maps that share same base name whenever two of them have duplicate names.
keys = #()
textures = #()
duplicates = #{}
base_keys = #()
base_textures = #()
for tex_class in textureMap.classes do
(
for tex in getClassInstances tex_class do
(
key = toLower tex.Name
index = findItem keys key
if index > 0 then
(
append textures[ index ] tex
duplicates[ index ] = true
)
else
(
append keys key
textures[ keys.Count ] = #( tex )
)
base_key = trimRight key "0123456789"
base_index = findItem base_keys base_key
if base_index > 0 then
(
append base_textures[ base_index ] tex
)
else
(
append base_keys base_key
base_textures[ base_keys.Count ] = #( tex )
)
)
)
for index in duplicates do
(
base_name = toLower (trimRight textures[ index ][1].Name "0123456789")
j = findItem base_keys base_name
i = 0
for tex in base_textures[ j ] do
(
tex.Name = base_name + (formattedPrint (i += 1) format:"03d")
)
)
Thanks Serejah, but your method is renaming ALL texturemaps from scene, but it is necessary that only those that have the same names are renamed.
For example, there is a Fallow texturemap named “Map # 001” that contains two texturemap with the same names “Map # 001”. After processing, these two maps should be assigned new names (ie “Map # 002” and “Map # 003”). Other texturemaps that already have unique names do not need to be renamed.
Thanks again!
No, it doesn’t rename all texturemaps.
What it does, it finds all texturemaps than have same name prefix and rename these maps. It discards numbers suffix and rename maps staring from 001 to the end.
Example:
mAp #001 -- name prefix 'map #'
MAP #535 -- name prefix 'map #'
map #855393 -- name prefix 'map #'
mAp #001 -- duplicate name, name prefix 'map #'. All maps starting with 'map #' will be renamed
Smoke #42 -- name prefix 'Smoke #', not going to be renamed
and the result:
map #001
map #002
map #003
map #004
Smoke #42
Maybe it is better to collect all the scene maps names and then find a new name for each duplicate that doesn’t collide with the rest of the existing names. Instead of renaming all the maps sharing the same prefix.
No, no. There is no need to search for texturemaps only by prefix, since many maps will have the same prefix, but the suffix will be different, which means they are already different names. It is necessary to rename only those texmaps that have completely identical names along with the prefix and suffix.
Actually Max has a method to rename maps, but for some reason it always increments map suffixes
details
just a quick demo:
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
rename = g.coreinterface14.AssignNewName
textures = #()
for tex_class in textureMap.classes do
(
join textures (getClassInstances tex_class)
)
for tex in textures do
(
anim = g.animatable.getanimbyhandle (dotNetObject "system.uintptr" (getHandleByAnim tex))
rename anim
)
This is probably correct in order to create a unique name. It seems to me that assignNewName not only changes the name, but also copies the map, which in this case does not need to be done.
So I think it’s better to use uniqueName for renaming.
No problem to rename. The problem is to find and rename only those texmaps that have identical names but are not instances.
you can collect all texmaps with the same name and then make unique array to discard instances. Or better use appendIfUnique when filling textures array
keys = #()
textures = #()
duplicates = #{}
for tex_class in textureMap.classes do
(
for tex in getClassInstances tex_class do
(
key = toLower tex.Name
index = findItem keys key
if index > 0 then
(
append textures[ index ] tex
duplicates[ index ] = true
)
else
(
append keys key
textures[ keys.Count ] = #( tex )
)
)
)
for index in duplicates do
(
unique_duplicates = makeUniqueArray textures[ index ]
if unique_duplicates.count > 1 do
(
map_name = unique_duplicates[1].Name
base_name = trimRight map_name "0123456789"
num_digits = map_name.Count - base_name.Count
num = (substring map_name (1 + base_name.Count) num_digits) as integer
format_string = "0" + num_digits as string + "d"
i = num
for j = 2 to unique_duplicates.Count do
(
-- replace below code with something like: new_name = MakeUniqueTexmapName base_name keys
new_name = base_name + (formattedPrint (i += 1) format:format_string)
-- to do: check that this new name isn't used by any texmap or mtl and make a new one if it does
unique_duplicates[j].Name = new_name
-- to do: append new name to the array of used names i.e. append keys (tolower new_name)
)
)
)
Thank you so much Serejah! I will try this. It looks like your code should work as expected.
Hi Serejah!
I tested your code on several large scenes with maps with the dublicate names and found that some maps were given new names that other maps already have.
How can I prevent the duplication of new names assigned to maps?
Thank!