but when the path to …/source_art changes (i.e., a new workspace is created in P4) max looses track of all the textures.
It’s a headache I’ve faced before and not found a robust solution for.
google hits at yield a wide variety of responses, mostly one-asset-at-a-time band aid solutions.
I’d like something bulletproof , reliable, and script-able.
I am thinking of dropping the mesh vs texture folder arrangement and just keeping the textures in the maxfilepath folder so Max can see them.
but I have noticed that when you do this, the mxs reference (obj.material.diffuseMap.filename) still points to the old location.
Thus is important because I need a reliable reference to the source textures file locations.
Just a thought, but did you consider a callback on scene open that checks if the relative path of referenced textures are correct? Also if you’re remapping p4 workspaces, you can check if the texture file reference exists, if not point to the proper path. This however assumes you have a consistent folder structure for your project.
You should add the relative texture path ( relative to the max file ) to your user paths-> External Files pathlist
I see your structure references the texture in a “.textures/” sub-path (relative to the max file location ,
so adding a “. extures” entry in “Configure User Paths->External Files” tab should solve your problem
thanks for your replies
@ spacefrog :
I tried adding the relative path to the External files in Configure User Paths GUI but it didn’t work.
So I started looking for a mistaken assumption in my situation.
I checked the user paths with some code:
for i = 1 to mapPaths.count() do
(
m=mapPaths.get i
format "%
" m
)
it returned a path relative to my C:\ drive rather than relative to the maxfilepath.
I think the project settings for our assets were never changed from Max’s Default settings.
So the “relative to what?” target is incorrect.
The wayward paths that spawned the “missing file” alerts seemed to be stored (or at least accessed) in the Asset Tracker (in mxs AtsOps Interface) so utilizing its functions provided a workable solution.
/*
newDir replaces the "mesh" maxfilepath with "texture"
so "C:/project/art/characters/myCharacter/mesh/ " becomes "C:/project/art/characters/myCharacter/textures/"
if not found in /textures/ then the global /art/ directory is searched.
this covers expected locations of the textures in anyone's local workspace
*/
fn repathBitmaps newDir:(substitutestring maxfilepath "mesh" "texture") =
(
local arr=#()
ATSOps.GetFilesByFileSystemStatus #Missing &arr--gather missing filpaths into the array arr
if arr.count>0 then(
format " repathMissingBitmaps to: %
" newDir
--use maxfilepath to find the local path to /art/
slices=filterstring maxfilepath "\\"
str = ""
artPath=""
index=finditem slices "art"
for i = 1 to index do
(
artPath+=slices[i]
artPath+="\\"
)
for asset in arr do
(
format " missing:%
" asset
AtsOps.clearSelection()
AtsOps.selectFiles #(asset)
local filenameOfAsset = (DotNetClass "System.IO.Path").GetFileName asset
local di = DotNetObject "System.IO.DirectoryInfo" newDir --look in ../textures/
local files = di.GetFiles filenameOfAsset (DotNetClass "System.IO.SearchOption").AllDirectories
if files[1] !=undefined then (
--if found , replace the path in the Asset Tracker
local newFileName = files[1].directoryName
AtsOps.SetPathOnSelection newFileName
format " FOUND:%
" newFileName
)else(
--not in ../textures/ so look globally in .../art/
di = DotNetObject "System.IO.DirectoryInfo" artPath
artfiles = di.GetFiles filenameOfAsset (DotNetClass "System.IO.SearchOption").AllDirectories
for each in artfiles do
if artfiles[1] !=undefined then (
newFileName = artfiles[1].directoryName
AtsOps.SetPathOnSelection newFileName
format " FOUND:%
" newFileName
)else(
format " NOT FOUND:%
"asset
)
)
ATSOps.refresh()
)
)
)