--createNormalSlidersFromMaps --tool for taking user selection of normal maps --then generating animated normal sliders & expressions --Jan 2014 --Matt Rennie ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ filein "rockstar/export/settings.ms" -- This is fast -- Figure out the project theProjectRoot = RsConfigGetProjRootDir() theProject = RSConfigGetProjectName() theWildWest = RsConfigGetWildWestDir() theProjectConfig = RsConfigGetProjBinConfigDir() toolsRoot = RsConfigGetToolsRootDir() -- filein (RsConfigGetWildWestDir() + "script\\max\\Rockstar_North\\character\\Includes\\FN_Rigging.ms") filein (theWildWest + "script/3dsMax/_config_files/Wildwest_header.ms") filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Perforce.ms") -- filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms" ) filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_UI.ms" ) filein (theWildWest + "script/3dsMax/_config_files/Wildwest_header.ms") filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_functions.ms") -- filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_weaponRigging_functions.ms") -- filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_weaponRigging_functions.ms") --HORRIBLE HACK. HAVE TO FILEIN TWICE TO TRY AND HACK AROUND A SCOPE ISSUE WITH FUNCTION ORDERS. -- filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_propRigging_functions.ms") -- filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_propRigging_subRollouts.ms") filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/expressionExport/mrExpression_SpringHack.ms") filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/expressionExport/mrExpression_CutPasteController.ms") filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/expressionExport/mrExpression_Export.ms") filein (theWildWest + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/expressionExport/mrExpression_Import.ms") boneTagMappingXmlFile = (toolsRoot + "/etc/content/animconfig/bone_tags.xml") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ fn RSTA_configureAnimatedNormalShader normalMapArray = ( slidersToBuild = #() for i = 1 to normalMapArray[1].count do ( --from the texture name we can derive which piece of geo this texture is for nameFlt = filterString normalMapArray[7][i] "_" nameString = (nameFlt[1]+"_"+nameFlt[2]) append slidersToBuild nameFlt[2] format ("Looking for "+nameString+"\n") obj = RSTA_getNodeByNameWildcard (nameString+"_U") objName = undefined if obj != undefined then ( objName = (nameString+"_U") ) else ( obj = RSTA_getNodeByNameWildcard (nameString+"_R") objName = (nameString+"_R") ) objNameLength = objName.count format ("objNameLength: "+(objNameLength as string)+"\n") format ("objName: "+(objName)+"\n") matchingObjs = #() --gonna do somethign a bit hacky here to try and find the real version - gonna grab all objects with nameStr in and find the highest poly version! for ob in objects do ( if toLower((substring ob.name 1 objNameLength)) == toLower(objName) do ( append matchingObjs ob ) ) vertCount = 0 for ob in matchingObjs do ( --format ("Testing "+ob.name+"\n") if ob.numverts > vertCount do ( vertCount = ob.numverts obj = ob ) ) mapList = #() for ml = 1 to obj.material.count do ( append mapList ml ) format ("obj:"+(obj as string)+"\n") idList = RsMatGetMapIdsUsedOnObject obj mapList --now what we need to is find which of the material id's has the most faces assigned --this should then allow us to know which is the appropriate material faceid = undefined if classof obj == Editable_mesh then ( faceCount = 0 faceId = 0 for id in idList do ( newFaceSel = #() for f = 1 to obj.numfaces do ( if getFaceMatID obj f == id do ( append newFaceSel f )--end if )--end f loop if newFaceSel.count > faceCount do ( faceCount = newFaceSel.count faceId = id ) ) ) else ( if classof obj == PolyMeshObject do ( faceCount = 0 faceid = 0 for id in idList do ( newFaceSel = #() numFaces = polyOp.getNumFaces obj for f = 1 to numFaces do ( if (polyOp.getFaceMatID obj f) == id do ( append newFaceSel f ) ) if newFaceSel.count > faceCount do ( faceCount = newFaceSel.count faceId = id ) ) ) ) objMat = obj.material --now we have the id we can find the shader IDin objMat if classof objMat == MultiMaterial then ( format ("faceId: "+(faceId as string)+"\n") objMatToUse = objMat[faceId] format ("Relevant material: "+(objMatToUse as string)+"\n") --now we need to use the rage commands to query the shader tpe and only change and configure the norals if its ped.sps or a nomral shader already currShader = RstGetShaderName objMatToUse format ("currShader :"+(currShader as string)+"\n" ) continueShader = false if currShader == "ped.sps" then ( shadertoset = "ped_wrinkle.sps" RstSetShaderName objMatToUse shadertoset continueShader = true ) else ( if currShader == "ped_wrinkle.sps" do ( continueShader = true ) ) if continueShader == true then ( --now we need to add the wrinkles etc shdrParams = RstGetVariableCount objMatToUse wrinkleMasks = #( #( normalMapArray[2][i], normalMapArray[3][i], normalMapArray[4][i], normalMapArray[5][i], normalMapArray[1][i], normalMapArray[8][i] ), #( "Wrinkle Mask 0", "Wrinkle Mask 1", "Wrinkle Mask 2", "Wrinkle Mask 3", "Wrinkle A", "Wrinkle B" ) ) if shdrParams != undefined do ( for sParam = 1 to shdrParams do ( thisParam = RstGetVariableName objMatToUse sParam for wm = 1 to wrinkleMasks[2].count do ( if thisParam == wrinkleMasks[2][wm] do ( print ("wrinkleMasks[1]["+(wm as string)+"]: "+(wrinkleMasks[1][wm] as string)) --now we need to set this parameter to be wrinkleMasks[1][wm] RstSetVariable objMatToUse sParam wrinkleMasks[1][wm] ) ) ) ) ) else ( format ("Skipping shader creation for "+normalMapArray[7][i]+" as the shader is not ped.sps or ped_wrinkle.sps\n") ) ) else ( format ("Multimaterial not found\n") ) ) return slidersToBuild ) fn RSTA_ConfigureWrinkleSliderExpression normalMapArray = ( firstPic = selection as array --first off we'll store all objects in the scene max select all origArray = selection as array --now we need to hook up the expression --WE'LL USE THE FUNCTIONS FROM MREXPRESSION HERE exprXml = "X:/gta5/art/peds/Skeletons/pedBodyWrinkleUpper/pedBodyWrinkleUpper.xml" --set of wrinkle slider expressions saved from Michael preserveExistingExpressionsVal = false forceDeleteSprings = false startObjects = objects as array RSTA_LoadExpressions exprXml forceDeleteSprings preserveExistingExpressionsVal true postExpressionObjects = objects as array newObjs = #() for post in postExpressionObjects do ( -- newObj = false -- for pre in startObjects do -- ( -- if post == pre do -- ( -- newObj = true -- ) -- ) -- -- if newObj == true do -- ( -- append newObjs post -- ) newObj = finditem startObjects post if newObj == 0 do ( append NewObjs post format (post.name+" is a new object\n") ) ) --now we need to setup the shader. slidersToBuild = RSTA_configureAnimatedNormalShader normalMapArray --now we need to only leave the wrinkle shaders for the maps we have. for i = 1 to slidersToBuild.count do ( sliderNumber = slidersToBuild[i] for ind = newObjs.count to 1 by -1 do ( obj = newObjs[ind] if obj.name == ("RECT_"+"WM_Upper_"+sliderNumber) do ( --format ("KEEPING "+obj.name+"\n") deleteItem newObjs ind ) if obj.name == ("TEXT_"+"WM_Upper_"+sliderNumber) do ( --format ("KEEPING "+obj.name+"\n") deleteItem newObjs ind ) if obj.name == ("WM_Upper_"+sliderNumber) do ( --format ("KEEPING "+obj.name+"\n") deleteItem newObjs ind ) if obj.name == "UPPER_WRINKLES_TEXT" do ( deleteItem newObjs ind ) if obj.name == "WRINKLES_TEXT" do ( deleteItem newObjs ind ) ) ) for i = newObjs.count to 1 by -1 do ( --format ("Removing "+newObjs[i].name+"\n") delete newObjs[i] ) ) fn RSTA_pickNormalMaps = ( normalArray = #( #(), --WrinkleA Map #(), -- A1 Mask #(), -- A2 Mask #(), --B1 Mask #(), -- B2 Mask #(), --component #(), --name #() --WrinkleB Map ) --wrinkle maps will always be in /textures/HighRes/wrinkleMaps/ fileFilter = "TGA Files (*_WA.tga)|*_WA.tga|All Files (*.*)|*.*" titleBar = "Select One Or More WrinkleMAP files" initialDir = (maxfilepath+"textures") dirExists = doesFileExist initialDir if dirExists == false do ( initialDir = maxfilePath ) format ("Using texturePath: "+initialDir+"\n") -- local wrinkleMaps = RSgetOpenFilenames caption:titleBar filename:"" types:fileFilter wrinkleMaps = RSTA_multiFileSelector fileFilter titleBar initialDir --wrinkle masks will always be in /textures/HighRes/wrinkleMasks/ fileNotFound = undefined if wrinkleMaps != undefined do ( for wMap in wrinkleMaps do ( append normalArray[1] wMap bMap = ((substring wMap 1 ((wMap.count)- 5)+"B.tga")) format ("bMap: "+(bMap as string)+"\n") append normalArray[8] bMap --now we need to find the A and B masks --so we get the filePath of wMap --then look for the corrseponding wrinkleMasks folder --format ("wMap: "+(wMap as string)+"\n") wMapFileName = filenameFromPath wMap --format ("wMapFileName: "+(wMapFileName as string)+"\n") wMapPath = getFilenamePath wMap --format ("wMapPath: "+(wMapPath as string)+"\n") --ok now we need to strip back wMapPath to substitue wrinkleMasks s2 = "wrinkleMaps" s3 = "wrinkleMasks" maskPath = substituteString wMapPath s2 s3 --format ("maskPath: "+(maskPath as string)+"\n") --now we need to do some file name switching --wrinkleMap will be of the form Uppr_000_WA.tga --wrinkle Masks will be of the form Uppr_Normal_000_MA1 mapFilt = filterString wMapFileName "." mapName = mapFilt[1] mapNameFilt = filterString mapName "_" maskAName = (mapNameFilt[1]+"_"+"Normal_") append normalArray[6] mapNameFilt[1] for i = 2 to (mapNameFilt.count - 1) do ( maskAname = (maskAName+mapNameFilt[i]+"_") ) tmpArr = #() append normalArray[7] mapName maskAName1 = (maskPath+maskAName+"M"+"A"+"1.tga") --format ("maskAName1: "+(maskAName1 as string)+"\n") append tmpArr maskAName1 maskAName2 = (maskPath+maskAName+"M"+"A"+"2.tga") --format ("maskAName2: "+(maskAName2 as string)+"\n") append tmpArr maskAName2 maskBName1 = (maskPath+maskAName+"M"+"B"+"1.tga") --format ("maskBName1: "+(maskBName1 as string)+"\n") append tmpArr maskBName1 maskBName2 = (maskPath+maskAName+"M"+"B"+"2.tga") --format ("maskBName2: "+(maskBName2 as string)+"\n") append tmpArr maskBName2 --now we need to check if these files actually exist for i = 1 to tmpArr.count do ( exists = doesFileExist tmpArr[i] if exists == true then ( append normalArray[i+1] tmpArr[i] --format ("appending "+tmpArr[i]+"\n") ) else ( format ("WARNING! "+tmpArr[i]+" not found\n") fileNotFound = false ) ) ) ) returnData = undefined if fileNotFound == undefined then ( returnData = normalArray ) return returnData ) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ if ((createNormalSliderGUI != undefined) and (createNormalSliderGUI.isDisplayed)) do (destroyDialog createNormalSliderGUI) rollout createNormalSliderGUI "Normal Sliders" ( dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:140 local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"PedAnimatedNormalMap" filename:(getThisScriptFilename()) button btnSelectNormals "Select Wrinkle Maps" width:135 height:40 tooltip:"Select your A maps and generate sliders" checkBox chkDebugPrnt "DebugPrint" checked:false tooltip:"Check to enable debug --print output." on createNormalSliderGUI open do ( banner.setup() chkDebugPrnt.state = false debugPrintVal = false ) on chkDebugPrnt changed theState do ( if chkDebugPrnt.state == false then ( debugPrintVal = false ) else ( debugPrintVal = true ) ) on btnSelectNormals pressed do ( normalMaps = RSTA_pickNormalMaps() -- if normalMaps != undefined then if normalMaps[1].count > 0 then ( --ok we can carry on for i = 1 to normalMaps[1].count do ( format ("Wrinkle:"+normalMaps[1][i]+"\n"+"Mask A1:"+normalMaps[2][i]+"\n"+"Mask A2:"+normalMaps[3][i]+"\n"+"Mask B1:"+normalMaps[4][i]+"\n"+"Mask B2:"+normalMaps[5][i]+"\n\n") format ("6:" +normalMaps[6][1]+"\n") format ("7:" +normalMaps[7][1]+"\n") ) -- RSTA_generateNormalSliders normalMaps RSTA_ConfigureWrinkleSliderExpression normalMaps format "DONE!\n" ) else ( format ("Cannot continue as maps not found. Please see the listener.") messagebox ("Cannot continue as maps not found. Please see the listener.") beep:true ) ) ) CreateDialog createNormalSliderGUI width:140 pos:[150, 150]