Notifications
Clear all

[Closed] Changing Texture File Names

Hi, I work with many people and our team has issue with texture file names. We would like the texture file names to follow the object names.

For example, we have 100 objects in the scene. Each object has diffuse texture with different file name:

  • Object001 —> DiffuseTexA.jpg
  • Object002 —> BDiffMapOK.jpg
  • Object003 —> TexNormalYes.jpg
  • And so on and so forth…

What we want is to change the diffuse texture file names, to follow the object names. For example:

  • Object001 —> Object001.jpg
  • Object002 —> Object002.jpg
  • Object003 —> Object003.jpg
  • And so on and so forth…

Is it possible to do this from 3ds Max? I spent days to solve this through MaxScript, but still cannot find the answer (I don’t know MaxScript too well). I attached a 3ds Max file, that I used for testing.

16 Replies

how do you collect texture names for selected objects?

1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

I don’t collect texture file names from selected objects, because I don’t know how to do it.
But I can collect all texture file names:

mMaps = getClassInstances bitmaptexture

for m in mMaps do
(
fName = getFileNameFile m.filename
)

1st thing – you have to collect textures for selection

	for s in selection do		
	(
		uniquebitmaps = #()
		if s.material!=undefined then
		(
			bitmaps=getClassInstances Bitmaptexture target:s.material
			for i=1 to bitmaps.count do if (doesfileexist (mapPaths.getFullFilePath bitmaps[i].filename)) then
			(
				if (finditem uniquebitmaps bitmaps[i].filename)==0 then append uniquebitmaps bitmaps[i].filename
			)
		)
		print uniquebitmaps
	)
1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

Yes, it just collects textures of the selected objects. I found the solution, but this will not work for objects that use the same texture file. If all selected objects use different texture files, the code will work:

for i = 1 to selection.count do
	(
		fileName = selection[i].material.diffuseMap.filename
		newFilename = getFilenamePath fileName + selection[i].name + getFilenameType fileName
		if renameFile fileName newFilename then theMaps[i].filename = newFilename
	)

I hope someone can help me to improve this? What I need to improve is:
“If some of the selected objects have the same texture file, do not change the texture file name”

the code should not be complicated but we need to know a scenario… you have to design it.
for example:

select all nodes that have to give their name to a texture

find material of every selected node

if it’s a standard material and has diffuse map and diffuse map is bitmaptexture

set texture filename the same as node name

if texture filename is already taken by another node (shared texture) don’t rename

1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

Sounds easy, but as I said I don’t know MaxScript too well. I’ll try to learn more when I’m free.

do you need to rename the textures only for diffuse map? What if a material in diffuse map has maps with more then 1 texture? How will you rename them?

what if the same material has the same texture in other maps – bump, reflection and so on?
Why do you need to rename according to object name, what do you receive from that?

1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

Q: do you need to rename the textures only for diffuse map?
A: Yup.

Q: What if a material in diffuse map has maps with more then 1 texture? How will you rename them?
A: Each material should only has one diffuse map.

Q: what if the same material has the same texture in other maps – bump, reflection and so on?
A: Each material should only has one diffuse map. No other maps.

Q: Why do you need to rename according to object name, what do you receive from that?
A: I have hundreds of objects with different texture file names, so I need to organize them.

fn renameDiffuseMaps nodes: =
(	
	if nodes == unsupplied do nodes = selection as array
	donetxt = #()	
	renamed = #()
	for node in nodes where iskindof (mat = node.material) Standard do  
	(
		if iskindof (txt = mat.diffusemap) BitmapTexture and finditem donetxt txt == 0 do
		(
			if (file = txt.filename) != undefined do
			(
				namedfile = getfilenamepath file + node.name + getfilenametype file
				if doesfileexist txt.filename and stricmp namedfile file != 0 do
				(
					if not doesfileexist namedfile do
					(
						copyfile file namedfile
					)
					txt.filename = namedfile
					append renamed #(node, namedfile)
				)
			)
			append donetxt txt
		)
	)
	renamed
)
/*
-- select what you want for rename and run:
print (renameDiffuseMaps())
*/
1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

This works better than my code! My code only changes the names of the existing texture files, but yours copies the existing texture files into new texture files with new names. Thanks a lot.

I have an issue with my example scene though (the attached ZIP). I have four Spheres. Two of them use the same material and the same texture file. After running your code, I only got Sphere001.jpg and Sphere002.jpg. Could you please tell me how to get Sphere003.jpg and Sphere004.jpg?

you have to make materials unique… i can add this option to the function (because you probably don’t know yet how to make it yourself ;))

1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

Yes please… I am a total noob in MaxScripting

fn renameDiffuseMaps nodes: makeMaterialsUnique:off =
(	
	if nodes == unsupplied do nodes = selection as array
	donetxt = #()	
	renamed = #()
	for node in nodes where iskindof (mat = node.material) Standard do  
	(
		if iskindof (txt = mat.diffusemap) BitmapTexture and (makeMaterialsUnique or finditem donetxt txt == 0) do
		(
			if (file = txt.filename) != undefined do
			(
				namedfile = getfilenamepath file + node.name + getfilenametype file
				if doesfileexist txt.filename and stricmp namedfile file != 0 do
				(
					if makeMaterialsUnique and (refs.dependentnodes mat).count > 1 do
					(
						node.material = copy mat
						txt = node.material.diffusemap
					)

					if not doesfileexist namedfile do
					(
						copyfile file namedfile
					)
					txt.filename = namedfile
					append renamed #(node, namedfile)
				)
			)
			append donetxt txt
		)
	)
	renamed
)
/*
-- select what you want for rename and run:
print (renameDiffuseMaps makeMaterialsUnique:on)
*/

Hi, I got the error message below when executing the code…

-- Error occurred in node loop
--  Frame:
--   mat: Material_Ground:Standard
--   makeMaterialUnique: undefined
--   txt: Map #1:Bitmap
--   node: $Plane001
--   file: undefined
--   namedfile: undefined
--   called in renameDiffuseMaps()
--  Frame:
--   nodes: #($Plane001, $Sphere001, $Sphere002)
--   donetxt: #()
--   makeMaterialsUnique: true
--   renamed: #()
-- Type error: logical-or requires BooleanClass, got: undefined

I have made all materials unique for each object

it was a bug. fixed in the code

1 Reply
(@gotanidea)
Joined: 1 year ago

Posts: 0

Thanks a lot! :bowdown: