Fixing obsolete files in 'Missing External Files'

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

Thread Tools Search this Thread Display Modes
  11 November 2013
Fixing obsolete files in 'Missing External Files'

We have files coming in form outsources that contain references to unneeded files.
The files have no object we can I identify which uses the missing external file.
how do I get rid of these, so that the 'Missing External Files' alert goes away?

I'm looking at the max MAX Scene File Properties help...but it seems like max ought to have some built in tool for this...
  11 November 2013
hmmm... poking around with fileproperties and the asset tracker , it seems like these references are very very hard to adjust.

Just to be clear: this is an unused reference to a bitmap file, not used in the scene, not found in the material editor or the bitmap /photometric path editor. it only exists as a reference in the file properties and the annoying ' Missing External Files' popup when the file is opened.

Last edited by Mambo4 : 11 November 2013 at 07:40 PM.
  11 November 2013
Originally Posted by Mambo4: Just to be clear: this is an unused reference to a bitmap file...

bitmap? or bitmaptexture? where were these bitmaps used?
  11 November 2013
I have no idea where the file reference comes from or what it was used on.
It's a path to a TIF that we do not use in anything in the file.
The outsources may have used it perhaps a lighting or camera effect for their own renders, but we do not need them.

They do not exist in sceneMaterials, only in fileProperties and the Asset Tracker.
Right clicking in the asset Tracker and choosing 'strip Path'
will remove the path ans stop the annoying pop up, but the reference stays in the asset tracker with no way to remove it.

the asset name in question is "glare_streaks_start_camera_filter.tif" if that means anything to anyone.

Last edited by Mambo4 : 11 November 2013 at 10:51 PM.
  11 November 2013
well... attach a file. i will take a look.
  11 November 2013
here goes...nothing in the file but a reference to a missing tif.
Attached Files
File Type: zip (24.1 KB, 11 views)
  11 November 2013
Originally Posted by Mambo4: here goes...nothing in the file but a reference to a missing tif.

that is exactly what i like. puzzle
  11 November 2013
before looking into the file let me conjecture...
# a missed texture cannot seat in the file without bitmap
# a bitmap in the empty file can be stored in only three places:
  • - material editor
  • - custom attribute
  • - environment map (background image)
# if it's a material but not in the material editor it's probably in the slate material editor
# if it's in a custom attribute there two possible places:
  • - max root node
  • - material editor reference object
  • - (there are some other places but an average developer doesn't know about them and very unlikely can put anything there by accident)
# if it's in a background image it's very easy to check

Last edited by denisT : 11 November 2013 at 01:37 AM.
  11 November 2013
The filepath shows up using the example enumeratefiles() fucntion
as well usedMaps rootScene
but neither function seems able to retrun exactly what max wrapper object uses the file.

by itertating usedMaps with various maxwrapper values , and some educated guessing,
I isolated the file's user: usedMaps rootScene.renderer.Camera_Output_Shader
returns the bitmap path.

I read further and discoverd that rootScene.renderer.Camera_Output_Shader
is a default value populated automatically by mentalRay.
It cannot be set to a null value, it must have a path.
Even if rootScene.renderer.Enable_Camera_Output_Shader:fal se ,
the bitmap is still referenced as a value and added to the Asset Tracker,
which then alerts the user if it is missing on file open.

The only one way I can find to get this value to stop poppign up an alert on file open:
change the rederer to a non-mental-ray renderer and save the file.
  11 November 2013
This will remove it from the scene and stop the pop-up without having to reset the renderer.

rootScene.renderer.Camera_Output_Shader.Streak_Ima ge = ""

or more commonly you would write

renderers.current.Camera_Output_Shader.Streak_Imag e = ""
Maxscript Made Easy...

Last edited by DaveWortley : 11 November 2013 at 07:03 PM.
  11 November 2013
if it's a default file for mental ray and you are not going to use it you can always create a small 64x64 black tif file at that location. It's not pretty but will kill the message
  11 November 2013
Using denisT's earlier work this will do what Mambo4 described. It doesn't have DenisT's elegance but someone else may find it of use.

Output should be:

Path: ..\..\..\..\Program Files\Autodesk\3ds Max 2012\Maps\glare\glare_streaks_star_camera_filter.t if
ClassType: GlaretextureMap
ClassPath: rootScene.Renderer.Camera_Output_Shader.Streak_Ima ge
ClassName: DefaultOutputShader

 	struct TextureData (class, classpath, className, value)
 	fn getPropertiesByType node type:"bitmap" = 
 		/**************************************************  **************************************************  **********
 		 <DOC>  Use this to pick out only bitmaps from shaders.
 				- DenisT came up with this function on CGTalk
 			<node> node:	any object node
 			<string> type:	any string representing a property. Default is "bitmap"
 			<Array> returns an zero to n number of NAMES found depending on results.
 		 **************************************************  **************************************************  **********/
 		local filter = " .:"
 		local props = #()
 		local ss = stringStream "", str
 		-- check through delegate if available
 		if (isproperty node #delegate) == true then 
 			showProperties node.delegate to:ss 
 		showProperties node to:ss
 		seek ss 0
 		while not eof ss do
 			str = filterstring (readline ss) filter
 			if stricmp str[str.count] type == 0 do
 			append props (str[1] as name)
 		free ss
 	fn _strArrayToClass strArray &stringRef:unsupplied = 
 		local ss = stringstream ""
 		for itm in strArray do format itm to:ss
 		str = (ss as string)
 		if iskindof stringRef string then stringRef = str
 		newRoot = execute(str)
 	fn whereIsTheTexture texturePath class:rootscene propArray:#("rootScene") recursive:false results:#() = 
 		-- prep stringstream with properties of the 'root' passed in.  
 		local filter = " .:"
 		local ss = stringStream ""
 		showProperties class to:ss
 		seek ss 0
 		while not eof ss do
 			local str = filterstring (readline ss) filter
 			local currentProp = str[str.count]
 			if (not matchpattern currentProp pattern:"Environment" and
 				not matchpattern currentProp pattern:"Medit_Materials" and 
 				isproperty class currentProp) do 
 				local maps = usedMaps (getproperty class currentProp)
 				if (iskindof maps Array and finditem maps texturePath > 0) then 
 					-- more properties to examine so we are going to have to rerun the function
 					recursive = true
 					if matchpattern propArray[propArray.count] pattern:"*DirectX_Shader" then
 						-- FIX: After solving for somethign in the materialLibrary() class we should step back int the array to this position again.
 						-- replace the last shader with the current one.
 						propArray[propArray.count] = ("." + currentProp)
 						append propArray ("." + currentProp)
 					newRoot = _strArrayToClass propArray
 					whereIsTheTexture texturePath class:newRoot propArray:propArray
 				)-- end inner if
 			)--end if
 		)-- end while
 		free ss
 		if recursive == false then
 			local newString = ""
 			local newRoot = _strArrayToClass propArray stringRef:&newString
 			local results01 = getPropertiesByType newRoot type:"filename"
 			local results02 = getPropertiesByType newRoot type:"bitmap"
 			local fullresults = join results01 results02
 			for result in fullresults do 
 				local var = (getproperty class result) as string
 				if matchpattern var pattern:("*"+texturePath) then 
 					append results (TextureData class:(classof newRoot) \
 												classpath:(newString + "." + result) \
 												value:texturePath )
 		if results.count > 0 then 
 			for itm in results do 
 				format "Path: %\n" itm.value
 				format "\tClassType: %\n" itm.class
 				format "\tClassPath: %\n" itm.classpath
 				format "\tClassName: %\n" itm.classname
 	for path in (usedmaps rootscene) do (whereIsTheTexture path)

