PDA

View Full Version : Collect and Move Maps to Folder


thatoneguy
08-10-2007, 03:06 AM
Two new scripts pretty basic. First one creates a .txt file of all the maps used in a scene. Second script copies all the maps from a list file to a designated folder.

(
filesave = getsavefilename types:"TXT(*.txt)"
filesave = (filesave+".txt")
if filesave != undefined then
(
BT=getClassInstances BitmapTexture
(
dump = ""
local mapfiles=#()
fn addmap mapfile =
(
local mapfileN=mapfile as name
local index=finditem mapfiles mapfileN
if index == 0 do append mapfiles mapfileN
)
enumeratefiles addmap
sort mapfiles
for mapfile in mapfiles do
(
append dump ((mapfile as string)+"\n")
)
createfile filesave
fstream = openfile filesave mode:"w"
format "%" dump to:fstream
)
)
)


(
file = getopenfilename caption:"Open New-Line-Seperated Map List."
if file != undefined then
(
dest = getsavepath initialDir:("W:\\") caption:"Choose a Destination Folder."
)
if file != undefined and dest != undefined then
(
open_file = openfile file mode:"r+"
seek open_file 0
mapfiles = readDelimitedString open_file "~"
mapfiles = filterstring mapfiles "\n"
for i = 1 to mapfiles.count do
(
newname = filenamefrompath mapfiles[i]
newname = (dest+"\\"+newname)
oldname = mapfiles[i]
copyfile oldname newname
)
)
)

lechoo
08-10-2007, 06:52 AM
Thanks for sharing this.

thatoneguy
08-10-2007, 08:47 AM
Edit: I noticed a few debug lines still in and a typo. Let me correct those real quick... boy... for being inside of "code" tags... CGTalk sure is insistant on changing my paste.

I give up trying to get the formatting to 'stick'. You get the idea. :) First script is based pretty heavily on one provided in the help documentation go ahead and check that one out it has some interesting peripheral information.

soulburn3d
08-10-2007, 06:24 PM
A shame "getClassInstances BitmapTexture" isn't a surefire way to get all the bitmaps in a scene. For example, it won't access the skylight map inside the brazil renderer. It also won't get maps that exist inside a displace modifier.

- Neil

MoonDoggie
08-10-2007, 06:41 PM
I have had great success with it reporting bitmaps included in VRayDisplacement Modifier...not exactly sure what problems you've had soulburn. It works for me.

thatoneguy
08-10-2007, 07:49 PM
Yeah I actually only wrote the second script because I didn't like how the "archive" option worked and I already had a TXT file with all the maps listed. But figured for 'future generations' that's not really an efficient use of your time to archive/delete a bunch of maps just for a text file. Ideally you would just skip the file altogether and just export all the maps. But I was (and am short on time).

Does the file -> Archive list more thoroughly find all maps?

MoonDoggie
08-10-2007, 07:55 PM
enumerateFiles

should be the most effective use of collecting missing maps. Although I don't like to use it mostly because it does things I don't expect (like calling the <function> twice for each file)

Maybe someone could shed some light on why it does that?
Thanks!

ypuech
08-10-2007, 08:50 PM
Maybe the references solution can be useful in this situation : http://www.sloft.net/2005/11/26/maxscript-references/

d3coy
08-10-2007, 11:40 PM
For some scripts I've written in the past I used getclassinstances and searched through some modifiers on a "special case" basis (like displace mod as Neil said, and Hair/Cloth mods also have map slots that aren't retrieved through getclassinstances) to get the bitmaptextures. It definitely doesn't make for clean code.

refs.dependents gives me a reference to the material editor when supplying a node with the displacement modifier on it, even if the map in the displacement modifier isn't instanced to the medit material array. refs.dependson yields the transform controller and some derived object classes... in which case I'd have to loop through the derived objects and employ more case-specific code.

So I'm still not sure how to get the maps from the modifier without doing some intense case-specific property checking, which is what we all try to avoid. Anyone know of a sure-fire way to do this? Not even Resource Collector grabs these maps.

