PDA

View Full Version : fixing bitmaps without causing Max to load them


cyrfer
06-11-2011, 12:53 AM
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!

PiXeL_MoNKeY
06-13-2011, 03:15 PM
Use ATSOps to handle the file name and path manipulations.

-Eric

cyrfer
06-14-2011, 09:32 PM
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.

denisT
06-14-2011, 09:54 PM
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.

PiXeL_MoNKeY
06-14-2011, 09:59 PM
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

Panayot
06-14-2011, 10:56 PM
... I get it from the Bitmap.filename property, but reading this property seems to cause Max to try to load the bitmap file. ...How can I read the filename property of a Bitmap without causing Max to try to load the Bitmap?
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:\temp' folder but there is not 'test2.bmp')
txtMap = bitmaptex()
txtMap.fileName -- ""
txtMap.fileName = "C:\\temp\\test2.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:\temp\test2.bmp")

allTxtMaps = getClassInstances BitmapTexture
allTxtMaps.count -- 1
allTxtMaps[1].filename -- "C:\temp\test2.bmp"

allTxtMaps[1].filename = "C:\\temp\\test1.bmp"
files = #()
enumerateFiles get_names files #missing
files.count -- 0 hope this help

PiXeL_MoNKeY
06-15-2011, 12:11 AM
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

denisT
06-15-2011, 05:21 AM
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.

PiXeL_MoNKeY
06-15-2011, 03:49 PM
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

denisT
06-15-2011, 05:37 PM
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.

cyrfer
06-15-2011, 06:33 PM
@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.

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.

@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.

denisT
06-15-2011, 07:07 PM
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?


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) >
)

PiXeL_MoNKeY
06-15-2011, 07:50 PM
The only case you need to know where the asset comes within a scene is if you have 2 (or more) objects referencing one asset, and you only want to update explicit versions (in other words not all instances at once). That can be done with the ATSOps.RetargetAssets, which expects a MaxObject (specific Bitmap Object), oldpath, and newpath. Using this you can have C:\texture.tga changed to C:\some other path\texture.tga, or c:\texture2.tga for that instance of the path.

The question is do you want to repath all references to that asset all at once, or separately based on the usage in the scene.

Hope that makes sense,
-Eric

gandhics
06-16-2011, 05:12 AM
Is it possible to use "AssetUser" for repathing?
I see .getFileName() method, but I can not find .setFileName method..

also I tried

-- 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

But, "atsops.setpathonselection newPath" did not work for broken path.

PiXeL_MoNKeY
06-16-2011, 04:22 PM
Try adding an atsops.refresh() at the end to force a refresh of the dialog. In a simple test I did my code worked fine on missing files that needed to be repathed. Now if you need to change the file type, ie somefile.jpg to somefile.tga you will need to do it per missing entry, not all at once.

Assetuser only allows get functions, you will need to use the asset metadata stream to fix it. See "MAX File Asset Metadata Stream Access (http://docs.autodesk.com/3DSMAX/14/ENU/MAXScript%20Help%202012/files/GUID-2AF2AFE0-1B22-4DA2-B0F9-CA3ADABCB6C-2017.htm)" and setMAXFileAssetMetadata.

-Eric

CGTalk Moderation
06-16-2011, 04:22 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.