Home Technical Talk
The BRAWL² Tournament Challenge has been announced!

It starts May 12, and ends Sept 12. Let's see what you got!

https://polycount.com/discussion/237047/the-brawl²-tournament

Max script batch process question

polycounter lvl 16
Offline / Send Message
NeoProfZ polycounter lvl 16
Having issues with a batch process that would remove the modifier "MultiRes" from the stack for a group of .max files. I'm not quite sure which part of it isn't working but I have a feeling its the actual modifier removal part of the process. Any help would be well appreciated.

macroScript ExportAllAnimation category:"WIT" tooltip:"ExportAllAnimation"

(

global W_ExportAllAnimation, RO_ExportAllAnimation


rollout RO_ExportAllAnimation "Batch Export DSQ" width:304 height:80

(

edittext edtSourceDirectory "" pos:[88,8] width:184 height:16

label lbl1 "Source directory" pos:[8,8] width:80 height:16

button ChooseSourceDir ".." pos:[272,8] width:16 height:16

edittext edtExportDirectory "" pos:[88,32] width:184 height:16

label lbl2 "Export directory" pos:[8,32] width:80 height:16

button ChooseExportDirectory ".." pos:[272,32] width:16 height:16

button btnExport "Export" pos:[8,56] width:280 height:16


on ChooseSourceDir pressed do

(

source_dir = getSavePath()

edtSourceDirectory.text = (source_dir as string)

)

on ChooseExportDirectory pressed do

(

export_dir = getSavePath()

edtExportDirectory.text = (export_dir as string)

)

on btnExport pressed do

(

maxfiles = getFiles (edtSourceDirectory.text + "\\*.max")

if edtSourceDirectory.text == "" or edtSourceDirectory.text == "undefined" then

(

messagebox "No source directory."

return 0

)

exportdir = (edtExportDirectory.text + "\\")

if edtExportDirectory.text == "" or edtExportDirectory.text == "undefined" then

(

exportdir = (edtSourceDirectory.text + "\\")

)

for fl in maxfiles do

(

loadMaxFile fl

select obj

deleteModifier obj MultiRes

fname = exportdir + getFilenameFile(fl) + ".max"

exportFile fname

)

)

)


if W_ExportAllAnimation != undefined do

(

try( closeRolloutFloater W_ExportAllAnimation )

catch()

)


W_ExportAllAnimation = newRolloutFloater "ExportAllAnimation" 310 116
addRollout RO_ExportAllAnimation W_ExportAllAnimation

Replies

  • Rob Galanakis
    Offline / Send Message
    Rob Galanakis polycounter lvl 18
    deleteModifier expects an index (1, 2, 3, etc.), or an instance of a modifier. So, you can change:
    deleteModifier obj MultiRes
    to
    deleteModifier obj obj.modifiers[#Multires]

    However, I don't see where you define 'obj', so the script probably still won't work (it will give you an error like, "no 'select' function for undefined", and will crash on the "select obj" line). If you need further help, just ask.
  • KikiAlex
    Offline / Send Message
    KikiAlex polycounter lvl 18
    1. fn Cleen_Multi =
    2. (
    3. for i in objects do
    4. (
    5. if i.modifiers.Count != 0 do
    6. (
    7. for m in i.modifiers do
    8. (
    9. if ((classof m) == MultiRes) do
    10. (
    11. deleteModifier i m
    12. )
    13. )
    14. )
    15. )
    16. )
    17.  
    18. fn Cleen_MultiRes =
    19. (
    20. for p = 1 to 20 do
    21. (
    22. Cleen_Multi()
    23. )
    24. )
    25.  
    26.  
    27. Cleen_MultiRes()

    This is how a clean MultiRes function should look like
    I iterate 20 times trough the clean function because in max 9+ sometimes it does not execute
  • Rob Galanakis
    Offline / Send Message
    Rob Galanakis polycounter lvl 18
    Your code can be simplified to:
    1. fn Cleen_MultiRes =
    2. (
    3. for o in objects do
    4. (
    5. while o.modifiers[#Multires] != undefined do
    6. deleteModifier o o.modifiers[#Multires]
    7. )
    8. )
    9.  
    10. Cleen_MultiRes()

    That will delete all Multires on all objects in your scene.
  • NeoProfZ
    Offline / Send Message
    NeoProfZ polycounter lvl 16
    Thanks much guys, I'll go ahead and give some of this stuff a shot.
  • NeoProfZ
    Offline / Send Message
    NeoProfZ polycounter lvl 16
    Much thanks with the help on the MultiRes removal. Looks like its working now.

    However, the script still only runs through a single source directory. Do you guys know if Maxscript could handle a more thorough batch process that includes subdirectories as well?
  • Mark Dygert
    Unfortunately I don't think there is a "include/exclude" sub directories command as part of getsavepath() ?

    Are any part of the names of the sub directories known?
    You could probably patch something together using "getDirectories" and the "PathConfig Struct"

    I'm sure Rob can blow your socks off with a way more awesome reply if not outright write a function for you....
  • NeoProfZ
    Offline / Send Message
    NeoProfZ polycounter lvl 16
    Ok, so here's where I am right now. I found a piece of code that looks like it'll recursively go through the existing directory structure of a given folder and collect up all the max files. I'm trying to integrate it with the multires removal code but it just ends up falling apart.
    1. thePath = getSavePath() --get a path dialog to specify the path
    2.  
    3. pattern = "*.max"
    4.  
    5.  
    6. --if thePath != undefined do --if the user did not cancel
    7.  
    8. --(
    9.  
    10. --theFiles = getFiles (thePath+"*.max") --collect all max files in the dir.
    11.  
    12. --for f in theFiles do --go through all of them
    13.  
    14. --(
    15.  
    16.  
    17. fn getFilesRecursive root pattern =
    18. (
    19. dir_array = GetDirectories (ThePath+"/*")
    20. for d in dir_array do
    21. join dir_array (GetDirectories (d+"/*"))
    22. TheFiles = #()
    23. for f in dir_array do
    24. join TheFiles (getFiles (f + pattern))
    25. TheFiles
    26. )
    27.  
    28. --getFilesRecursive ThePath pattern
    29.  
    30. for m in theFiles do
    31. ---------------------------------------------------------------------------
    32.  
    33. loadMaxFile m --load the next file
    34.  
    35.  
    36. fn Cleen_MultiRes =
    37. (
    38. for o in objects do
    39. (
    40. while o.modifiers[#MultiRes] != undefined do
    41. deleteModifier o o.modifiers[#MultiRes]
    42. )
    43. )
    44.  
    45. Cleen_MultiRes()
    46.  
    47.  
    48. saveMaxFile m --save the file back to disk
    49.  
    50. )--end f loop
    51.  
    52. -------------------------------------------------------
    53.  
    54. resetMaxFile #noPrompt --at the end, you can reset
    55.  
    56. )--end if
    57.  
    While I'm at it (and since I'm still really new to max scripting) is there a better environment to do this sort of thing than wordpad? ultraedit comes to mind but I just want a way to debug this code without so much guess-work.


    edit: Forgot to mention, it'll go through several files before returning an error of "-- Unable to convert: Undefined to type: String". It looks like its not removing the multires modifier either.
  • Rob Galanakis
    Offline / Send Message
    Rob Galanakis polycounter lvl 18
    Since I won't have time to write up a proper response for a little while, check out Paul Neale's Batch It Max: http://www.paulneale.com/scripts/batchItMax/batchItMax.htm
  • Mark Dygert
    I'm not sure I can test what you have going but lets see if I can help you structure things so they're a little more manageable and readable.
    1. (--Start of Script
    2. -------------------------------------------------
    3. --DECLARATIONS--
    4. -------------------------------------------------
    5. thePath = getSavePath() --get a path dialog to specify the path
    6. pattern = "*.max"
    7.  
    8. -------------------------------------------------
    9. --FUNCTIONS--
    10. -------------------------------------------------
    11. fn getFilesRecursive root pattern =
    12. (--Get sub directories?
    13. dir_array = GetDirectories (ThePath+"/*")
    14. for d in dir_array do
    15. join dir_array (GetDirectories (d+"/*"))
    16. TheFiles = #()
    17. for f in dir_array do
    18. join TheFiles (getFiles (f + pattern))
    19. TheFiles
    20. )
    21.  
    22. fn Clean_MultiRes =
    23. (--Delete MultiRes Modifier
    24. for o in objects do
    25. (
    26. while o.modifiers[#MultiRes] != undefined do
    27. deleteModifier o o.modifiers[#MultiRes]
    28. )
    29. )
    30.  
    31. -------------------------------------------------
    32. --MEAT--
    33. -------------------------------------------------
    34. if thePath != undefined do
    35. (--collect all max files in the dir.
    36. theFiles = getFiles (thePath+"*.max")
    37. for f in theFiles do --go through all of them
    38. (
    39. getFilesRecursive ThePath pattern
    40. )
    41. )
    42. for m in theFiles do
    43. (--Load, Clean & Save
    44. loadMaxFile m --load the next file
    45. Clean_MultiRes() --Call clean function
    46. saveMaxFile m --save the file back to disk
    47. )
    48.  
    49. resetMaxFile #noPrompt --at the end, you can reset
    50.  
    51. )--end of script
    (This is more cleaning up the script and offering organizational suggestions then it is actually making the script work...)

    Declarations, Functions and Meat works best for me but not always, there are times I'll write functions in other places but in general I try to keep each piece in its section. As well as adhering to some kind of indenting rule(s).

    Also 3dsmax2008-09 have a pretty good Maxscript editor. Main Menu > MAXScript > MAXScript Editor.
    If your on older versions Notepad++ is pretty good.
  • NeoProfZ
    Offline / Send Message
    NeoProfZ polycounter lvl 16
    I did get it working, but the fact that there are missing map files is making it still click intensive. (from the missing map file dialog)

    I'm trying to set

    logsystem.quietmode or setquietmode() , but I don't know why they don't work. any idea why max 5 would have an issue with these, or how they are meant to be used?
  • Mark Dygert
    humm that will cause some issues. I'm not sure switching to quitemode will get you past the problem. You might have better luck updating the bitmap paths. Might come in handy to update automate the path update anyway. I guess if you have to set it back you can temporarily update them and set it back...

    http://www.scriptspot.com/3ds-max/relink-bitmaps
    This relink bitmap script might have some good pointers if you decide to go that route.
  • NeoProfZ
    Offline / Send Message
    NeoProfZ polycounter lvl 16
    Thanks vig,

    but this is over 2000 files, , we just need to strip the multires out of them. Many of the textures don't even exist anymore. It loops and gets rid of the multires, but someone has to sit there and click "continue" for each file.
  • Mark Dygert
    Ahh in that case, it gets difficult. The reason I don't think it will work is because quite mode is very specific to what triggers the error. In this case I don't think quitemode has an option for export (you're exorting right?), but the render "missingExtFilesAction:" might work, but I doubt it because its not triggered at render time but exporting, which means it might just be ignored...
    Quiet Mode
    missingExtFilesAction: <actions>
    Actions to take on Missing External Files, where <actions> is: #logmsg, #logToFile, #abort, #default and/or an integer, or an array of one or more of those items.
    I think you'll run into more trouble because the #default action option was added into 3dsmax8 and higher. So theres a slim chance it would work in 8 or higher and hardly a chance at all to work in 5. But the maxscript help doc for 5 might have a work around... maybe...

    Do you even need to worry about the map paths? Maybe just applying a standard material to the object and clear the material editor. In which case you might want to take a peak at this material cleaner script I wrote for some useful functions.
    1. macroScript MatClean
    2. Category:"HITools"
    3. toolTip:"Material Cleaner"
    4. buttontext:"MatClean"
    5. (--Used to clean and prep scenes for animation (I not need ur puny textors fumans!)
    6. rollout MatClean "MatClean" width:128 height:136
    7. (--Rollout and script
    8. button btn_RstSM "Clean Objects" pos:[8,32] width:112 height:24 toolTip:"Removes materials from selected objects, or from all objects if nothing is selected"
    9. button btn_WrClr "Wire Color" pos:[8,56] width:72 height:24 toolTip:"Sets selected objects to the same custom wire color or all objects if nothing is selected (materials do not change)"
    10. button btn_RstME "Clean Editor" pos:[8,8] width:112 height:24 toolTip:"Resets all material editor slots (does not pay attention to selection)"
    11. button btn_Mat1WrClr "Mat1 + Wire Color" pos:[8,104] width:112 height:24 toolTip:"Applies Mat Slot 1 to selected objects or for all objects if nothing is selected (Sets the wire color to the current custom color)"
    12. button btn_RndmWrClr "Random Wire Color" pos:[8,80] width:112 height:24 toolTip:"Applies random wire colors to selected objects, or to all objects if nothing is selected. (materials do not change)"
    13. colorPicker cp1 "" pos:[72,56] width:48 height:24 color:(color 0 0 0) title:"Choose a color"
    14.  
    15. --Functions
    16. fn clear_all_meditSlots =
    17. (--Resets all material samples in the material editor to default standard.
    18. macros.run "Medit Tools" "clear_medit_slots"
    19. )
    20. fn kill_materials =
    21. (--Removed all materials from the scene (checks and operates on selection only if something is selected)
    22. if $ == Undefined then
    23. (
    24. max select all
    25. $.material = noMaterial()
    26. )
    27. else
    28. (
    29. $.material = noMaterial()
    30. )
    31. )
    32. fn dull_materials =
    33. (--Sets all objects to the material material slot 1, and changes the wire color to black
    34. clear_all_meditSlots()
    35. kill_materials()
    36. )
    37. fn wire_color =
    38. (--sets the wire color on all objects to the specified color
    39. if $ == Undefined then
    40. (
    41. max select all
    42. $.wirecolor = cp1.color
    43. )
    44. else
    45. (
    46. $.wirecolor = cp1.color
    47. )
    48. )
    49. --Button Actions
    50. on btn_RstSM pressed do
    51. (
    52. kill_materials()
    53. )
    54.  
    55. on btn_WrClr pressed do
    56. (
    57. wire_color()
    58. )
    59.  
    60. on btn_RstME pressed do
    61. (
    62. macros.run "Medit Tools" "clear_medit_slots"
    63. )
    64. on btn_Mat1WrClr pressed do
    65. if $ == undefined then
    66. (
    67. dull_materials()
    68. wire_color()
    69. max select all
    70. $.material = meditMaterials[1]
    71. )
    72. else
    73. (
    74. dull_materials()
    75. wire_color()
    76. $.material = meditMaterials[1]
    77. )
    78. on btn_RndmWrClr pressed do
    79. if $ == undefined then
    80. (
    81. for obj in objects do
    82. obj.wirecolor = color (random 0 255) (random 0 255) (random 0 255)
    83. clearSelection()
    84. )
    85. else
    86. (
    87. for obj in selection do
    88. obj.wirecolor = color (random 0 255) (random 0 255) (random 0 255)
    89. clearSelection()
    90. )
    91.  
    92. )
    93. (--U makem pretty window now k!?
    94. createdialog MatClean
    95. )
    96. )
  • Rob Galanakis
    Offline / Send Message
    Rob Galanakis polycounter lvl 18
    We had a similar problem, but because Max was coming up with memory problems. I'll post the solution later tonight, requires some explanation.
  • Rob Galanakis
    Offline / Send Message
    Rob Galanakis polycounter lvl 18
    http://tech-artists.org/forum/showthread.php?p=1831#post1831

    There you go. That should get you over your design hurdles and technical workarounds- the rest of the work is coming up with the actual code, but it is not difficult and it will be a good learning experience.
  • Mark Dygert
    Hey, that's slick!
Sign In or Register to comment.