soulburn3d
08-11-2007, 05:30 PM
Ya, there really seems to be no surefire way to collect all the maps in a scene, so in the past I've had to write a lot of special case code. I tried getClassInstances BitmapTexture in max8, and here's the results...

Background map - works
displace modifiers - works sometimes (that's pretty agrivating, sometimes it works, sometimes it doesn't it seems)
displace spacewarps - works
max projector lights - works
brazil 1 & 2 projection lights - doesn't work
brazil skylight map - doesn't work
fog - works
render effects blur filter - doesn't work

Oh, to actually have one function that returns it all :D

- Neil

soulburn3d
08-11-2007, 05:35 PM
Does the file -> Archive list more thoroughly find all maps?

Nope, it also, for example, misses any map in the render effects dialog.

- Neil

soulburn3d
08-11-2007, 05:43 PM
Maybe someone could shed some light on why it does that?
Thanks!

Personally, I've never been able to understand the code behind the materials system.

Objects seem far more well laid out, if you want a property, you do something like myobject.property, you want a property of a modifier, you say myobj.modifier.property.

To get things in materials requires using numsubs, subAnims and you have to manually traverse the trees. And it seems like there's a lot of junk in there that isn't really useful, and lots of duplicate information.

Anytime I have to write a map or material related script, a little part of me gets scared. :)

- Neil

d3coy
08-13-2007, 03:40 PM
haha, I feel the same way.

One function to rule them all... I guess I'll continue writing special-case material fetching code.

MoonDoggie
08-13-2007, 03:54 PM
Thanks for the response Soulburn. Glad I'm not the only one who has problems with this.

-Colin

simonenastasi
08-13-2007, 04:49 PM
I always used the utility "map path" something, can't remember the name. Usually it worked...

magicm
08-13-2007, 06:42 PM
displace modifiers - works sometimes (that's pretty agrivating, sometimes it works, sometimes it doesn't it seems)
This could be because the displace modifier has two slots, one for a texturemap, and another for a bitmap. The latter won't collect when using getClassInstances bitmapTexture since it is not a bitmapTexture (just like bitmaps in render effects like the Blur effect).

getClassInstances bitmap doesn't work either, probably because the word bitmap means different things in mxs (eg. ui control and bitmap constructor). It might also have to do with the fact that Bitmap is a base class like matrix3 or float. Calling getClassInstances on one of these wouldn't make much sense either.

I've been struggling with this in the past as well, and wasn't able to come up with a generic solution at the time. I used a combination of functions like Neil which worked but was painfully slow with large scenes. Traversing the subanim trees of all objects/effects/etc seems like the most robust way of collecting all bitmaps, but like I said it's simply way too slow.

Martijn

soulburn3d
08-14-2007, 12:07 AM
This could be because the displace modifier has two slots, one for a texturemap, and another for a bitmap. The latter won't collect when using getClassInstances bitmapTexture since it is not a bitmapTexture

Yup, I'm aware of that, I still get random behavior when only using the texturemap slot, and ignoring the bitmap slot entirely.

(just like bitmaps in render effects like the Blur effect).

Are you sure? Because the Map Mask in the blur render effect brings up a dialog to choose any sort of map, not a file dialog for me to pick a bitmap. Or were you refering to a different slot?

- Neil

magicm
08-14-2007, 12:24 AM
..the Map Mask in the blur render effect brings up a dialog to choose any sort of map, not a file dialog for me to pick a bitmap. Or were you refering to a different slot?
You're right. This bitmap should be picked up by the getClassInstances call.. Even getClassInstances bitmapTexture target:(getEffect 1) (assuming there's a Blur effect containing a bitmapTexture at the first index) returns no results. An atmospheric effect with a bitmap (for example Fog) does return it's bitmap with getClassInstances though. Sounds like a bug to me!

Martijn

soulburn3d
08-14-2007, 12:35 AM
Sounds like a bug to me!

Yup, there are a lot of them in this chunk of the code :) I remember having a lot of problems with maxscript not being able to find some bitmaps, or finding the same map again and again. From my recollection, I had a discussion with the developper in charge of maxscript at the time (max 3 or 4 I believe), and he said there wasn't much he could do about this sort of thing because the material related maxscript calls rely heavily on the SDK, and so it was the material tree code that needed the fix, not maxscript, and they hadn't had a developper go into that code for quite some time. Maybe that sort of stuff will get a fix if they go in and rip out the system in order to put a schematic material editor in there :)

