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