edit: The script should now handle DirectX shaders (I haven't tried on delegates tho...)
edit2: Cleaned up the code a bit.. added an additional line to indicate what the classof the object holding the texture/shader is.
edit3: Now handles multiple shaders. Output provides the class name (which may be the material you are looking for.)

Last edited by JasonB : 11 November 2013 at 08:49 PM.
  04 April 2014
sorry to resurrect the thread but I'm back to this annoying problem.

many files no longer used are clogging the Asset tracker and I would love to automatically cull these useless references.

I assumed that AssetManager.ReleaseReference was the ticket but it seems to not accomplish what I need.
I can gather a list of all the files acutally being used by scene objects, compare the files returned by AssetManager. AssetManager.GetAssetByIndex(), and pass IDs of undesired refs to AssetManager.ReleaseReference <ID> which returns true.

but still, the file opens with warnings and the Asset Tracking tool still lists all the no longer existing bitmaps.

how can I use a script to destroy these undesired refs?

Last edited by Mambo4 : 04 April 2014 at 08:31 PM.
  04 April 2014
took some digging, but i got it.

the necessary maxscript to effectively manage the Asset Tracker are split between two interfaces:
ATSOps and AssetManager. Both utilizes some of the more obfuscated max script features and types.
(anybody know what the un-google-able "TSTR" or "&TSTR" values are?)

only AssetManager.ReleaseReference() can remove a reference form the asset manager.
you have to pass the function an asset ID which you get from
AssetManager.GetAssetId <fileName> #Bitmap 

unless you then refresh the asset manager with ATSOps.refresh(), max script will not know this has been released.

	ATSOps.GetFilesByFileSystemStatus #Missing &arr --get asset tracker's missing files
	ATSOps.GetDependencyFileList rootscene &used true --get all files used by scene objects
	for i=1 to arr.count do(
		--is the missing file it list of files used by scene objects?
		if finditem used  f !=0 then(
			format "% is used\n" f
			--if not used , get its ID and pass it to AssetManager.ReleaseReference()
			format "% is unused. released:%\n" f (AssetManager.ReleaseReference(AssetManager.GetAss  etId f #Bitmap ))
	--update asset tracker 

Last edited by Mambo4 : 04 April 2014 at 10:17 PM.
reply share thread

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Society of Digital Artists

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump

All times are GMT. The time now is 07:17 PM.

Powered by vBulletin
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.