Files
gtav-src/tools_ng/wildwest/script/3dsMax/Characters/Rigging/createNormalSlidersFromMaps.ms
T
2025-09-29 00:52:08 +02:00

537 lines
15 KiB
Plaintext
Executable File

--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]