616 lines
16 KiB
Plaintext
Executable File
616 lines
16 KiB
Plaintext
Executable File
filein (RsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms")
|
|
|
|
struct TextureDataStruct
|
|
(
|
|
normFileName,
|
|
normName,
|
|
heightMapName,
|
|
rageShaderDeps = #() --DataPair shadername: shaderType:
|
|
)
|
|
|
|
struct PXMUpgradeStruct
|
|
(
|
|
pxmShaders = for sps in RsGetShaderList() where (matchpattern sps pattern:"*pxm*") collect sps,
|
|
|
|
csvPath = "X:/gta5/Docs/art/Maps/NG/Terrain_normal_textures.csv",
|
|
nxgTexPath = (RsConfigGetArtDir() + "textures/NXG/....bmp"),
|
|
textureList = #(),
|
|
sceneCandidates = #(),
|
|
actionCandidates = #(),
|
|
missingHMMaterials = #(),
|
|
|
|
shaderOriginal = #("terrain_cb_w_4lyr_2tex_blend", "terrain_cb_w_4lyr_2tex_blend_ttn", "terrain_cb_w_4lyr_2tex_blend_tt",
|
|
"terrain_cb_w_4lyr_cm", "terrain_cb_4lyr_2tex", "terrain_cb_4lyr", "terrain_cb_w_4lyr_cm_tnt",
|
|
"terrain_cb_w_4lyr_spec_int", "terrain_cb_w_4lyr_spec", "terrain_cb_w_4lyr"
|
|
),
|
|
|
|
shaderPXM = #("terrain_cb_w_4lyr_2tex_blend_pxm_spm", "terrain_cb_w_4lyr_2tex_blend_pxm_tn_spm", "terrain_cb_w_4lyr_2tex_blend_pxm_tt_spm",
|
|
"terrain_cb_w_4lyr_cm_pxm", "terrain_cb_4lyr_2tex_pxm", "terrain_cb_4lyr_pxm", "terrain_cb_w_4lyr_cm_tnt_pxm",
|
|
"terrain_cb_w_4lyr_spec_int_pxm", "terrain_cb_w_4lyr_spec_pxm", "terrain_cb_w_4lyr_pxm"
|
|
),
|
|
|
|
hmPathRoot = (RsConfigGetArtDir() + "textures/NXG/Terrain_POM/"),
|
|
|
|
matLookup = #(),
|
|
|
|
/***
|
|
Parse the Terrain_normal_textures.csv
|
|
|
|
***/
|
|
fn parseCSV =
|
|
(
|
|
free textureList
|
|
|
|
fh = openfile csvPath
|
|
|
|
while not eof fh do
|
|
(
|
|
local theLine = filterString (tolower(readline fh)) ","
|
|
if theLine[2] != "~" do
|
|
(
|
|
local texData = TextureDataStruct()
|
|
texData.normFileName = theLine[1]
|
|
texData.normName = getFilenameFile theLine[1]
|
|
texData.heightMapName = theLine[2]
|
|
|
|
append textureList texData
|
|
)
|
|
--for item in (filterString (readline fh) ",") collect (trimLeft item)
|
|
--append textureList theLine
|
|
)
|
|
|
|
close fh
|
|
|
|
--print textureList
|
|
|
|
),
|
|
|
|
/***
|
|
Build a lookup for scene bitmaps to the rage_shader materials they use
|
|
|
|
***/
|
|
fn buildMatLookup =
|
|
(
|
|
local bitmaps = getClassInstances Bitmaptexture
|
|
local bitmapNames = for item in bitmaps where (item.fileName != undefined) collect toLower(getfilenamefile item.fileName)
|
|
|
|
--local matLookup = #()
|
|
|
|
--dict = dotnetobject "RSG.MaxUtils.MaxDictionary"
|
|
|
|
local rageMats = getClassInstances Rage_Shader
|
|
|
|
for mat in rageMats do
|
|
(
|
|
local rageBitmapNames = for bm in (RsGetTexPathsFromMat mat) collect (tolower(getFilenameFile bm))
|
|
|
|
for bm in rageBitmapNames do
|
|
(
|
|
local idx = findItem bitmapNames bm
|
|
if (idx != 0) do
|
|
(
|
|
if matLookup[idx] == undefined then
|
|
(
|
|
matLookup[idx] = #(mat)
|
|
)
|
|
else
|
|
(
|
|
appendIfUnique matLookup[idx] mat
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
--print matLookup
|
|
),
|
|
|
|
/***
|
|
Find materials from scene bitmaps
|
|
***/
|
|
fn findMaterials =
|
|
(
|
|
local bitmaps = getClassInstances Bitmaptexture
|
|
local bitmapNames = for item in bitmaps where (item.fileName != undefined) collect toLower(getfilenamefile item.fileName)
|
|
|
|
--match a bitmap against any in the textureList
|
|
for tex in textureList do
|
|
(
|
|
local idx = findItem bitmapNames (toLower (tex.normName))
|
|
|
|
if (idx != 0) then
|
|
(
|
|
--print bitmapNames[idx]
|
|
--local matMatches = for item in refs.dependents bitmaps[idx] where classOf item == Rage_Shader collect item
|
|
local matMatches = matLookup[idx]
|
|
local matShaderMatches = #()
|
|
if matMatches != undefined then
|
|
(
|
|
matShaderMatches = for item in matMatches
|
|
where (findItem shaderOriginal (getFilenameFile(RstGetShaderName item)) != 0) --or (findItem shaderPXM (getFilenameFile(RstGetShaderName item)) != 0)
|
|
collect (DataPair material:item shader:(getFilenameFile(RstGetShaderName item)))
|
|
)
|
|
|
|
tex.rageShaderDeps = matShaderMatches
|
|
)
|
|
)
|
|
),
|
|
|
|
/***
|
|
Filter out any texture data objects in the textureList that have no valid shaders
|
|
***/
|
|
fn getSceneCandidates =
|
|
(
|
|
sceneCandidates = for item in textureList where item.rageShaderDeps.count != 0 collect item
|
|
),
|
|
|
|
|
|
/***
|
|
|
|
|
|
***/
|
|
fn harvestActionCandidates actionNames =
|
|
(
|
|
local materialList = #()
|
|
|
|
for tex in textureList do
|
|
(
|
|
local materialNames = for mat in tex.rageShaderDeps collect mat.material.name
|
|
|
|
local foundOne = false
|
|
for item in materialNames while (foundOne == false) do
|
|
(
|
|
if (findItem actionNames item) != 0 do
|
|
(
|
|
appendIfUnique actionCandidates tex
|
|
foundOne = true
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
|
|
|
|
/***
|
|
If the shader is legacy swap for a pxm version
|
|
and fill in the heightmap slots where we can
|
|
|
|
if it already is a pxm shader then the heightmap slots should be filled where possible
|
|
***/
|
|
fn swapPXM debug:false =
|
|
(
|
|
--dCounter = 1
|
|
for texData in actionCandidates do
|
|
(
|
|
--get the material
|
|
local matList = texData.rageShaderDeps
|
|
format "matList.count: % \n" matList.count
|
|
|
|
for item in matList do
|
|
(
|
|
local mat = item.material
|
|
|
|
local pxmShader = undefined
|
|
|
|
local mapIdx = findItem shaderOriginal item.shader
|
|
if (mapIdx != 0) then
|
|
(
|
|
pxmShader = shaderPXM[mapIdx]
|
|
)
|
|
|
|
--is it already a pxm shader
|
|
local isPXM = undefined
|
|
if (mapIdx == 0) then
|
|
(
|
|
isPXM = (findItem shaderPXM item.shader)
|
|
)
|
|
|
|
|
|
--set the new shader name if we can
|
|
if (pxmShader != undefined) do
|
|
(
|
|
RstSetShaderName mat (pxmShader + ".sps")
|
|
)
|
|
|
|
--find the shadervar
|
|
local normTex = undefined
|
|
for i = 1 to (RstGetVariableCount mat) where ((RstGetVariableType mat i) == "texmap") and (MatchPattern (RstGetVariableName mat i) pattern:"*Bump*") do
|
|
(
|
|
local thisNorm = tolower(getFilenameFile(RstGetVariable mat i))
|
|
local thisNormPath = tolower(getFilenamePath(RstGetVariable mat i))
|
|
|
|
if (thisNorm == texData.normName) do
|
|
(
|
|
--get the path and append the heightmap name
|
|
local hmPath = hmPathRoot + texData.heightMapName + ".bmp"
|
|
format "thisNorm: % normName: % \n" thisNorm texData.normName
|
|
|
|
--replace the normal for the nxg_ version if it exists
|
|
local nxgNormPath = (thisNormPath + "nxg_" + thisNorm + ".bmp")
|
|
--print nxgNormPath
|
|
|
|
if doesFileExist nxgNormPath then
|
|
(
|
|
RstSetVariable mat i nxgNormPath
|
|
)
|
|
|
|
--does that path exist
|
|
if not (doesFileExist hmPath) then --try to sync it
|
|
(
|
|
local success = gRsPerforce.sync #(hmPath)
|
|
if not success then format "couldnt sync texture: % \n" hmPath
|
|
)
|
|
|
|
--set the heightmap tex
|
|
if (not debug) then
|
|
(
|
|
--meditmaterials[dCounter] = mat
|
|
--print (RstGetVariableType mat (i+1))
|
|
--print (RstGetVariableName mat (i+1))
|
|
if (RstGetVariableName mat (i+1) != undefined) and (MatchPattern (RstGetVariableName mat (i+1)) pattern:"Height*") do
|
|
(
|
|
RstSetVariable mat (i+1) hmPath
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
--dCounter += 1
|
|
)
|
|
),
|
|
|
|
fn fixupMissingHM mat =
|
|
(
|
|
if (mat == undefined) do return false
|
|
|
|
--find the shadervar
|
|
local normTex = undefined
|
|
for i = 1 to (RstGetVariableCount mat) where ((RstGetVariableType mat i) == "texmap") and (MatchPattern (RstGetVariableName mat i) pattern:"*Bump*") do
|
|
(
|
|
local rawPath = tolower(RstGetVariable mat i)
|
|
local thisNorm = getFilenameFile rawPath
|
|
local thisNormPath = getFilenamePath rawPath
|
|
|
|
--find the normal and HM for it
|
|
local heightMapName = undefined
|
|
for tex in textureList while (heightMapName == undefined) do
|
|
(
|
|
if (tex.normName == thisNorm) then
|
|
(
|
|
heightMapName = tex.heightMapName
|
|
)
|
|
)
|
|
|
|
if (heightMapName != undefined) then
|
|
(
|
|
--get the path and append the heightmap name
|
|
local hmPath = hmPathRoot + heightMapName + ".bmp"
|
|
format "thisNorm: % heightMapName: % \n" thisNorm heightMapName
|
|
|
|
--replace the normal for the nxg_ version if it exists
|
|
local nxgNormPath = (thisNormPath + "nxg_" + thisNorm + ".bmp")
|
|
--print nxgNormPath
|
|
|
|
if doesFileExist nxgNormPath then
|
|
(
|
|
RstSetVariable mat i nxgNormPath
|
|
)
|
|
|
|
--does that path exist
|
|
if not (doesFileExist hmPath) then --try to sync it
|
|
(
|
|
local success = gRsPerforce.sync #(hmPath)
|
|
if not success then format "couldnt sync texture: % \n" hmPath
|
|
)
|
|
|
|
--set the heightmap tex
|
|
--if (not debug) then
|
|
--(
|
|
--meditmaterials[dCounter] = mat
|
|
--print (RstGetVariableType mat (i+1))
|
|
--print (RstGetVariableName mat (i+1))
|
|
if (RstGetVariableName mat (i+1) != undefined) and (MatchPattern (RstGetVariableName mat (i+1)) pattern:"Height*") do
|
|
(
|
|
RstSetVariable mat (i+1) hmPath
|
|
)
|
|
--)
|
|
)
|
|
)
|
|
),
|
|
|
|
/***
|
|
List any pxm shaders with empty heightmap slots
|
|
or with dummy NXG_DELETE_H.bmp
|
|
|
|
***/
|
|
fn listMissingHM =
|
|
(
|
|
free missingHMMaterials
|
|
local rageMats = for shd in (getClassInstances Rage_Shader) where ((finditem shaderPXM (getFilenameFile((RstGetShaderName shd)))) != 0) collect shd
|
|
|
|
--print rageMats.count
|
|
--now go through and check for any missing heightmap slots
|
|
for mat in rageMats do
|
|
(
|
|
for i = 1 to (RstGetVariableCount mat) where ((RstGetVariableType mat i) == "texmap") and (MatchPattern (RstGetVariableName mat i) pattern:"Height*") do
|
|
(
|
|
if ((RstGetVariable mat i) == "") or (MatchPattern (getFilenameFile(RstGetVariable mat i)) pattern:"*NXG_DELETE_H*" != false) do
|
|
(
|
|
appendifunique missingHMMaterials mat
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
|
|
--/////////////////////////////////////////
|
|
-- UI
|
|
--/////////////////////////////////////////
|
|
--try(destroyDialog PXMUpgradeUI)catch()
|
|
rollout PXMUpgradeUI "POM HeightMap Slot Stuffer" width:300 height:460
|
|
(
|
|
--/////////////////////////////////////////
|
|
-- VARIABLES
|
|
--/////////////////////////////////////////
|
|
local PXMUpgrade = PXMUpgradeStruct()
|
|
local mlbItemMats = #()
|
|
local mlbItems = #()
|
|
local candidateMap = #()
|
|
|
|
--/////////////////////////////////////////
|
|
-- CONTROLS
|
|
--/////////////////////////////////////////
|
|
--dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:PXMUpgradeUI.width
|
|
--local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"CHANGEME" versionNum:1.02 versionName:"Yielding Playground" filename:(getThisScriptFilename())
|
|
timer ctrlState interval:5000 active:false
|
|
|
|
group "Materials"
|
|
(
|
|
multilistbox mlbMaterials height:20
|
|
)
|
|
|
|
group ""
|
|
(
|
|
dotNetControl btnListMissingHM "Button" text:"Missing HM" width:(PXMUpgradeUI.width - 25) height:dnStyle.stdButtonHeight offset:[0, -5]
|
|
dotNetControl btnfixMissingHM "Button" text:"Fix" width:(PXMUpgradeUI.width - 25) height:dnStyle.stdButtonHeight
|
|
)
|
|
|
|
group ""
|
|
(
|
|
dotNetControl btnRefreshList "Button" text:"Refresh" height:dnStyle.stdButtonHeight across:3 align:#left offset:[0, -5]
|
|
dotNetControl btnDoUpgrade "Button" text:"Scene Upgrade" width:160 height:dnStyle.stdButtonHeight offset:[0, -5]
|
|
checkbox chkAll "All" align:#right offset:[0, -2]
|
|
)
|
|
|
|
|
|
|
|
--/////////////////////////////////////////
|
|
-- FUNCTIONS
|
|
--/////////////////////////////////////////
|
|
|
|
/***
|
|
Sync the textures and lookup csv
|
|
***/
|
|
fn syncResources =
|
|
(
|
|
--sync any nextgen textures
|
|
gRsPerforce.sync #(PXMUpgrade.nxgTexPath)
|
|
|
|
--sync latest report
|
|
pushPrompt "Syncing textures..."
|
|
gRsPerforce.sync #(PXMUpgrade.csvPath)
|
|
popPrompt()
|
|
|
|
|
|
)
|
|
|
|
/***
|
|
Refresh material list
|
|
***/
|
|
fn refreshMatList =
|
|
(
|
|
syncResources()
|
|
|
|
PXMUpgrade.parseCSV()
|
|
PXMUpgrade.buildMatLookup()
|
|
PXMUpgrade.findMaterials()
|
|
PXMUpgrade.getSceneCandidates()
|
|
|
|
mlbItemMats = #()
|
|
mlbItems = #()
|
|
mlbMaterials.items = #()
|
|
candidateMap = #()
|
|
|
|
tempItems = #()
|
|
for i=1 to PXMUpgrade.sceneCandidates.count do
|
|
(
|
|
join tempItems PXMUpgrade.sceneCandidates[i].RageShaderDeps
|
|
for j=1 to PXMUpgrade.sceneCandidates[i].RageShaderDeps.count do
|
|
(
|
|
append candidateMap i
|
|
)
|
|
)
|
|
|
|
mlbItemMats = for item in tempItems collect item.material
|
|
mlbItemMats = makeUniqueArray mlbItemMats
|
|
mlbItems = for item in tempItems collect item.material.name
|
|
mlbItems = makeUniqueArray mlbItems
|
|
--print mlbItems
|
|
mlbMaterials.items = mlbItems
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- EVENTS
|
|
--/////////////////////////////////////////
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnListMissingHM click do
|
|
(
|
|
--set style
|
|
dnStyle.setExecuteStyle btnListMissingHM
|
|
|
|
syncResources()
|
|
|
|
--btnDoUpgrade.enabled = false
|
|
chkAll.enabled = false
|
|
|
|
PXMUpgrade.listMissingHM()
|
|
if (PXMUpgrade.missingHMMaterials.count > 0 ) do
|
|
(
|
|
mlbMaterials.items = for item in PXMUpgrade.missingHMMaterials collect item.name
|
|
mlbItemMats = PXMUpgrade.missingHMMaterials
|
|
)
|
|
|
|
--set style
|
|
ctrlState.active = true
|
|
dnStyle.setSuccessStyle btnListMissingHM
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnfixMissingHM click do
|
|
(
|
|
--set style
|
|
dnStyle.setExecuteStyle btnfixMissingHM
|
|
|
|
syncResources()
|
|
|
|
local actionNames = for idx in mlbMaterials.selection collect mlbMaterials.items[idx]
|
|
actionNames = makeUniqueArray actionNames
|
|
|
|
--print actionNames
|
|
|
|
--PXMUpgrade.harvestActionCandidates actionNames
|
|
|
|
local terrainMats = #()
|
|
for mat in PXMUpgrade.matLookup where (mat != undefined) do
|
|
(
|
|
join terrainMats mat
|
|
)
|
|
terrainMats = makeUniqueArray terrainMats
|
|
|
|
for item in actionNames do
|
|
(
|
|
--find the material from its name
|
|
local theMat = undefined
|
|
for mat in terrainMats while (theMat == undefined) do
|
|
(
|
|
if (mat.name == item) then
|
|
(
|
|
theMat = mat
|
|
)
|
|
)
|
|
|
|
--got the mat, now update the HM slots
|
|
PXMUpgrade.fixupMissingHM theMat
|
|
)
|
|
|
|
mlbMaterials.items = #()
|
|
|
|
--set style
|
|
ctrlState.active = true
|
|
dnStyle.setSuccessStyle btnfixMissingHM
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnRefreshList click do
|
|
(
|
|
--set style
|
|
dnStyle.setExecuteStyle btnRefreshList
|
|
|
|
syncResources()
|
|
|
|
btnDoUpgrade.enabled = true
|
|
chkAll.enabled = true
|
|
refreshMatList()
|
|
|
|
--set style
|
|
ctrlState.active = true
|
|
dnStyle.setSuccessStyle btnRefreshList
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on mlbMaterials doubleClicked arg do
|
|
(
|
|
MatEditor.open()
|
|
meditmaterials[1] = mlbItemMats[arg]
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on chkAll changed arg do
|
|
(
|
|
case arg of
|
|
(
|
|
true:mlbMaterials.selection = #{1..mlbMaterials.items.count}
|
|
false:mlbMaterials.selection = #{}
|
|
)
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnDoUpgrade click do
|
|
(
|
|
--set style
|
|
dnStyle.setExecuteStyle btnDoUpgrade
|
|
|
|
--build actionable material list by matching the the selected ui item name to material names
|
|
local actionNames = for idx in mlbMaterials.selection collect mlbMaterials.items[idx]
|
|
actionNames = makeUniqueArray actionNames
|
|
|
|
PXMUpgrade.harvestActionCandidates actionNames
|
|
|
|
--PXMUpgrade.actionCandidates = for item in mlbMaterials.selection collect PXMUpgrade.sceneCandidates[item]
|
|
|
|
--for item in PXMUpgrade.textureList where item.rageShaderDeps.count != 0 do print item
|
|
|
|
PXMUpgrade.swapPXM()
|
|
|
|
--refreshMatList()
|
|
mlbMaterials.selection = #{}
|
|
chkAll.state = false
|
|
|
|
--set style
|
|
ctrlState.active = true
|
|
dnStyle.setSuccessStyle btnDoUpgrade
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- Switch control state on timer trigger
|
|
--/////////////////////////////////////////
|
|
on ctrlState tick do
|
|
(
|
|
dnStyle.setDormantStyle btnListMissingHM
|
|
dnStyle.setDormantStyle btnfixMissingHM
|
|
dnStyle.setDormantStyle btnRefreshList
|
|
dnStyle.setDormantStyle btnDoUpgrade
|
|
ctrlState.active = false
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on PXMUpgradeUI open do
|
|
(
|
|
--banner.setup()
|
|
--set button styles
|
|
dnStyle.initButtonStyle btnListMissingHM
|
|
dnStyle.initButtonStyle btnfixMissingHM
|
|
dnStyle.initButtonStyle btnRefreshList
|
|
dnStyle.initButtonStyle btnDoUpgrade
|
|
windows.processPostedMessages()
|
|
|
|
)
|
|
)
|
|
|
|
--createDialog PXMUpgradeUI |