[Closed] fixing bitmaps without causing Max to load them
Hi,
I have written a 3DS MAXscript (using 2010) to help the art team fix broken filepaths to the scene Bitmaps. The script makes a variation of the filepath based on user settings for a few cases:
1- a new folder,
2- remove base name prefix,
3- or change to a different extension.
It is working well, but it suffers from one requirement that I would like to remove. Unfortunately, to know the value of the current filepath for the BitMap, I get it from the Bitmap.filename property, but reading this property seems to cause Max to try to load the bitmap file. The Bitmap file does not exist (hence the reason for this script) and the filename property returns ‘undefined’. This screws up the rest of my script and I do not know another way to get the value of the Bitmap’s filename property.
How can I read the filename property of a Bitmap without causing Max to try to load the Bitmap?
Thanks for any help!
Will you elaborate? I looked at ATSOps and I do not think it will solve this problem.
I believe I am “handling”, or manipulating, the filename well already.
The problem is that I need to get the value of the Bitmap’s filename without causing Max to try to load the bitmap.
If I understood right you are talking about Bitmap (not Bitmaptexture). So you can’t get bitmap’s filename property of undefined bitmap. When max tries to open bitmap with bad or nonexistent texture file it creates undefined bitmap. When you call this bitmap from max script the system tries resolve the bitmap (open) with fail. I couldn’t find a way to read filename of broken bitmap using mxs.
All maps (and external files) should exist in the Asset Tracker. If you get and set the file there, it won’t try to load until after you adjust. There is also the AssetManager interface which handles all asset management in 3ds Max 2010+. The AssetManager also allows you to alter the path of assets without the file being loaded.
-Eric
You can call directly BitmapTexture.FileName (not need Bitmap.FileName). Here is a snippet test to bring an idea to get started. (for the test i put a ‘test1.bmp’ into ‘C: emp’ folder but there is not ‘test2.bmp’)
txtMap = bitmaptex()
txtMap.fileName -- ""
txtMap.fileName = "C:\ emp\ est2.bmp"
stdMat = standard()
stdMat.diffuseMap = txtMap
b = box()
b.mat = stdMat
txtMap.Bitmap.fileName == txtMap.fileName
-----------------------------------------
function get_names name a = append a name
files = #()
enumerateFiles get_names files #missing
files -- #("C: emp est2.bmp")
allTxtMaps = getClassInstances BitmapTexture
allTxtMaps.count -- 1
allTxtMaps[1].filename -- "C: emp est2.bmp"
allTxtMaps[1].filename = "C:\ emp\ est1.bmp"
files = #()
enumerateFiles get_names files #missing
files.count -- 0
hope this help
Here is a sample using ATSOps:
-- Get all files
atsops.GetFiles &fileList
-- Get missing files
missingFiles = for val in fileList where ((atsops.GetFileSystemStatus val)[1] == #missing) collect val
-- Desired new path
newPath = ""
-- Select missing files
atsops.selectfiles missingFiles
-- Retarget selection to new path
atsops.setpathonselection newPath
-Eric
this is not a problem to get a list of missing textures. the problem is to know where they are missed from. if textures are missing from bitmap (NOT BITMAPTEXTURE) there is no way (at least for me) to say what bitmap misses the texture.
i can find missing bitmaps by NODE (object, material, bitmaptexture, custom attribute, modifier, etc.). but BITMAP is not a Node, it’s not a MaxObject. i can find missing textures by bitmap using the SDK and c++ only, and can’t do it using the MXS.
the max assets tracker doesn’t show missing texture BITMAPS.
Yes it does, now the bitmap you are thinking of may not expose itself properly to asset tracker. For example, add a bitmap to the displace modifier (or background bitmap) it will show up in the asset tracker and as missing if it is missing. It is the responsibility of the tool developer to make sure their assets are exposed properly to the asset tracker.
Bitmaps should also appear through the asset manager interface.
-Eric
we are talking about different things. I say that the Asset Tracker doesn’t show the destination of texture. Lets say a DirectX shader… The Tracker shows all shader’s textures, but it doesn’t show accurate within a bitmap where they used.
@Pixel_Monkey: Thanks for the great tips. Now I see what you mean about ATSOps. If a fix for my issue exists, I believe you that ATSOps will be the solution. I will see what I can learn from your example code. Also, I think you pointed out that a possible solution depends on how the asset was exposed. How I can check how the asset was exposed? Is there a visual browser? Please read the additional info I post below.
@DenisT: Thanks for speaking for me, you were right to assume I meant the Bitmap class and not the Bitmaptexture class. How can I confirm the Tracker does or does not show the texture files for the example you proposed?
A little more info:
1- We use a 3rd party plugin for the materials. Using “showClass OgreMax_Texture_Unit.*” (analogous to a Bitmaptexture class I think) I see that it has a member named “Bitmap” of type “bitmap”.
2- I have a correction to my original statement. The symptom from reading the texture.Bitmap.filename value does not return ‘undefined’. Reading that value actually kills the script because some code behind the curtain fails in its attempt to load the file (from the path it knows from ATSOps?). I get a pop-up message from MXS for a ‘rollout handler exception’ saying “runtime error: error opening bitmap: C:\example\folder\original_file.jpg”. My script never goes farther in its execution after reading that value.
i was absolutely sure that you talked about some scripted material or 3d party material. Probably we are talking about some real-time shader that extends DirectX Shader.
Asset Tracker shows you missing textures, but it doesn't show the place where the missing texture was used. If there is only one missing texture per shader it's easy to find a place.
if you go through all shader's bitmaps and check the class of returned property:
- the valid bitmap returns Bitmap class,
- the not-assigned bitmap returns UndefinedClass,
and
- the bitmap with missed texture throws system exception...
so the pseudo-code is:
fn getBrokenBitmaps mat =
(
for p in bitmap_properties_of_mat where (try (classof (getproperty mat p)) catch()) == undefined collect p
)
but if we have more than one missing textures there is a problem to find what broken bitmap missed the texture.
In this case there is a solution (pseudo-code):
broken_bitmaps = getBrokenBitmaps shader
for t in missing_textures do
(
temp_texture = createValidTexture t
updateShader shader
still_broken = getBrokenBitmaps shader
fixed = broken_bitmaps - still_broken
delete temp_texture
< we have a pair = missing_texture + broken_bitmap(s) >
)