- Neil

MoonDoggie
08-14-2007, 03:10 PM
wtb integrated Node based material editor please.

PS. anyone write a script so I can link the coordinates for some of my materials? If it was node based, I could just link the coords so if I update the real-world-mapping scale in the bitmap material, it would affect the diffuse,opacity,reflection so I don't forget to accidently set the coord scale.

I will write one if no-one knows of one.

Solomon
09-19-2007, 09:40 PM
hi thatoneguy (http://forums.cgsociety.org/member.php?u=141678)

does this script also update the material slots so they point to the where the files have been copied to?

PiXeL_MoNKeY
09-24-2007, 09:24 PM
Just curious if anyone has looked into using atsops in Max 8+ to get/set/replace/remap bitmaps and bitmapstextures? You can easily access all files referenced by the scene and get access to their full paths. So you should be able to easily move the files and then update the path in the ATS. You would just need to filter out file types you don't want remapped, such as xref files.

Just a thought,
-Eric

MoonDoggie
09-24-2007, 11:19 PM
Just a quick personal plug:

I wrote a relink bitmaps script that doesn't provide the exact functionality you're looking for, but could be an asset at a later time, I know it's helped me time and again.

The script identifies missing bitmaps the scene and allows the user to recursively search for them in any directory the user specifies and will update the bitmaps accordingly (relinking them in the material editor etc to reflect the new paths to answer your question Soloman)

The script has some features the asset browser and photometric bitmap paths doesn't include:

1. Recursive Directory searching
2. Saveable Quick Paths allowing the user to easily search common texture library directories
3. Interactive Mode - When on, allows the user to click the missing bitmap to select the object it is assigned to. Double-clicking the missing bitmap will put the object in isolation mode.
4. It's fast, I can search my entire maps directory (12,000+ textures) in under 30 seconds

The script is always updated on scriptspot here:

http://www.scriptspot.com/3ds-max/relink-bitmaps

Hope it helps,
Colin

PiXeL_MoNKeY
09-25-2007, 05:28 PM
MoonDoggie, so you were able to get around the issue of getclassinstances not working with textures in bitmap slots instead of texture slots? The atsops approach should provide a workaround to this. For example, it will show the displacement modifier bitmap image (and texture image) and the render effect blur Map Mask image.

-Eric

Edit: magicm, getClassInstances bitmapTexture target:(getEffect 1).selmaskmap will return the blur mask map.

MoonDoggie
09-25-2007, 05:46 PM
MoonDoggie, so you were able to get around the issue of getclassinstances not working with textures in bitmap slots instead of texture slots? The atsops approach should provide a workaround to this. For example, it will show the displacement modifier bitmap image (and texture image) and the render effect blur Map Mask image.

-Eric

Edit: magicm, getClassInstances bitmapTexture target:(getEffect 1).selmaskmap will return the blur mask map.


Not quite actually. The script finds missing bitmaps using two functions to produce similar results each with an advantage over the other.

The normal function used for finding missing bitmap textures is via the getClassInstances method, which is quicker than the other method enumerateFiles which is a bit quirky, but carries different functionality over getClassInstances.

For the time being, getclassinstances proved to be just fine. Special-case scenarios where plenty of additional checking for different renderers (Vray, Maxwell, MR, Brazil) ends up slowing the script down, and my main goal was speed in the end.

In the script there are two functions for building the missing maps, one uses getClassInstances, the other, EnumerateFiles. I'll update them to include special cases and renders if it's wanted. Meanwhile we're stuck with a non-node based material editor and a poor way to access missing bitmaps, at least we're in the same boat.


-Colin

edit: I'm unfamiliar with the atsops approach, care to elaborate a bit?

PiXeL_MoNKeY
09-25-2007, 05:50 PM
You may want to look at atsops.getfilebystatus #Missing &FileList. It should return any missing maps based on the FileList array in parameter. Again this is just thinking out loud I haven't tried implementing any of these approaches.

-Eric

PiXeL_MoNKeY
09-25-2007, 06:59 PM
Colin from the Maxscript Reference:
A Core Interface providing access to the Asset Tracking System. Available in 3ds Max 8 and higher. It looks like you can script just about everything available to Asset Tracking Dialog. Such as setting paths, changing file used, identifying status of files, handle the bitmap proxy settings, etc.

-Eric

djlane
09-25-2007, 07:44 PM
The asset tracking system sounds interesting,awhile ago I had to write a bitmap redirection script and noticed that there were cases were getClassInstances wouldnt pick up all the bitmaps. I am sure getClassInstances does not pick up bitmaps used by the Arch and Design material.

MoonDoggie
09-25-2007, 11:19 PM
Eric,
Thanks for the refs, I'll take a look at both of them to improve my script and hopefully not render it obsolete ;) More to come.

martinB
09-27-2007, 05:27 PM
So far, I find that either


files =()
ATSOps.GetFilesByFileSystemStatus #Ok &files
-- replace #Ok with #Missing if you're after the missing bitmaps


or


fn get_names name a = append a name
files = #()
enumerateFiles get_names files #render


gives me a full list of bitmaps used, but I haven't checked all possibilites.
If someone finds a missing spot, please let me know.

-- MartinB

CosyTo
05-28-2008, 11:27 AM
So far, I find that either


files =()
ATSOps.GetFilesByFileSystemStatus #Ok &files
-- replace #Ok with #Missing if you're after the missing bitmaps


or


fn get_names name a = append a name
files = #()
enumerateFiles get_names files #render


gives me a full list of bitmaps used, but I haven't checked all possibilites.
If someone finds a missing spot, please let me know.

-- MartinB

I've been looking through the ATSOps recently but cannot figure out how to get the all the information. All it seems to return are integers/indexes. Is is possible to get some path information out of it?
If would just like to build a list with all assets used in the scene (bitmaps, XRefs, Cache files, ... ).

thanks
Tom

martinB
05-28-2008, 03:59 PM
Tom,

try this:

files = #()
numOk = ATSOps.GetFilesByFileSystemStatus #Ok &files
format "Found % assets with status OK\n" numOk
for i = 1 to files.count do format "Asset #% = %\n" i files[i]

If you replace #ok with #missing you would get a list of all missing assets.

Note that this does not necessarily cover all external files!

-- MartinB

PiXeL_MoNKeY
05-28-2008, 04:43 PM
Here is a script I wrote for someone who needed the paths of a scene exported to a text file.out_name = getSaveFileName caption:"Text File" types:"Text Files (*.txt)|*.txt|All Files (*.*)|*.*|"
if out_name != undefined then (
out_file = createfile out_name
flList = #()
ATSOps.Refresh()
ATSOps.GetFiles &flList
for inFile in 1 to flList.count do (
if ATSOps.IsInputFile flList[inFile] == true then (
format "%\n" flList[inFile] to:out_file
)
)
close out_file
edit out_name
)Basically I use the ATSOps.GetFiles &fileArray to fill an empty array with all file paths. Once done you just need to search through the fileArray using 1 to fileArray.count to get all paths. I used ATSOps.IsInputfile so that output paths will be ignored.

Hope that helps some,
-Eric

Edit:Stupid formating.

ZeBoxx2
05-28-2008, 07:22 PM
I wouldn't trust .isInputFile any further than I can throw it; and it's virtual, so that's not very far.


renderers.current.ShadowMapFilename
"C:\Documents and Settings\YupItsMe\My Documents\3dsmax\sceneassets\renderassets\zort.zt"

fList = #()
ATSOps.Refresh()
ATSOps.GetFiles &fList
for i = 1 to fList.count do (
f = fList[i]
if (ATSOps.IsInputFile f) then (
format "IN : %\n" f
)
else ( format "OUT: %\n" f )
)

IN : c:\temp\test.max
IN : glare_streaks_star_camera_filter.tif
OUT: C:\Documents and Settings\YupItsMe\My Documents\3dsmax\sceneassets\renderassets\zort.zt


Problem is, that file is input -and- output. Now for a shadow maps file that might not be a huge deal. If it's a large cache file - such as an irradiance cache, a pointcache, a Krakatoa cache, and so forth and so on and ATSOps goes "bah, that's not input, no need to parse that" :shrug:

DaveWortley
05-28-2008, 07:40 PM
Two new scripts pretty basic. First one creates a .txt file of all the maps used in a scene. Second script copies all the maps from a list file to a designated folder.

(
filesave = getsavefilename types:"TXT(*.txt)"
filesave = (filesave+".txt")
if filesave != undefined then
(
BT=getClassInstances BitmapTexture
(
dump = ""
local mapfiles=#()
fn addmap mapfile =
(
local mapfileN=mapfile as name
local index=finditem mapfiles mapfileN
if index == 0 do append mapfiles mapfileN
)
enumeratefiles addmap
sort mapfiles
for mapfile in mapfiles do
(
append dump ((mapfile as string)+"\n")
)
createfile filesave
fstream = openfile filesave mode:"w"
format "%" dump to:fstream
)
)
)




Is there a way with this code to also list the Bitmap sizes at the same time? Would be very very useful to debug a massive scene we're having problems with.

Also is there a way to get it to inspect in Xref Scene Entries?

ZeBoxx2
05-28-2008, 08:06 PM
Is there a way with this code to also list the Bitmap sizes at the same time?
The quoted code doesn't appear to be valid; it collects the bitmapTextures into BT, but then BT is never used later?

Here's one way, with additional checks:

(
filesave = getsavefilename types:"TXT(*.txt)|*.txt"
if filesave != undefined then
(
deleteFile fileSave
fStream = createFile fileSave
for bmp in getClassInstances bitmapTexture do (
format "map: %\n" bmp to:fStream
if (bmp.filename == "") then ( format "\t-- no filename set\n" to:fStream )
else (
format "\tfilename: %\n" bmp.filename to:fStream
if (not (doesFileExist bmp.filename)) then ( format "\t\t-- file does not exist\n" to:fStream )
else (
bmpFile = openBitmap bmp.filename
if (bmpFile == undefined) then (
format "\t\t-- file is not a valid bitmap file\n" to:fStream
)
else (
format "\t\tresolution: %x%\n" bmpFile.width bmpFile.height to:fStream
)
)
)
)
close fStream
)
edit fileSave
)


Sample output:

map: Bitmaptexture:Bitmap
filename: c:\temp\test.bmp
resolution: 512x512
map: Map #1:Bitmap
filename: c:\test.max
-- file is not a valid bitmap file
map: Map #2:Bitmap
-- no filename set
map: Map #3:Bitmap
filename: C:\test2.bmp
-- file does not exist

MoonDoggie
05-28-2008, 10:20 PM
We often have the same problems with files being too large at render so I wrote a quick script to do searching for large bitmaps and sort them by file size or dimensions, so bump:

http://www.scriptspot.com/3ds-max/find-large-bitmaps

-Colin

It's saved me alot of time finding and troubleshooting, troublesome scenes.

DaveWortley
05-29-2008, 09:53 AM
We often have the same problems with files being too large at render so I wrote a quick script to do searching for large bitmaps and sort them by file size or dimensions, so bump:

http://www.scriptspot.com/3ds-max/find-large-bitmaps

-Colin

It's saved me alot of time finding and troubleshooting, troublesome scenes.

Just a shame it doesn't work with Xref Scene... Anyone know a way to adapt the code?

CosyTo
05-30-2008, 04:50 PM
Tom,

try this:

files = #()
numOk = ATSOps.GetFilesByFileSystemStatus #Ok &files
format "Found % assets with status OK\n" numOk
for i = 1 to files.count do format "Asset #% = %\n" i files[i]

If you replace #ok with #missing you would get a list of all missing assets.

Note that this does not necessarily cover all external files!

-- MartinB

I completely overlooked that function! It's exactly what I need. Thanks a lot for pointing it out.

CGTalk Moderation
05-30-2008, 04:50 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.