Notifications
Clear all

[Closed] Fixing obsolete files in 'Missing External Files'

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.tif
ClassType: GlaretextureMap
ClassPath: rootScene.Renderer.Camera_Output_Shader.Streak_Image
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
 		 Arguments:
 			<node> node:	any object node
 		 Optional:
 			<string> type:	any string representing a property. Default is "bitmap"
 		 Return:
 			<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
 		props
 	)
 	
 	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)
 					
 					)
 					else
 					(
 						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) \
 												className:newRoot.name \
 												value:texturePath )
 				)
 			)
 		)
 		
 		if results.count > 0 then 
 		(
 			for itm in results do 
 			(
 				format "Path: %
" itm.value
 				format "	ClassType: %
" itm.class
 				format "	ClassPath: %
" itm.classpath
 				format "	ClassName: %
" 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.)

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?

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(
		f=arr[i]
		--is the missing file it list of files used by scene objects?
		if finditem used  f !=0 then(
			format "% is used
" f
		)else(
			--if not used , get its ID and pass it to AssetManager.ReleaseReference()
			format "% is unused. released:%
" f (AssetManager.ReleaseReference(AssetManager.GetAssetId f #Bitmap ))
		)
	)
	--update asset tracker 
	ATSOps.refresh()

(anybody know what the un-google-able “TSTR” or “&TSTR” values are?)

TSTR is usually either CStr or WStr depending on the build settings.

So TSTR is just a more obscure way of saying <string> ?

no not really, it’s a way of setting a type depending on build settings. If the build is set to unicode character set, any variable using type TSTR is set to WStr otherwise CStr (not a problem since 2014 as everything is WStr). MXS string doesn’t use CStr btw.

In 2016+ you can use

AssetManager.RemoveMissingAssets()
Page 2 / 2