Files
gtav-src/tools_ng/dcc/current/max2012/scripts/pipeline/util/substanceFns.ms
T
2025-09-29 00:52:08 +02:00

515 lines
18 KiB
Plaintext
Executable File

--- ROCKSTAR SUBSTANCE FUNCTIONS
-- Useage : Converts substance information that is used on export to create RAGE shaders for game
-- Allan Hayburn
-- Nov 2012
-----------------------------------------------------------------
-- CALLS TO CONVERT A SUBSTANCE SCENE -----
-----------------------------------------------------------------
--rsMaterialHolder = rsSubstanceMaterialHolder() --- This generates the rsMaterialHolder
-- struct that, on create, holds all the substance materials in scene
--rsMaterialHolder.convertSceneToRage() -- Call to convert scene
--rsMaterialHolder.returnSceneToSubstance() -- Call to return scene
filein (rsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms")
filein (RsConfigGetToolsDir()+"dcc/current/max2012/scripts/pipeline/util/p4.ms")
rsSubstanceMappingFile = (RsConfigGetProjBinConfigDir()+"generic/SubstanceMappingTable.xml")
struct rsSubstanceFunctions
(
substanceMappingFile = rsSubstanceMappingFile,
--------------------------------------------------------------------------------------------------------------------------------
-- fn checkRenderedMaps -- does perforce checks for rendered files. will add to new CL.
--------------------------------------------------------------------------------------------------------------------------------
fn checkRenderedMaps files =
(
checkFiles = gRsPerforce.getFileStats files
filesInP4 = #()
submitList = #()
fileNames = #()
checkingP4 = false
for i in 1 to files.count do -- adds the files arg names to array to check in p4
(
append fileNames (getfilenamefile files[i])
)
checknames = #()
for i in 1 to checkFiles.count do -- creates a struct and gets the name of the file for each file in p4
(
theRecordStruct = gRsPerforce.record2struct checkFiles[i]
theFileProps = getpropnames theRecordStruct
doesItHaveHeadRev = finditem theFileProps #headRev
if doesItHaveHeadRev != 0 then
(
append checknames (getfilenamefile theRecordStruct.depotFile)
)
)
for i in 1 to filenames.count do
(
inP4 = finditem checknames filenames[i] -- is our file in p4?
if inP4 == 0 then
(
append submitList files[i] -- if no add to submit list
) else
(
append filesInP4 files[i] -- if yes then checkout dialog
)
)
format "New Files: \n"
for f in submitList do format "%\n" f
format "In P4 Files:\n" filesInP4
for f in filesInP4 do format "%\n" f
if submitList.count > 0 then
(
gRsPerforce.addToChangelistByName "Substance Generated Maps" submitList
checkingP4 = true
)
if filesInP4.count > 0 then
(
checkingP4 = gRsPerforce.readOnlyP4Check filesInP4
)
checkingP4
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn makeRageFromSubstance -- converts to substance shader to rage shader
--------------------------------------------------------------------------------------------------------------------------------
fn makeRageFromSubstance theMaterial theMaps =
(
local theSubstanceSettings = theMaterial.ambientmap
newRageMaterial = rage_shader()
newRageMaterial.name = theMaterial.name
RstSetShaderName newRageMaterial theSubstanceSettings.presetType
theRsVariables = RstGetVariableCount newRageMaterial
for i in 1 to theMaps.count do
(
for ii in 1 to theRsVariables do
(
if (tolower (RstGetVariableName newRageMaterial ii)) == theMaps[i].slot then
(
RstSetVariable newRageMaterial ii theMaps[i].map
)
)
)
newRageMaterial
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn renderSubstanceMaps -- renders the substance maps defined by the preset - if test: = true then it will only generate a list of maps, not render them.
--------------------------------------------------------------------------------------------------------------------------------
fn renderSubstanceMaps theMaterial presetArray dataPairArray iterateVal test:false =
(
format "%\n" theMaterial
local theSubstanceSettings = theMaterial.ambientmap
local rsMaps = #()
local rsPreset = getfilenamefile theSubstanceSettings.presetType
local notfound = true, res
for i = 1 to presetArray.count while notfound do
if presetArray[i].preset == rsPreset then (res = i; notfound = false;)
res
if notfound == false do
(
local theMappings = presetArray[res].mappings
for i in 1 to theMappings.count do
(
local theMap = (tolower theMappings[i].mapping1)
local theMapType = case theMap of
(
"diffusemap":"texture"
"specularmap":"texture"
"bumpmap":"texture"
"specular_levels_out":"float"
"normal_strength":"float"
)
if theMapType == "texture" then
(
local rendertype = case theMap of
(
"diffusemap":theMaterial.diffusemap
"specularmap":theMaterial.SpecularMap
"bumpmap":theMaterial.bumpMap
)
local theSuffix = case theMap of
(
"diffusemap":"_d"
"specularmap":"_s"
"bumpmap":"_n"
)
local theBaseTex = ((substring (getfilenamefile theSubstanceSettings.baseTexture.filename) 1 8)+"_Subst"+iterateVal as string )
local theRsMapFile = (theSubstanceSettings.textureOutputDirectory+theBaseTex+theSuffix+".tif")
if test == true then
(
--theDataPair = datapair BaseTexture:theBaseTex MatArray:(datapair mat:theMaterial texture:theRsMapFile)
--format "--------------------------\n\n%\n\n-------------------------\n\n" theDataPair
) else (
format "Rendering Substance Bitmap:%\n" theRsMapFile
rm = renderMap rendertype size:[1024,1024] fileName:theRsMapFile
rm.gamma = IDisplayGamma.gamma
save rm
)
append rsMaps (datapair Slot:(tolower theMappings[i].mapping2) Map:theRsMapFile)
) else if theMapType == "float" then (
local rendervalue = case theMap of
(
"specular_levels_out":theMaterial.ambientmap.substance.Specular_Levels_Out.x
"normal_strength":theMaterial.ambientmap.substance.Normal_Strength
)
local valArray = (datapair Slot:(tolower theMappings[i].mapping2.mapping2) Map:rendervalue)
append rsMaps valArray
)
)
)
rsMaps
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn makeRagePresetArray -- Generates the list of rage presets that have been defined in the xml file
--------------------------------------------------------------------------------------------------------------------------------
fn makeRagePresetArray =
(
local presetArray = #()
if presetArray == undefined then format "No Preset Array Defined" else
(
if doesfileexist substanceMappingFile == true then
(
xmlDoc = dotnetobject "System.XML.XMLDocument"
xmlDoc.load substanceMappingFile
theEle = xmlDoc.DocumentElement
for i = 0 to theEle.childNodes.count-1 do
(
theObject = theEle.ChildNodes.itemOf[i]
if theObject.attributes.getnameditem "type" != undefined then
(
if ((theObject.GetAttributeNode "type").value) == "preset" then
(
mappingArray = #()
for chld = 0 to theObject.childNodes.count-1 do
(
theMapping = theObject.ChildNodes.itemOf[chld]
if theMapping.name != "#comment" then
(
if ((theMapping.GetAttributeNode "type").value) == "texture" then
(
thePair = (datapair mapping1:(theMapping.GetAttributeNode "mapping1").value mapping2:(theMapping.GetAttributeNode "mapping2").value)
append mappingArray thePair
)
if ((theMapping.GetAttributeNode "type").value) == "float" then
(
local theValues = datapair mapping2:(theMapping.GetAttributeNode "mapping2").value values:#((theMapping.GetAttributeNode "value1").value,(theMapping.GetAttributeNode "value2").value)
thePair = datapair mapping1:(theMapping.GetAttributeNode "mapping1").value mapping2:theValues
-- print thePair
append mappingArray thePair
)
)
)
append presetArray (datapair preset:(theObject.GetAttributeNode "name").value mappings:mappingArray)
)
)
)
)
)
presetArray
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn makePresetList -- Generates the list of rage presets for ui
--------------------------------------------------------------------------------------------------------------------------------
fn makePresetList =
(
presetArray = makeRagePresetArray()
presetlist = #()
for i in 1 to presetArray.count do
(
append presetlist (presetArray[i].preset + ".sps")
)
sort presetlist
presetlist
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn replaceShaderScenObjs -- looks for scene objects with the mat and converts their material
--------------------------------------------------------------------------------------------------------------------------------
fn replaceShaderScenObjs theMat theNewMat=
(
local theObjs = $objects as array
local theMatObjs = #()
for i in 1 to theObjs.count do
(
if theObjs[i].material == theMat then theObjs[i].material = theNewMat
)
theMatObjs
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn findTextures -- finds the given texture in a material
--------------------------------------------------------------------------------------------------------------------------------
fn findTextures ThisTexture =
(
local notfound = true, res = false
if ThisTexture != undefined do
(
if ThisTexture == medit.GetCurMtl() do (res = true; notfound = false;)
texcount = (getNumSubTexmaps ThisTexture)
for i in 1 to texcount do
(
Texture = getSubTexMap ThisTexture i
findTextures (Texture)
)
)
res
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn findParentMaterials -- finds the parent material of a texture
--------------------------------------------------------------------------------------------------------------------------------
fn findParentMaterials =
(
if classof (medit.GetTopMtlSlot (medit.GetActiveMtlSlot() )) != multimaterial then
(
theMaterial = ( medit.GetTopMtlSlot (medit.GetActiveMtlSlot() ))
theParentMaterial = theMaterial
theNum = 1
) else (
theMulti = ( medit.GetTopMtlSlot (medit.GetActiveMtlSlot() ))
submatcount = getNumSubMtls theMulti
for m in 1 to submatcount do
(
if theMulti[m] != undefined do
(
--check the subtextures
subtexcount = getNumSubTexmaps theMulti[m]
for i in 1 to subtexcount do
(
checkThis = findTextures (getSubTexMap theMulti[m] i)
if checkThis == true then
(
theNum = m
theMaterial = theMulti[m]
)
)
)
)
theParentMaterial = theMulti
)
datapair pMaterial:theParentMaterial mMaterial:(datapair mat:theMaterial num:theNum)
)
)
global grsSubstance = rsSubstanceFunctions()
struct rsSubstanceMaterialHolder
(
thePresetArray = undefined,
sceneHasSubstanceMaterials = false,
substanceObjects = #(),
substanceMaterials = #(),
tempMaterials = #(),
textureDataPairs = #(),
func1 = undefined, -- These functions are left undefined so that on create we can leverage functions from the rsSubstanceFunctions struct.
func2 = undefined,
func3 = undefined,
func4 = undefined,
iterateVal = 0,
conversion = false,
--------------------------------------------------------------------------------------------------------------------------------
-- fn checkForSubstanceTexture -- finds any substance texture that is used as an ambient map in the given material
--------------------------------------------------------------------------------------------------------------------------------
fn checkForSubstanceTexture mat =
(
retval = #()
if classof mat != multimaterial then
(
if mat != undefined and hasProperty mat #ambientmap and classof mat.ambientmap == rsSubstance do
(
append retval 1
)
) else
(
for m in 1 to mat.count where mat[m] != undefined AND hasProperty mat[m] #ambientmap AND classof mat[m].ambientmap == rsSubstance do
(
append retval m
)
)
retval
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn findRsSubstanceInScene -- finds any object in the scene that is using a substance texture and adds that to material and object to the lists.
--------------------------------------------------------------------------------------------------------------------------------
fn findRsSubstanceInScene =
(
substanceObjects = #()
substanceMaterials = #()
tempMaterials = #()
textureDataPairs = #()
local theObjs = $objects as array
for i in 1 to theObjs.count do
(
local testMat = checkForSubstanceTexture theObjs[i].material
if testMat.count > 0 then
(
sceneHasSubstanceMaterials = true
isUnique = appendifUnique substanceMaterials theObjs[i].material
if isUnique == true then
(
append tempMaterials (copy theObjs[i].material )
append substanceObjects (datapair Material:(theObjs[i].material as string) objects:#(theObjs[i]))
) else
(
for o in 1 to substanceObjects.count do
(
hasMat =substanceObjects[o].material == (theObjs[i].material as string)
if hasMat == true then append substanceObjects[o].objects theObjs[i]
)
)
)
)
sceneHasSubstanceMaterials
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn convertSceneToRage -- goes through the created lists of materials and objects and converts them to rage shaders.
--------------------------------------------------------------------------------------------------------------------------------
fn convertSceneToRage =
(
local submissionTextures = #()
local theRageMat = undefined
if sceneHasSubstanceMaterials == true then
(
Format "Converting Substance Materials to Rage Shaders:\n"
for m in SubstanceMaterials do
(
if classof m != multimaterial then
(
iterateVal = iterateVal+1
theMaps = (func2 m thePresetArray textureDataPairs iterateVal test:true )
for i in 1 to theMaps.count do
(
if (classof theMaps[i].map) == string then append submissionTextures theMaps[i].map
)
) else
(
theSubMats = (checkForSubstanceTexture m)
for sm in 1 to theSubMats.count do
(
iterateVal = iterateVal+1
theMaps = (func2 m[theSubMats[sm]] thePresetArray textureDataPairs iterateVal test:true )
for i in 1 to theMaps.count do
(
if (classof theMaps[i].map) == string then append submissionTextures theMaps[i].map
)
)
)
)
func3 submissionTextures
iterateVal = 0
for m in 1 to SubstanceMaterials.count do
(
mm = SubstanceMaterials[m]
if classof mm != multimaterial then
(
iterateVal = iterateVal+1
theMaps = (func2 mm thePresetArray textureDataPairs iterateVal test:false )
theRageMat = func4 mm theMaps
for i in 1 to substanceObjects[m].objects.count do
(
substanceObjects[m].objects[i].material = theRageMat
)
) else
(
theSubMats = (checkForSubstanceTexture mm)
for sm in 1 to theSubMats.count do
(
iterateVal = iterateVal+1
theMaps = (func2 mm[theSubMats[sm]] thePresetArray textureDataPairs iterateVal test:false )
theRageMat = func4 mm[theSubMats[sm]] theMaps
mm[theSubMats[sm]] = theRageMat
for i in 1 to substanceObjects[m].objects.count do
(
substanceObjects[m].objects[i].material = mm
)
)
)
)
)
),
--------------------------------------------------------------------------------------------------------------------------------
-- fn returnSceneToSubstance -- reverts any object in list back to a substance shader
--------------------------------------------------------------------------------------------------------------------------------
fn returnSceneToSubstance =
(
if sceneHasSubstanceMaterials == true then
(
for i in 1 to substanceObjects.count do
(
for o in substanceObjects[i].objects do
(
o.material = tempMaterials[i]
)
)
)
),
on create do
(
thePresetArray = (grsSubstance.makeRagePresetArray())
func2 = grsSubstance.renderSubstanceMaps
func3 = grsSubstance.checkRenderedMaps
func4 = grsSubstance.makeRageFromSubstance
max select none
)
)
global rsMaterialHolder = rsSubstanceMaterialHolder()
global ConvertRsSubstance
(try ConvertRsSubstance R1 catch())
Rollout ConvertRsSubstance "RS Substance Conversion"
(
local substancesConverted = false
Button B2 "Convert All Substance To Rage" width:230
Button B3 "Return All Rage to Substance" width:230
on B2 Pressed do (
rsMaterialHolder.convertSceneToRage()
substancesConverted = true
)
on B3 Pressed do (
rsMaterialHolder.returnSceneToSubstance()
substancesConverted = false
)
on R1 open do
(
rsMaterialHolder = rsSubstanceMaterialHolder()
rsMaterialHolder.findRsSubstanceInScene()
)
on R1 oktoclose do
(
if substancesConverted == true then querybox "You have unreverted Substances. Close?"
)
)