This tool was created and used at Blizzard to iterate different types of fluid simulation to fit the art direction at the most.
Maxscript
(local FFXSRoll,FFXSTool,FumeSel,FFXSLogoglobal Rp = getFileNamePath rendOutputFilenameglobal Rf = getFileNameFile rendOutputFilenameglobal Rt = getFileNameType rendOutputFilenameglobal simFilesListrollout FFXVol "FumeFX Creator" width:240 height:240( edittext objName "Name " pos:[8,119] width:110 height:18 button btnAdd "Add Selection" pos:[8,8] width:110 height:16 button rmvBttn "Remove" pos:[120,8] width:110 height:16 spinner strFrame "Start Frame " pos:[41,144] width:76 height:18 range:[-50000,50000,100] type:#integer spinner endFrame "End Frame " pos:[156,144] width:76 height:18 range:[-50000,50000,200] type:#integer button btnVolFume "Generate FumeFX" pos:[8,166] width:224 height:24 listBox objLst "Object Selected" pos:[8,29] width:224 height:5 local ObjSel = #() on btnAdd pressed do ( getObj = for i in selection collect i if ObjSel.count == 0 then ( for i in getObj do insertItem i ObjSel 1 ObjSelList = for p in ObjSel collect p.name objLst.items = ObjSelList ) else ( for i in getObj do ( local nameCheck = 0 for j = 1 to ObjSel.count do ( tempSel = i if tempSel.name != ObjSel[j].name then ( nameCheck = nameCheck + 0 ) else ( nameCheck = nameCheck + 1 ) ) if nameCheck == 0 then ( tempSel = i slot = ObjSel.count + 1 insertItem tempSel ObjSel slot ObjSelName = for k in ObjSel collect k.name objLst.items = ObjSelName ) else ( messagebox (i.name +" is already on the list") ) ) ) ) on rmvBttn pressed do ( if objLst.selection != 0 then ( s_Item = objLst.selection deleteItem ObjSel (s_Item) ObjSelName = for i in ObjSel collect i.name objLst.items = ObjSelName ) else ( messagebox "No Object Selected" ) ) on btnVolFume pressed do ( for i = 1 to ObjSel.count do ( tempObj = ObjSel[i] slidertime = strFrame.value for i = strFrame.value to endFrame.value do ( min1 = (box scale:[.01,.01,.01] name:"get_min1" position:tempObj.min) max1 = (box scale:[.01,.01,.01] name:"get_max1" position:tempObj.max) min2 = (box scale:[.01,.01,.01] name:"get_min2" position:[max1.position.x, min1.position.y, min1.position.z] ) min3 = (box scale:[.01,.01,.01] name:"get_min3" position:[min1.position.x, max1.position.y, min1.position.z] ) min4 = (box scale:[.01,.01,.01] name:"get_min4" position:[max1.position.x, max1.position.y, min1.position.z] ) max2 = (box scale:[.01,.01,.01] name:"get_max2" position:[min1.position.x, max1.position.y, max1.position.z] ) max3 = (box scale:[.01,.01,.01] name:"get_max3" position:[max1.position.x, min1.position.y, max1.position.z] ) max4 = (box scale:[.01,.01,.01] name:"get_max4" position:[min1.position.x, min1.position.y, max1.position.z] ) slidertime +=1 ) ) collectGet = $get_* as array for i = 1 to collectGet.count do ( addmodifier collectGet[i] (edit_mesh()) collapsestack collectGet[i] ) for i = 1 to (collectGet.count - 1) do ( meshop.attach collectGet[collectGet.count] collectGet[i] ) bBox = collectGet[collectGet.count] ( newmin1 = (dummy name:"box_min1" position:bBox.min) newmax1 = (dummy name:"box_max1" position:bBox.max) newmin2 = (dummy name:"box_min2" position:[newmax1.position.x, newmin1.position.y, newmin1.position.z]) newmin3 = (dummy name:"box_min3" position:[newmin1.position.x, newmax1.position.y, newmin1.position.z] ) newmin4 = (dummy name:"box_min4" position:[newmax1.position.x, newmax1.position.y, newmin1.position.z] ) ) delete bBox pointA=$box_min4 pointB =$box_min3 pointC =$box_min2 pointD =$box_max1 getFumeLength = distance pointA pointC getFumeWidth = distance pointA pointB getFumeHeight = distance pointA pointD posX= (pointB.position.x + ((distance pointA pointB)/2) ) posY = (pointC.position.y + ((distance pointA pointC)/2) ) posZ = (pointD.position.z - ((distance pointA pointD)) ) getName=ObjName.text as string getFume = (FumeFX name:getName) getFume.position = [posX,posY,posZ] getFume.length = getFumeLength getFume.width = getFumeWidth getFume.height = getFumeHeight delete $box_* ))rollout FFXSTool "Simulation Priority" width:240 height:320( listBox fumePri "FumeFX Priority" pos:[8,43] width:190 height:12 button upBttn "UP" pos:[202,58] width:28 height:79 images:#(arrup(),arrup(),1,1,1,2,2) button dwBttn "DW" pos:[202,141] width:28 height:79 images:#(arrdw(),arrdw(),1,1,1,2,2) button btnAdd "Add Selection" pos:[8,8] width:110 height:16 button rmvBttn "Remove" pos:[120,8] width:110 height:16 button strSimBttn "Start Simulation" pos:[8,224] width:224 height:16 button strSimRenBttn "Start Sim and Render" pos:[8,245] width:224 height:16 checkbox sWavelet "Wavelet" pos:[80,27] checkbox sPost "Post" pos:[148,27] checkbox sStandard "Standard" pos:[8,27] local FumeSel = #() on btnAdd pressed do ( getFume = for i in selection collect i if FumeSel.count == 0 then ( for i in getFume do ( if classof i == FumeFX then insertItem i FumeSel 1 else messagebox (i.name +" is not FumeFX type") ) FumeSelList = for p in FumeSel collect p.name fumePri.items = FumeSelList ) else ( for i in getFume do ( local nameCheck = 0 for j = 1 to FumeSel.count do ( tempSel = i if tempSel.name != FumeSel[j].name then ( nameCheck = nameCheck + 0 ) else ( nameCheck = nameCheck + 1 ) ) if nameCheck == 0 then ( tempSel = i slot = FumeSel.count + 1 if classof i == FumeFX then insertItem i FumeSel slot else messagebox (i.name +" is not FumeFX type") FumeSelName = for k in FumeSel collect k.name fumePri.items = FumeSelName ) else ( messagebox (i.name +" is already on the list") ) ) ) ) on rmvBttn pressed do ( if fumePri.selection != 0 then ( s_Item = fumePri.selection deleteItem FumeSel (s_Item) FumeSelName = for i in FumeSel collect i.name fumePri.items = FumeSelName ) else ( messagebox "No FumeFX Selected" ) ) on upBttn pressed do ( if fumePri.selection > 1 then ( s_Item = fumePri.selection insertItem FumeSel[s_Item] FumeSel (s_Item - 1) deleteItem FumeSel (s_Item + 1) FumeSelName = for i in FumeSel collect i.name fumePri.items = FumeSelName fumePri.selection = s_Item-1 ) ) on dwBttn pressed do ( if fumePri.selection != FumeSel.count then ( s_Item = fumePri.selection insertItem FumeSel[s_Item] FumeSel (s_Item + 2) deleteItem FumeSel (s_Item) FumeSelName = for i in FumeSel collect i.name fumePri.items = FumeSelName fumePri.selection = s_Item + 1 ) ) on strSimBttn pressed do ( if sStandard.checked == false and sPost.checked == false and sWavelet.checked == false then ( messagebox "No Sim Type Selected" ) else ( for goSim in FumeSel do ( if sStandard.checked == true do ( goSim.RunSimulation 0 ) if sWavelet.checked == true do ( goSim.RunSimulation 2 ) if sPost.checked == true do ( goSim.RunSimulation 3 ) ) ) ) on strSimRenBttn pressed do ( if sStandard.checked == false and sPost.checked == false and sWavelet.checked == false then ( messagebox "No Sim Type Selected" ) else ( for goSim in FumeSel do ( if sStandard.checked == true do ( goSim.RunSimulation 0 ) if sWavelet.checked == true do ( goSim.RunSimulation 2 ) if sPost.checked == true do ( goSim.RunSimulation 3 ) ) ) render framerange:(interval rendStart rendEnd) outputfile:rendOutputFilename --resetMaxFIle #noPrompt --gc() ))rollout FFXSTool_3 "Sim and Render Murtiple" width:240 height:240( button pathBttn "Add File" pos:[8,8] width:110 height:16 button pathRmvBttn "Remove File" pos:[121,8] width:110 height:16 listBox fileList "File List" pos:[8,32] width:224 height:6 button simStrBttn "Start Simulation" pos:[8,140] width:224 height:16 --spinner startfr "StartFrame" pos:[38,165] width:80 height:16 range:[-10000,10000,1] type:#integer --spinner endfr "EndFrame" pos:[151,165] width:80 height:16 range:[-10000,10000,3] type:#integer button renStrBttn "Start Render" pos:[8,160] width:224 height:16 button simrenStrBttn "Start Sim and Render" pos:[8,180] width:224 height:16 global simFilesArray = #() -- ����Ʈ�� �̸��� �ø������� ��� global nameArr = #() -- ����� ������Ʈ�� ���� ��� global simFilesList = #() --���Ͽ����� ���� ��� on pathBttn pressed do ( ( global simFiles = (getopenFileName caption:"Load a SourceFiles" types:"SourceFiles(*.max)|*.Max") insertItem simFiles simFilesList 1 global simFilesName = getFilenameFile simFiles insertItem simFilesName simFilesArray 1 if simFilesArray[1] != undefined then ( fileList.items = simFilesArray ) else() ) ) on pathRmvBttn pressed do ( if fileList.selection != 0 then ( d_item = fileList.selection deleteItem simFilesArray (d_item) nameArr = for i in simFilesArray collect i fileList.items = nameArr ) else messagebox "No Scene File Selected" ) on simStrBttn pressed do ( files = getFiles (getFilenamePath simFiles + "*.max") for filenames in simFilesList do ( loadmaxfile filenames objAll = for o in geometry collect o local fumebox = #() for a in objAll do ( if classof a == fumefx then ( insertItem a fumebox 1 ) ) if fumebox.count > 0 then ( for k in fumebox do ( k.RunSimulation 0 ) ) --resetMaxFIle #noPrompt --gc() ) ) on renStrBttn pressed do ( files = getFiles (getFilenamePath simFiles + "*.max") for filenames in simFilesList do ( loadmaxfile filenames render framerange:(interval rendStart rendEnd) outputfile:rendOutputFilename --resetMaxFIle #noPrompt --gc() ) ) on simrenStrBttn pressed do ( files = getFiles (getFilenamePath simFiles + "*.max") for filenames in simFilesList do ( loadmaxfile filenames objAll = for o in geometry collect o local fumebox = #() for a in objAll do ( if classof a == fumefx then ( insertItem a fumebox 1 ) ) if fumebox.count > 0 then ( for k in fumebox do ( k.RunSimulation 0 ) ) render framerange:(interval rendStart rendEnd) outputfile:rendOutputFilename --resetMaxFIle #noPrompt --gc() ) ))if FFXSRoll != undefined then ( closeRolloutFloater FFXSRoll)FFXSRoll = newrolloutfloater "FFXS v1.5 jyoo" 252 680addrollout FFXVol FFXSRolladdrollout FFXSTool FFXSRolladdrollout FFXSTool_3 FFXSRoll)