/** THIS IS A MODIFICATION OF THE ORIGINAL ASSET RESOURCE TOOL TO MAKE THINGS MUCH MORE AUTOMATED. A LOT OF THE FUNCTIONS ARE DIRECTLY COPIED OVER FORM THE OLD TOOL WITH A FEW EXTRA PARAMS ADDED TO THEM WITH A FEW NEW PREP FUNCTIONS ADDED IN. **/ if resourcePrep_UI != undefined then destroyDialog resourcePrep_UI filein "rockstar/export/settings.ms" -- This is fast -- Figure out the project theProjectRoot = RsConfigGetProjRootDir() theProject = RSConfigGetProjectName() theWildWest = RsConfigGetWildWestDir() theProjectConfig = RsConfigGetProjBinConfigDir() toolsRoot = RsConfigGetToolsRootDir() RSTA_LoadCommonFunction #("FN_Materials.ms") filein (theWildWest + "script/3dsMax/_config_files/Wildwest_header.ms") filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Perforce.ms") filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms") filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_UI.ms") global resourcePrep_UIWidth = 240 global resourcePrep_UIHeight = 270 global resourcePrep_UI = undefined rageMaterialsArray = undefined index = undefined ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ fn RSTA_getUiPosFile = ( --THIS HAS TO BE DECLARED FROM WITHIN THIS SCRIPT uiPosFile = ((getThisScriptFilename())) filePath = filterString uiPosFile "." uiPosFile = (filePath[1]+"_UIPOSFILE.TXT") return uiPosFile ) fn findLodObjects = ( lodStrings = #( "_LOD", --end of string "_SLOD", --end of string "_lod_" --anywhere in string ) lodObjects = #() for obj in objects do ( if superclassof obj == GeometryClass do ( nameCount = obj.name.count if (substring (toLower(obj.name)) (nameCount - 3) -1) == toLower(lodStrings[1]) do ( appendIfUnique lodObjects obj --format ("Appending "+lodStrings[1]+" "+obj.name+" to lodObjects.\n") ) if (findString (toLower(obj.name)) (toLower(lodStrings[2]))) != undefined do ( appendIfUnique lodObjects obj --format ("Appending "+lodStrings[2]+" "+obj.name+" to lodObjects.\n") ) if (findString (toLower(obj.name)) (toLower(lodStrings[3]))) != undefined do ( appendIfUnique lodObjects obj --format ("Appending "+lodStrings[3]+" "+obj.name+" to lodObjects.\n") ) ) ) return lodObjects ) -- collects all children recursively. arguments: -- found on http://forums.cgsociety.org/showpost.php?p=4427477&postcount=2 fn CollectChildren obj &allChildren includeParent:false includeHidden:false = ( -- check if object should be collected if (includeHidden or not obj.isHiddenInVpt) and includeParent and finditem allChildren obj == 0 then append allChildren obj -- collect current object's children for c in obj.children do CollectChildren c &allChildren includeParent:true includeHidden:includeHidden ) -- end collectChildren -- tidy up the user defined properties by sorting it alphabetically fn ReorderTags tagMe = ( currentUDP = getUserPropbuffer tagMe filterUDP = filterString currentUDP "\r\n" alphUDP = sort filterUDP tag = "" for t = 1 to alphUDP.count do ( tag = tag + alphUDP[t] + "\r\n" setUserPropbuffer tagMe tag ) )-- end reorderTags -- delete any mesh info tags. this includes selection sets and meshnames -- deleteFromThese = the meshes to delete from fn DelFileInfoTags deleteThisMesh = ( keepUDP = #() currentUDP = getUserPropbuffer deleteThisMesh filterUDP = filterString currentUDP "\r\n" for f = 1 to filterUDP.count do ( tempUDP = uppercase filterUDP[f] shortUDP = substring tempUDP 1 7 if (shortUDP != "MAXFILE") then append keepUDP tempUDP ) tag = "" if keepUDP.count == 0 then setUserPropbuffer deleteThisMesh tag else for k = 1 to keepUDP.count do ( tag = tag + keepUDP[k] + "\r\n" setUserPropbuffer deleteThisMesh tag ) ReorderTags deleteThisMesh )-- end delFileInfoTags -- go through all geometry and tag it with the maxscene name fn TagFileNameInfo meshToTag = ( tagThis = "" tagThis = "MaxFile=" + maxfilepath + maxfilename oldTag = getUserPropbuffer meshToTag tagThis = oldTag+"\r\n"+tagThis tagThis = uppercase tagThis setUserPropbuffer meshToTag tagThis ReorderTags meshToTag --tidy up the tags )-- end tagFileNameInfo fn CaptureDisplay = ( filein (RsConfigGetWildWestDir() + "script/3dsMax/Cutscene/CutsceneCaptureSphereDisplay.ms") ) fn restoreMaterials rageMaterialsArray = ( if rageMaterialsArray.count == 24 then ( for i = 1 to rageMaterialsArray.count do ( -- for tmp = 1 to rageMaterialsArray[i][1].count do -- ( -- format ("Restoring "+(tmp as string)+" "+(rageMaterialsArray[i][1][tmp] as string)+"\n") -- ) meditMaterials[i] = rageMaterialsArray[i][1][1] rageMat = meditMaterials[i] if rageMaterialsArray[i][2].count > 0 then ( for obj = 1 to rageMaterialsArray[i][2].count do ( thisObj = rageMaterialsArray[i][2][obj] thisObj.material = rageMat ) ) ) format ("Materials restored.") ) else ( format ("Could not find stored materials array.\n") ) ) fn Export mode = ( case mode of ( #cutscene: ( messagebox "Export #cutscene" ) #game: ( messagebox "Export #game" ) ) ) -- fn PrepareProp exportAlso = -- ( -- if selection.count == 1 then -- ( -- thisProp = getCurrentSelection() -- --=========================================================================================================================== -- --a section to handle gun magazine meshes - bug 808586 -- gunMag == false -- propName = upperCase thisProp[1].name --get the prop name -- filterPropName = filterString propName "_" --filter the name for breaks -- shortPropName = #() --an array to hold the shortened filter data -- for x=1 to filterPropName.count do (append shortPropName (subString filterPropName[x] 1 3)) -- magCheck = findItem shortPropName "MAG" -- if magCheck !=0 do (if filterPropName[magCheck].count == 4 do gunMag = true) -- --=========================================================================================================================== -- -- if ((isMeshSkinned thisProp[1]) == true) and (gunMag != true) then--if the mesh is skinned -- ( -- print "Preparing skinned prop" -- thisProp = getCurrentSelection() -- SortAndSwitch thisProp -- SkinnedProp thisProp[1] exportAlso -- ) -- else -- ( -- if queryBox "This appears to be an unskinned prop.\r\nI will attempt create a rig root setup for it.\r\nDo you want to continue?" beep:false title:"Materials Export Manager" do -- ( -- print "Preparing unskinned prop" -- thisProp = getCurrentSelection() -- SortAndSwitch thisProp -- UnskinnedProp thisProp[1] exportAlso -- ) -- ) -- ) -- else (messageBox "Please run with only one object selected.") -- ) fn PrepareVehicle= ( print "Preparing vehicle" if selection.count != 0 then ( vehicleMeshes = getCurrentSelection() -- vehicleMeshes = #() -- appendIfUnique vehicleMeshes driver -- for obj in skelArray do -- ( -- appendIfUnique vehicleMeshes obj -- ) SortAndSwitch vehicleMeshes VehicleSetup()-- driver skelArray ) else ( if queryBox "Nothing selected.\r\nI will attempt to perform this on all objects in the scene.\r\nThis could take a while.\r\nDo you want to continue?" beep:false do ( hideByCategory.none() -- unhide all by categry max unhide all -- unhide all max select all --select all vehicleMeshes = getCurrentSelection() -- vehicleMeshes = #() -- appendIfUnique vehicleMeshes driver -- for obj in skelArray do -- ( -- appendIfUnique vehicleMeshes obj -- ) clearSelection() SortAndSwitch vehicleMeshes VehicleSetup() -- VehicleSetup driver skelArray ) ) ) fn PrepareMap = ( print "Preparing map" if queryBox "I will attempt to delete all materials in the scene.\r\nDo you want to continue?" beep:false do ( -- clear_all_materials() format ("Cleared all materials...\n") -- kill_materials() format ("Killed all materials...\n") CSMapExport() format ("CS Map Exported.\n") ) ) fn SetupEnvironment = ( filein (RsConfigGetWildWestDir() + "script/3dsMax/Cutscene/cs_enviroment_setup.ms") ) ------------------------------------------------------------------------------------------------------------------------------------------ --WORKHORSE FUNCTIONS ------------------------------------------------------------------------------------------------------------------------------------------ fn CullTextures = ( print "Cull Textures" local shaders = getClassInstances StandardMaterial local diffuseMaps = for item in shaders where item.diffuseMap != undefined collect item.diffuseMap local buffer = #() local mapKeepList = #() --array of map id's that we are going to keep --work out which maps to keep ( if (CutsceneDataPrepUI.AlphaCheckBox.Checked) then append mapKeepList 6 ) clearlistener() -- for item in diffuseMaps where item.bitmap != undefined do for item in diffuseMaps do ( try ( item.bitmap append buffer item ) catch (print "problem with " + item as string) ) diffuseMaps = makeUniqueArray buffer for item in diffuseMaps do ( print item.bitmap ) -- print diffuseMaps ) fn UnskinnedProp theProp exportAlso = --theProp = a single mesh ( convertto theProp editable_poly --convert mesh to edit poly ResetTransform theProp --reset xforms convertto theProp editable_poly --convert mesh to edit poly again to be sure --move selected to 0,0,0 worldspace in coordsys world theProp.pos = [0,0,0] print "Prop defined and moved to center" -- newRootSystem = BuildRigRootSystem theProp RSTA_buildPropRoot theProp false false -- rootObj = newRootSystem[2][1]--this should be the dummy -- movObj = newRootSystem[2][2]--this should be the mover rootObj = getNodeByName ("Dummy_"+theProp.name) movObj = getNodeByName ("Mover_"+theProp.name) local newRootSystem = #( #(), #() ) newRootSystem[1] = RSTA_getAllChildren rootObj arr:newRootSystem[1]#() if classOf rootObj == Dummy do--we are going to tag the dummy with the filename ( DelFileInfoTags rootObj --delete the tags off the children of the export dummy TagFileNameInfo rootObj --tag mesh information ) for boneDel=1 to newRootSystem[1].count do ( if newRootSystem[1][boneDel] != rootObj then ( if newRootSystem[1][boneDel] != movObj then ( delete newRootSystem[1][boneDel] ) ) ) theProp.parent = movObj--parent the prop to the mover exportMeshes = #() CollectChildren rootObj &exportMeshes includeParent:true includeHidden:true --collect all the skeleton heirarchy appendIfUnique exportMeshes theProp hideByCategory.none() -- unhide all by categry max unhide all -- unhide all clearSelection() select exportMeshes max hide inv if exportAlso == true do ( --hacky export selected as method. needs better way. actionMan.executeAction 0 "40373" -- File: Export Selected ) )--end UnskinnedProp --**************************************************************************************** fn SkinnedProp theProp exportAlso = --theProp = a single mesh ( exportMeshes = #(theProp) skinningBones = #() objectsToShow = #() rootObj = undefined if (isMeshSkinned theProp) == true do--if the mesh is skinned ( skinMod = theProp.modifiers[#Skin] modPanel.setCurrentObject skinMod skinnedBoneCount = skinops.getNumberBones skinMod if skinnedBoneCount > 0 do --if there are bones in the skin modifier ( realBone = getBoneFromSkin skinMod 1 --find a real bone in the scene rootObj = WWfindRootObject realBone --find the root of the heirarchy CollectChildren rootObj &skinningBones includeParent:true includeHidden:true --collect all the skeleton heirarchy ) )--if the mesh is skinned remember it if classOf rootObj == Dummy do--we are going to tag the dummy with the filename ( DelFileInfoTags rootObj --delete the tags off the children of the export dummy TagFileNameInfo rootObj --tag mesh information ) objectsToShow = exportMeshes join objectsToShow skinningBones selectionsets["*CS Export"] = objectsToShow --create selection set of everything hideByCategory.none() -- unhide all by categry max unhide all -- unhide all clearSelection() select objectsToShow max hide inv if exportAlso == true do ( --hacky export selected as method. needs better way. actionMan.executeAction 0 "40373" -- File: Export Selected ) )--end SkinnedProp --attempt to find the export dummy fn findTheDummy = ( characterNode = undefined try ( selectByWildCard "head_000" --there should always be a head mesh if selection.count > 0 then --if we find at least 1 mesh ( obj = selection[1] exportDummy = WWfindRootObject obj clearSelection() exportDummy --pass out the export dummy ) else ( print "I couldn't find my head" ) )catch() )--end findTheDummy fn ShowSkinningAndBones = ( if ((progBar != undefined) and (progBar.isDisplayed)) do (destroyDialog progBar) CreateDialog progBar width:300 Height:30 progBar.prog.color = [225, 110, 35] --green max modify mode exportMeshes = #() skinningBones = #() objectsToShow = #() characterNode = FindTheDummy() --find the export dummy if classOf characterNode == Dummy do--we are going to tag the dummy with the filename ( DelFileInfoTags characterNode --delete the tags off the children of the export dummy TagFileNameInfo characterNode --tag mesh information ) if characterNode != undefined then ( progBar.prog.value = 20 CollectChildren characterNode &exportMeshes includeParent:false includeHidden:true --collect all the skeleton heirarchy if exportMeshes.count > 0 do ( progBar.prog.value = 40 for checkMesh = 1 to exportMeshes.count while skinningBones.count == 0 do ( if (isMeshSkinned exportMeshes[checkMesh]) == true do--if the mesh is skinned ( progBar.prog.value = 60 skinMod = exportMeshes[checkMesh].modifiers[#Skin] modPanel.setCurrentObject skinMod skinnedBoneCount = skinops.getNumberBones skinMod if skinnedBoneCount > 0 do --if there are bones in the skin modifier ( progBar.prog.value = 80 realBone = getBoneFromSkin skinMod 1 --find a real bone in the scene rootObj = WWfindRootObject realBone --find the root of the heirarchy CollectChildren rootObj &skinningBones includeParent:true includeHidden:true --collect all the skeleton heirarchy progBar.prog.value = 100 ) )--if the mesh is skinned remember it ) ) objectsToShow = exportMeshes join objectsToShow skinningBones appendIfUnique objectsToShow characterNode selectionsets["*CS Export"] = objectsToShow --create selection set of everything hideByCategory.none() -- unhide all by categry max unhide all -- unhide all clearSelection() select objectsToShow max hide inv (destroyDialog progBar) ) else ( progBar.prog.color = [255,0,0]--red progBar.prog.value = 100 print "Couldn't find the export dummy!" (destroyDialog progBar) ) exportMeshes--pass out the meshes for the shader change )--end showSkinningAndBones fn VehicleSetup = --copied from vehicle_export_setup.ms ( savePath = theProjectRoot + "/art/animation/resources/vehicles/" maxName = undefined vehicleMesh = #() parentDummy = undefined vehicleSkel = #() everything = #() --this is a neater way of getting all children. alt method to using actionMan.executeAction 0 "40180" fn selectHierarchy whatGeo = ( for p in whatGeo do ( if p.children != undefined do ( selectmore p.children ) ) )--end selectHierarchy maxName = filterstring maxFileName "_" --this should get the prefix of vehicle name which is always vehiclename_skinned.max chassisBoneName = (maxName[1]+"_Skel") try (delete $Dummy01) catch()--try and delete a dummy mesh if it exists already parentDummy = dummy pos:[0,0,0] parentDummy.name = "Dummy01" skel = getNodeByName chassisBoneName if (skel != undefined) then ( skel.parent = parentDummy print (chassisBoneName+" parented to "+parentDummy.name) hideByCategory.none()--unhide everything by category unhide (for obj in objects where obj.ishidden collect obj) --unhide all maxName = filterstring maxFileName "_" meshName = maxName[1] + "_skin" try ( vehicleMesh = getNodeByName meshName ) catch (print ("Couldn't find " +meshName)) hideByCategory.none()--unhide everything by category unhide (for obj in objects where obj.ishidden collect obj) --unhide all try ( selectHierarchy parentDummy --select the children (and children's children) of the parentdummy -- clearSelection() -- select skelArray selectmore parentDummy --add the dummy to the selection selectionsets["*vehicleSkel"] = selection --create selection set of everything vehicleSkel = getCurrentSelection() clearSelection() print "vehicle skeleton found" ) catch (messagebox "Can't Find Parent Dummy" title:"Materials Export Manager") --attempt to select the export dummy everything = vehicleSkel appendIfUnique everything vehicleMesh select everything saveFile = savePath + maxName[1] exportFile saveFile #noPrompt selectedOnly:true using:FBXEXP messageText = maxName[1] + " exported as FBX to " + saveFile + ".fbx" messageBox messageText title:"Materials Export Manager" ) else ( messageBox "Selected vehicle has no skeleton." title:"Materials Export Manager" ) )--end vehicleSetup --function for getting the shader/material values and storing them fn SwitchRageToStd matID = ( if classof mlib[MatID] == Multimaterial then --if the material is a multisub then we want to look in it ( for SubID = 1 to mlib[MatID].numSubs do --for every multisub in this material ( if classof mlib[matid][subid] == Rage_Shader then ( varValue = ""--set an undefined value for the bitmap path for x=1 to RstGetVariableCount mlib[matid][subid] do ( --if the variable type is texmap, the map type is diffuse and the path is not undefined if (uppercase (RstGetVariableType mlib[matid][subid] x)) == "TEXMAP" and (findstring (uppercase (RstGetVariableName mlib[matid][subid] x)) "DIFFUSE TEXTURE") != undefined and (RstGetVariable mlib[matid][subid] x) != "" do ( varValue = RstGetVariable mlib[matid][subid] x--store the bitmap path ) ) mlib[matid][subid] = Standardmaterial () --change it to a standard material mlib[matid][subid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader mlib[matid][subid].showInViewport = true ) else ( if classof mlib[matid][subid] == Standardmaterial then ( if mlib[matid][subid].diffusemap != undefined do ( varValue = mlib[matid][subid].diffusemap.filename if varValue != undefined do ( mlib[matid][subid] = Standardmaterial () --change it to a standard material mlib[matid][subid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader mlib[matid][subid].showInViewport = true ) ) ) else() ) ) ) else ( if classof mlib[matid] == Rage_Shader then ( varValue = ""--set an undefined value for the bitmap path for x=1 to RstGetVariableCount mlib[matid] do ( --if the variable type is texmap, the map type is diffuse and the path is not undefined if (uppercase (RstGetVariableType mlib[matid] x)) == "TEXMAP" and (findstring (uppercase (RstGetVariableName mlib[matid] x)) "DIFFUSE TEXTURE") != undefined and (RstGetVariable mlib[matid] x != "") do ( varValue = RstGetVariable mlib[matid] x--store the bitmap path ) ) mlib[matid] = Standardmaterial () --change it to a standard material mlib[matid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader mlib[matid].showInViewport = true ) else ( if classof mlib[matid] == Standardmaterial then ( if mlib[matid].diffusemap != undefined do ( varValue = mlib[matid].diffusemap.filename if varValue != undefined do ( mlib[matid] = Standardmaterial () --change it to a standard material mlib[matid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader mlib[matid].showInViewport = true ) ) ) else() ) ) )--end switchRageToStd --function to filter selection and switch materials fn SortAndSwitch meshesToSort = --meshesToSort = an array of objects ( if ((progBar != undefined) and (progBar.isDisplayed)) do (destroyDialog progBar) CreateDialog progBar width:300 Height:30 progBar.prog.color = [10,210,10] --green meshesToChange = #() if meshesToSort.count > 0 do ( for allSel=1 to meshesToSort.count do ( if superClassOf meshesToSort[allSel] == GeometryClass do append meshesToChange meshesToSort[allSel] ) if meshesToChange.count > 0 do ( print "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" print "Starting Texture Swtich" startTimer = timestamp() print ("Converting "+ (meshesToChange.count as string) + " mesh materials.") for selMesh=1 to meshesToChange.count do ( if meshesToChange[selMesh].material != undefined do ( mlib[24] = meshesToChange[selMesh].material SwitchRageToStd 24 meshesToChange[selMesh].material = mlib[24] ) progBar.prog.value = ((100* selMesh)/meshesToChange.count) ) endTimer = timeStamp() print "Texture Switch Complete" format "Time taken: %s\n" ((endTimer - startTimer) / 1000.0) print "^^^^^^^^^^^^^^^^^^^^^^" ) ) (destroyDialog progBar) )--end sortAndSwitch --function for writing out the selection sets to a text file fn WriteSelectionSets = ( everything = #() outputFolder = maxfilepath --output folder is the same as the max file outputFile = outputFolder + "SelectionSets.txt" --save the file as "SelectionSets.txt" selectionSetFile = createFile outputFile --now we make the text file using the above settings --fileHeadText = ("Created on " + localtime) --print fileHeadText to: selectionSetFile --write the system time to the text file for ss = 1 to selectionsets.count do ( singleSelSet = #(infoText = ("Selection Set " + ss as string + " of " + selectionsets.count as string)) --some header information selSetName = SelectionSets[ss].name --the name of the selection set append singleSelSet selSetName matchSS = for obj in SelectionSets[ss] collect obj.name --turn sel.set into array append singleSelSet matchSS append everything singleSelSet ) print everything to: selectionSetFile close selectionSetFile --housekeeping. this closes the txt file )--end writeSelectionSets --function to setup map for cs export --copied code from cs_enviroment_setup.ms fn CSMapExport = ( exportOk = false --Unhide & unfreeze the dummy01 node max unhide all max unfreeze all --Select the original scene root, it can be called either Dummy01 or Dummy001 try( select $Point01 $.name = "PointOrig" )catch(format ("couldn't find $point01\n")) try( select $Point001 $.name = "PointOrig" )catch(format ("couldn't find $point01\n")) if $PointOrig != undefined then ( --Copy the "Point Orig" and rename Copy $ select $PointOrig001 $.name = "SetRoot" --Set selection filter to select the geo and parent selection to the setroot setSelectFilter 2 max select all $.parent = $SetRoot --Return Selection filter to all SetSelectFilter 1 --Clear the selection clearSelection() --Create "PointZerod2" Point pos:[0,0,0] isSelected:on $.name = "PointZerod2" --Align Setroot to "PointZerod2" select $SetRoot $.pos = $PointZerod2.pos --Parent the "PointZerod2" & "Point Orig" to the SetRoot select $PointZerod2 $.parent = $SetRoot select $PointOrig $.parent = $SetRoot --Clear the selection clearSelection() --select the "PointOrig" & Get offset information select $PointOrig offsetposition = $PointOrig.pos Positionfilter = (offsetposition as string) Position_offset_values = filterstring Positionfilter "[ ]" PointOrigangle = $PointOrig.rotation as eulerAngles offsetrotation= PointOrigangle.Z Rotation_offset_values = (offsetrotation as string ) --Time & user stamp timedate = localtime Updatedby = sysInfo.username Filename = maxFileName as string Setname = filterString Filename "." format ("Attempting to output offset file...\n") -- create an offset co-ordinate file makeDir @"X:\gta5\art\animation\resources\sets\Offsets" output_name = ("X:\\gta5\\art\\animation\\resources\\sets\\Offsets\\"+ Setname[1] +".log") outputFile = createfile output_name format (("<<<<<< " +Setname[1] +" >>>>>>" )+"\n") to:outputFile format (("Last updated by " + Updatedby + " on the " + timedate)+"\n") to:outputFile format (("" )+"\n") to:outputFile format (("Position Offset = " + Position_offset_values[1] )+"\n") to:outputFile format (("Rotation Offset = " + Rotation_offset_values )+"\n") to:outputFile close outputFile format (output_name+" created.\n") exportOk = true ) else ( messagebox ("Couldn't prep and export map as Point001/point01 not found. \n") exportOk = false ) return exportOk )--csMapExport fn PrepareProp exportAlso = ( if selection.count == 1 then ( thisProp = getCurrentSelection() --=========================================================================================================================== --a section to handle gun magazine meshes - bug 808586 gunMag == false propName = upperCase thisProp[1].name --get the prop name filterPropName = filterString propName "_" --filter the name for breaks shortPropName = #() --an array to hold the shortened filter data for x=1 to filterPropName.count do (append shortPropName (subString filterPropName[x] 1 3)) magCheck = findItem shortPropName "MAG" if magCheck !=0 do (if filterPropName[magCheck].count == 4 do gunMag = true) --=========================================================================================================================== if ((isMeshSkinned thisProp[1]) == true) and (gunMag != true) then--if the mesh is skinned ( print "Preparing skinned prop" thisProp = getCurrentSelection() SortAndSwitch thisProp SkinnedProp thisProp[1] exportAlso ) else ( if queryBox "This appears to be an unskinned prop.\r\nI will attempt create a rig root setup for it.\r\nDo you want to continue?" beep:false title:"Materials Export Manager" do ( print "Preparing unskinned prop" thisProp = getCurrentSelection() SortAndSwitch thisProp UnskinnedProp thisProp[1] exportAlso ) ) ) else (messageBox "Please run with only one object selected.") ) fn PrepareCharacter = ( print "Preparing character" local pedMeshes = ShowSkinningAndBones() SortAndSwitch pedMeshes WriteSelectionSets() -- addDummyData() RSTA_addDummyData() ) fn PrepareExpressions = ( print "Preparing expressions" filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/usefulScripts/RSTA_cleanExpressionControllersForMotionBuilder.ms") --from "X:\gta5\tools\wildwest\script\3dsMax\Characters\Rigging\riggingToolsGUI.ms" lines 154 -> 155 filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/findExpressionObjects.ms") print "Expression set Created" exprItems = #() selCount = getNumNamedSelSets() for i = selCount to 1 by -1 do ( if getNamedSelSetName i == "*expressionsToExport" then ( setItems = getNamedSelSetItemCount i for a = 1 to setItems do ( thisItem = getNamedSelSetItem i a appendIfUnique exprItems thisItem ) ) ) select exprItems --from "X:\gta5\tools\wildwest\script\3dsMax\Characters\Rigging\ExpressionExporter\expressionGUI.ms" lines 161 -> 164 filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/ExpressionExporter/objectOutput.ms") filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/ExpressionExporter/expressionOutputXML.ms") print "Expressions saved" local dummyObj = getNodeByName "Dummy01" local exprFile = undefined local thisPath = maxFilePath if thisPath != undefined do ( if maxfileName != undefined do ( local thisMaxFile = (filterstring (maxFileName as string) ".") thisMaxFile = thisMaxFile[1] local output_nameXML = (thisPath+thisMaxFile+"_RSNXML.xml") if (doesFileExist output_NameXml) == true then ( exprFile = output_nameXML ) ) ) if dummyObj != undefined do ( setUserProp dummyObj "exprFile" (exprFile as string) ) ) fn rsta_findObjectsToKeep charDummy = ( /** WILL FIND ALL CHILDREN OF NODES IN NODES TO KEEP AND ENSURE THAT THESE ARE PASSED THROUGH AS A SELECTION THIS CAN THEN BE USED TO FILTER WHAT WE TEMPORARILY DELETE FROM THE SCENE. **/ objectsToKeep = #() nodesToTest = #( charDummy, "FaceFX", "Ambient_UI", "Dummy01", "faceControls_OFF", "FacialAttrGUI", "facialRoot_C_OFF", "TEXT_Normals", "WRINKLES_TEXT" ) for obj in objects do ( if substring obj.name 1 4 == "RECT" do ( appendIfUnique nodesToTest obj.name ) ) for item in nodesToTest do ( thisNode = getNodeByName item if thisNode != undefined then ( append objectsToKeep thisNode objectsToKeep = RSTA_getAllChildren thisNode arr:objectsToKeep#() ) else ( format ("Couldn't find "+(item as string)+"\n") ) ) return objectsToKeep ) fn rsta_exportFbx fbxFileName fbxVer exportSelected = ( if fbxVer == 2010 then ( format ("Exporting as fbx 2010\n") --think i need to call the import here pluginManager.loadClass FBXEXP fbxExporterSetParam "FileVersion" "FBX 201000" exportFile fbxFileName #noPrompt selectedOnly:exportSelected using:FBXEXP ) else ( if fbxVer == 2012 then ( version = 2012 format ("Exporting as fbx 2012\n") pluginManager.loadClass FBXEXP fbxExporterSetParam "FileVersion" "FBX201200" exportFile fbxFileName #noPrompt selectedOnly:exportSelected using:FBXEXP ) else ( format ("Couldn't export fbx file as version was set to "+(fbxVer as string)+"\n") messagebox ("Couldn't export fbx file as version was set to "+(fbxVer as string)+"\n") beep:true title:"Save Error!" ) ) ) fn PrepAndExportCharacter = ( start = timestamp() local fbxFileName = undefined undo label:"Prep and Epxort Character" on( --first off we need to pick the name and location of the fbx file to save fbxFileName = getSaveFileName caption:"FBX File" types:"FBX File (*.FBX)|*.fbx|All Files (*.*)|*.*|" if fbxFileName != undefined then ( --first off remove any template heads. filein (RsConfigGetWildWestDir() +"script\\3dsMax\\Characters\\Rigging\\ambientFacial\\removeGuideHead.ms") --now we will delete unselected nodes charDummy = findTheDummy() --format ("charDummy: "+(charDummy as string)+"\n") selArray = rsta_findObjectsToKeep charDummy.name select selArray objArray = objects as array objToDelete = #() for o = objArray.count to 1 by -1 do ( obj = objArray[o] fnd = finditem selArray obj if fnd == 0 then ( --format ("Couldn't find "+obj.name+" in selArray\n") append objToDelete obj ) ) delete objToDelete PrepareCharacter() PrepareExpressions() rageMaterials = rsta_NukeMaterials true --NOW WE CAN EXPORT --now if the character has an ambient ui then it needs to be exported as fbx2010 otherwise 2012 ambientUINode = getNodeByName "Ambient_UI" local version = undefined if ambientUINode != undefined then ( fbxVer = 2010 rsta_exportFbx fbxFileName fbxVer false ) else ( fbxVer = 2012 rsta_exportFbx fbxFileName fbxVer false ) ) else ( format ("No valid fbx file specified.") ) ) format ("Exporting. This can take a little while...\n") --now we can undo everytihng. max undo format ("Scene reset to initial state.\n") fndFbx = doesFileExist fbxFileName end = timestamp() if fndFbx == true then ( format ("Exported to "+fbxFileName+"\n") format "Processing Prepare & Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exported to "+fbxFileName+"\n") beep:true title:"Success!" ) else ( format "Processing Prepare & Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exporting appears to have failed. Please see the listener.") beep:true title:"WARNING!" ) ) -- fn PrepAndExportVehicle genType = fn PrepAndExportVehicle = ( start = timestamp() local fbxFileName = undefined undo label:"Prep and Export Vehicle" on( selectedVehicle = selectByName title:"Pick Vehicle skin mesh." showHidden:true driver = selectedVehicle[1] format "You selected Vehicle:'%'!\n" driver.name -- if selection.count == 1 then if driver != undefined then ( select driver format ("Exporting "+driver.name+"\n") if driver.modifiers[#Skin] != undefined then ( --first off we need to pick the name and location of the fbx file to save fbxFileName = getSaveFileName caption:"FBX File" types:"FBX File (*.FBX)|*.fbx|All Files (*.*)|*.*|" if fbxFileName != undefined then ( --now we will delete unselected nodes local mainName = filterstring driver.name "_" mainName = mainName[1] -- genType = (findString (toLower(obj.name)) "_ng_") -- local lwrName = toLower(driver.name) -- genType = findstring lwrName "_ng_" local selArray = #() --format ("charDummy: "+(charDummy as string)+"\n") -- append selArray driver -- local skelRootNode = undefined -- if genType == undefined then -- ( -- format ("Prepping as last gen.\n") skelRootNode = getNodeByName (mainName+"_"+"skel") -- ) -- else -- ( -- format ("Prepping as next gen.\n") -- skelRootNode = getNodeByName (mainName+"_"+"ng") -- ) skelArray = undefined if skelRootNode != undefined do ( append selArray skelRootNode selArray = RSTA_getAllChildren skelRootNode arr:selArray#() skelArray = deepcopy selArray ) append selArray driver -- select selArray objArray = objects as array objToDelete = #() for o = objArray.count to 1 by -1 do ( obj = objArray[o] fnd = finditem selArray obj if fnd == 0 then ( --format ("Couldn't find "+obj.name+" in selArray\n") append objToDelete obj ) ) -- select objToDelete delete objToDelete select selArray -- PrepareVehicle driver skelArray local parentDummy = dummy pos:[0,0,0] parentDummy.name = "Dummy01" skelRootNode.parent = parentDummy rageMaterials = rsta_NukeMaterials true true --NOW WE CAN EXPORT --now if the character has an ambient ui then it needs to be exported as fbx2010 otherwise 2012 fbxVer = 2012 rsta_exportFbx fbxFileName fbxVer false format ("Exporting. This can take a little while...\n") --now we can undo everytihng. max undo format ("Scene reset to initial state.\n") fndFbx = doesFileExist fbxFileName end = timestamp() if fndFbx == true then ( format ("Exported to "+fbxFileName+"\n") format "Processing Prepare & Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exported to "+fbxFileName+"\n") beep:true title:"Success!" ) else ( format "Processing Prepare & Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exporting appears to have failed. Please see the listener.") beep:true title:"WARNING!" ) ) else ( format ("No valid fbx file specified.") ) ) else ( format ("No skin modifier found on "+driver.name+"\n") messagebox ("No skin modifier found on "+driver.name+"\n") beep:true title:"WARNING!" ) ) else ( format "Please select only your vehicle mesh." messagebox "Please select only your vehicle mesh." beep:true title:"Warning" ) ) ) fn EnvSetupPrepMapAndExport = ( start = timestamp() local fbxFileName = undefined undo label:"Prep and Export Map" on( --first off we need to pick the name and location of the fbx file to save fbxFileName = getSaveFileName caption:"FBX File" types:"FBX File (*.FBX)|*.fbx|All Files (*.*)|*.*|" if fbxFileName != undefined then ( rsta_NukeMaterials true true -- PrepareMap() filePath = "//depot/gta5/art/animation/resources/sets/Max_Files/" maxFile = filterString fbxFileName "." maxFile = (maxFile[1]+".max") if maxFile != undefined then ( saveMaxFile maxFile exportOk = CSMapExport() if exportOk == true do ( format ("Exporting as fbx 2012\n") fbxVer = 2012 rsta_exportFbx fbxFileName fbxVer false format ("Exporting. This can take a little while...\n") --now we can undo everytihng. max undo format ("Scene reset to initial state.\n") fndFbx = doesFileExist fbxFileName end = timestamp() if fndFbx == true then ( format ("Exported to "+fbxFileName+"\n") format "Processing Setup Prep and Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exported to "+fbxFileName+"\n") beep:true title:"Success!" ) else ( format "Processing Setup Prep and Export took % seconds\n" ((end - start) / 1000.0) messagebox ("Exporting appears to have failed. Please see the listener.") beep:true title:"WARNING!" ) ) ) else ( format ("No max file name set") ) ) else ( format ("No valid fbx file specified.") ) ) ) fn ImportMapAssets interiorType = ( success = true undo label:"Prep Map Data" on( viewpt = viewport.setLayout #layout_1 viewport.SetRenderLevel #wireframe containerFileName = undefined if interiorType == false then ( containerFileName = getOpenFileName caption:"Container File" types:"Container File (*.MAXC)|*.maxc|All Files (*.*)|*.*|" ) else ( containerFileName = getOpenFileName caption:"Interior File" types:"Interior File (*.MAX)|*.max|All Files (*.*)|*.*|" ) if containerFileName != undefined then ( format ("Picked "+containerFileName+"...\n") if interiorType == false then ( cont1 = Containers.CreateInheritedContainer containerFileName cont1.MakeUnique() format "Made Unique\n" --now unlink for obj in objects do ( obj.parent = undefined ) delete cont1 lodObjs = findLodObjects() delete lodObjs objToDelete = #() selArray = #() for obj in objects do ( if superclassof obj != GeometryClass do ( append objToDelete obj ) ) delete objToDelete ) else ( mergemaxFile containerFileName #prompt objToDelete = #() for obj in objects do ( if superclassof obj != GeometryClass then ( append objToDelete obj ) ) delete objToDelete ) for obj in objects do ( convertTo obj Editable_Mesh ) ) else ( format ("No container picked.\n") ) ) if success == false do ( max undo ) messagebox ("Map Assets imported.") beep:true ) fn prepareAndExportProp obj = ( success = false undo label:"Prep and Export prop" on( fbxFileName = getSaveFileName caption:"FBX File" types:"FBX File (*.FBX)|*.fbx|All Files (*.*)|*.*|" if fbxFileName != undefined then ( select obj PrepareProp false fbxVer = 2012 rsta_exportFbx fbxFileName fbxVer true success = true ) else ( format ("No valid fbx file picked.\n") success = false ) ) if success == true do ( format ("Trying to Restore scene state...\n") max undo ) messagebox ("Prop Prepped and exported.") beep:true ) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- fn RSTA_resourcePrepUI = ( --HAD TO TURN THIS INTO A FUNCTION SO WE CAN RESET IT AFTER CREATION OF EXPRESSIONS. --////////////////////////////////////////////////////////////////////////////////////////////// -- UI --////////////////////////////////////////////////////////////////////////////////////////////// if resourcePrep_UI != undefined then destroyDialog resourcePrep_UI rollout resourcePrep_UI "Resource Prep" --this is the main rollout that contains all the tabs and sub rollouts. ( --////////////////////////////////////////////////////////////////////////////// -- VARIABLES --////////////////////////////////////////////////////////////////////////////// local tabHeight = 20 -- local tabHeight = 40 --for if iwe want double tab rows local tabRollouts = #(::rollCharacters,::rollProp,::rollVehicles,::rollMap) -- local expressionSubRolls = #(::subRollNodePick,::subRollExpressionType, ::subRollExpressionText, ::subRollLoadPreset, ::subRollSavePreset) --////////////////////////////////////////////////////////////////////////////// -- CONTROLS --////////////////////////////////////////////////////////////////////////////// dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:resourcePrep_UI.width local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"ExpressionCreate" filename:(getThisScriptFilename()) dotNetControl dnTabs "system.windows.forms.tabControl" width:resourcePrep_UI.width height:tabHeight offset:[-12, 0] subRollout theSubRollout width:(resourcePrep_UI.width - 2) height:(resourcePrep_UI.Height - (dnTabs.height + rsBannerPanel.height))offset:[-12, 0] pos:[-1, dnTabs.pos.y + (tabHeight+ 10)] --////////////////////////////////////////////////////////////////////////////// -- FUNCTIONS --////////////////////////////////////////////////////////////////////////////// fn SetPage index = ( if index > tabRollouts.count do messageBox "invalid tab" for roll in theSubRollout.rollouts do ( removeRollout roll ) AddSubRollout theSubRollout tabRollouts[index] rolledup:false border:true if index == 1 do --ie characters ( -- AddSubRollout theSubRollout expressionSubRolls[1] rolledup:false border:false ) if index == 2 do -- ie prop ( -- AddSubRollout theSubRollout expressionSubRolls[1] rolledup:false border:false ) if index == 3 do --ie vehicles ( -- AddSubRollout theSubRollout expressionSubRolls[1] rolledup:false border:false ) if index == 4 do --ie map ( ) if index != 1 then ( -- subRollNodePick.btnCreateDriverJoystick.enabled = false ) else ( -- subRollNodePick.btnCreateDriverJoystick.enabled = true ) ) --////////////////////////////////////////////////////////////////////////////// -- EVENTS --////////////////////////////////////////////////////////////////////////////// on dnTabs Click do ( local tabNum = dnTabs.SelectedIndex + 1 -- local tabName = tabRollouts[tabNum].name SetPage tabNum ) on resourcePrep_UI open do ( banner.setup() dnTabs.multiline = true --this lets us have multiple lines of tabs for tab in tabRollouts do dnTabs.tabPages.Add tab.title SetPage 1 --now we need to find a previous saved position and apply that if found uiPosFile = RSTA_getUiPosFile() --get the dialogPos file dialogPos = RSTA_DialogPosLoad uiPosFile --get the position form the dialog pos file format ("Attempting to set dialog pos to "+(dialogPos as string)+"\n") SetDialogPos resourcePrep_UI dialogPos ) on resourcePrep_UI close do ( gc light:true ) on resourcePrep_UI moved position do ( uiPosFile = RSTA_getUiPosFile() --get the dialogPos file RSTA_DialogPosRec resourcePrep_UI uiPosFile ) ) rollout rollCharacters "Characters" ( button btnPrepareAndExportCharacter "Prepare & Export" width:(resourcePrep_UIWidth - 20) tooltip:"Prepare meshes, expressions, shaders and then export." button btnPrepareCharacter "Prepare Character" width:(resourcePrep_UIWidth - 20) tooltip:"Prepare meshes and shaders" button btnPrepareExpressions "Prepare Expressions" width:(resourcePrep_UIWidth - 20) button btnNukeMaterials "Nuke Materials" width:(resourcePrep_UIWidth - 20) button btnRestoreMaterials "Restore Materials" width:(resourcePrep_UIWidth - 20) on btnPrepareAndExportCharacter pressed do ( PrepAndExportCharacter() ) on btnPrepareCharacter pressed do ( PrepareCharacter() ) on btnPrepareExpressions pressed do ( PrepareExpressions() ) on btnNukeMaterials pressed do ( rsta_NukeMaterials false true ) on btnRestoreMaterials pressed do ( if rageMaterialsArray != undefined then ( restoreMaterials rageMaterialsArray ) else ( messagebox ("Rage materials have not been stored so we cannot restore them. Sorry\n") beep:true ) ) ) rollout rollProp "Prop" ( button btnPrepareAndExportProp "Prepare & Export Prop" width:(resourcePrep_UIWidth - 20) tooltip:"Prepare props" button btnPrepareProp "Prepare Prop" width:(resourcePrep_UIWidth - 20) tooltip:"Prepare props" button btnNukeMaterials "Nuke Materials" width:(resourcePrep_UIWidth - 20) button btnRestoreMaterials "Restore Materials" width:(resourcePrep_UIWidth - 20) on btnPrepareAndExportProp pressed do ( if selection.count == 1 then ( if superclassof $ == GeometryClass then ( prepareAndExportProp $ ) else ( format ($.name+" is not a valid geometry.\n") messagebox ($.name+" is not a valid geometry.\n") beep:true ) ) else ( format ("Please only pick the prop mesh you wish to export.\n") messagebox ("Please only pick the prop mesh you wish to export.\n") ) ) on btnPrepareProp pressed do ( PrepareProp true ) on btnNukeMaterials pressed do ( rsta_NukeMaterials false true ) on btnRestoreMaterials pressed do ( if rageMaterialsArray != undefined then ( restoreMaterials rageMaterialsArray ) else ( messagebox ("Rage materials have not been stored so we cannot restore them. Sorry\n") beep:true ) ) ) rollout rollVehicles "Vehicles" ( button btnPrepareAndExportVechicle "Prep & Export Vehicles" width:(resourcePrep_UIWidth - 20) button btnPrepareVechicle "Prepare Vehicles" width:(resourcePrep_UIWidth - 20) button btnNukeMaterials "Nuke Materails" width:(resourcePrep_UIWidth - 20) button btnRestoreMaterials "Restore Materials" width:(resourcePrep_UIWidth - 20) on btnPrepareAndExportVechicle pressed do ( PrepAndExportVehicle() ) on btnPrepareVechicle pressed do ( PrepareVehicle() ) on btnNukeMaterials pressed do ( rsta_NukeMaterials false true ) on btnRestoreMaterials pressed do ( if rageMaterialsArray != undefined then ( restoreMaterials rageMaterialsArray ) else ( messagebox ("Rage materials have not been stored so we cannot restore them. Sorry\n") beep:true ) ) ) rollout rollMap "Map" ( local interiorType = false checkbox chkInterior "Interior Asset" default:false button btnImportMapAssets "Import Map Assets" width:(resourcePrep_UIWidth - 20) button btnEnvSetupPrepMapAndExport "Prepare & Export Map" width:(resourcePrep_UIWidth - 20) button btnPrepareMap "Prepare Map" width:(resourcePrep_UIWidth - 20) button btnNukeMaterials "Nuke Materials" width:(resourcePrep_UIWidth - 20) button btnRestoreMaterials "Restore Material" width:(resourcePrep_UIWidth - 20) button btnExportFbx "Export FBX" width:(resourcePrep_UIWidth - 20) on chkInterior changed state do ( interiorType = state ) on btnImportMapAssets pressed do ( ImportMapAssets interiorType ) on btnEnvSetupPrepMapAndExport pressed do ( EnvSetupPrepMapAndExport() ) on btnPrepareMap pressed do ( -- PrepareMap() if maxFileName != undefined then ( CSMapExport() ) else ( messagebox ("Please save your max file and try again.\n") ) ) on btnNukeMaterials pressed do ( rsta_NukeMaterials false true ) on btnRestoreMaterials pressed do ( if rageMaterialsArray != undefined then ( restoreMaterials rageMaterialsArray ) else ( messagebox ("Rage materials have not been stored so we cannot restore them. Sorry\n") beep:true ) ) on btnExportFbx pressed do ( fbxFileName = getSaveFileName caption:"FBX File" types:"FBX File (*.FBX)|*.fbx|All Files (*.*)|*.*|" if fbxFileName != undefined then ( fbxVer = 2012 rsta_exportFbx fbxFileName fbxVer ) else ( format ("No valid fbx file picked.\n") ) ) ) createDialog resourcePrep_UI width:resourcePrep_UIWidth height:resourcePrep_UIHeight style:#(#style_titlebar, #style_border, #style_sysmenu) format ("Regenerating ui...\n") ) RSTA_resourcePrepUI()