Files
2025-09-29 00:52:08 +02:00

602 lines
17 KiB
Plaintext
Executable File

--url:bugstar:463942
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
struct TextureData
(
name,
type,
path,
propTexture,
alpha,
hdsplit,
imgData
)
try( destroyDialog PropHDSplit_UI)catch()
rollout PropHDSplit_UI "Prop HD Splitter"
(
local headers = #("Name", "Type", "Path", "Alpha", "Prop Texture", "Width", "Height", "HDSplit")
local txSizes = #("128", "256", "512", "1024", "2048")
local tcsPathRoot = RsConfigGetTCSMapsRoot()
local regex = dotnetclass "System.Text.RegularExpressions.Regex"
local textures = #()
local listTextures = #()
local feedback = undefined
local changeListNum = undefined
----------------------------------------------------------------------------------
-- CONTROLS
----------------------------------------------------------------------------------
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:PropHDSplit_UI.width
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"PropTexture HDSplitter" filename:(getThisScriptFilename())
dropdownlist ddl_txSize "Min Texture Size:" items:txSizes width:(1000 * 0.5 - 20)
button btn_doAnalysis "Analyse Selected" across:3 align:#left width:(1000 * 0.5 - 20)
button btn_doChanges "Add HDSplit" width:200 offset:[200, 0]
button btn_removeHDSplit "Remove HDSplit" width:200
dotNetControl lstPropList "System.Windows.Forms.DataGridView" align:#center
------------------------------------------------------------------------------------
-- DotNet values:
------------------------------------------------------------------------------------
local textFont, dingFont, textFontBold
local DNcolour = dotNetClass "System.Drawing.Color"
local textCol = (colorMan.getColor #windowText) * 255
local windowCol = (colorMan.getColor #window) * 255
local notLoadedCol = if (windowCol[1] < 128) then (windowCol * 1.5) else (windowCol * 0.85)
local textColour = DNcolour.FromArgb textCol[1] textCol[2] textCol[3]
local backColour = DNcolour.FromArgb windowCol[1] windowCol[2] windowCol[3]
local altBackColour = DNcolour.FromArgb (windowCol[1]-10) (windowCol[2]-10) (windowCol[3]-10)
--local inSceneBackColour = DNcolour.FromArgb windowCol[1] windowCol[2] (windowCol[3]+64)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn arrangeCtrls size:[PropHDSplit_UI.width, PropHDSplit_UI.height] =
(
lstPropList.width = size.x - 25
lstPropList.height = size.y - 90
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn init =
(
lstPropList.SelectionMode = lstPropList.SelectionMode.FullRowSelect
lstPropList.AllowUserToAddRows = false
lstPropList.AllowUserToDeleteRows = false
lstPropList.AllowUserToOrderColumns = true
lstPropList.AllowUserToResizeRows = false
lstPropList.AllowUserToResizeColumns = false
lstPropList.AllowDrop = false
lstPropList.MultiSelect = true
lstPropList.ReadOnly = true
lstPropList.dock = lstPropList.dock.fill
lstPropList.DefaultCellStyle.backColor = backColour
lstPropList.DefaultCellStyle.foreColor = textColour
lstPropList.AlternatingRowsDefaultCellStyle.BackColor = altBackColour
textFont = lstPropList.font
dingFont = dotNetObject "System.Drawing.Font" "Webdings" textFont.size
textFontBold = dotnetobject "system.drawing.font" textFont (dotnetclass "system.drawing.fontstyle").bold
lstPropList.EnableHeadersVisualStyles = false
lstPropList.ColumnHeadersDefaultCellStyle.backColor = backColour
lstPropList.ColumnHeadersDefaultCellStyle.foreColor = textColour
lstPropList.ColumnHeadersDefaultCellStyle.font = textFontBold
lstPropList.ColumnHeadersHeight = 34
lstPropList.RowHeadersVisible = false
--lstPropList.AutoSizeColumnsMode = (dotNetClass "System.Windows.Forms.DataGridViewAutoSizeColumnsMode").AllCellsExceptHeader
startSize = [PropHDSplit_UI.width - 10, PropHDSplit_UI.height - 40]
arrangeCtrls size:startSize
local colNum
--append headers ""
for item in headers do
(
colNum = lstPropList.Columns.add item item
lstPropList.Columns.item[colNum].minimumWidth = 75
lstPropList.Columns.item[colNum].autoSizeMode = (dotNetClass "System.Windows.Forms.DataGridViewAutoSizeColumnMode").AllCellsExceptHeader
)
local firstCol = lstPropList.Columns.item[0]
--local lastCol = lstPropList.Columns.item[colNum]
firstCol.width = 160
--lastCol.AutoSizeMode = lastCol.AutoSizeMode.AllCellsExceptHeader
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getVarTextures mat =
(
varTextures = #()
counter = 1
for i = 1 to (RstGetVariableCount mat) do
(
if (RstGetVariableType mat i) == "texmap" then
(
append varTextures (DataPair var:i subtex:counter)
counter += 1
)
)
varTextures
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getAlphaTexture mat Idx =
(
--get texture count for the material
textureCount = (for i = 1 to (RstGetVariableCount mat) where (RstGetVariableType mat i) == "texmap" collect i).count
--get the var textures lookup
local varTextures = getVarTextures mat
--format "mat:% idx:% count:%\n" mat idx texCount
numTextures = getNumSubTexmaps mat
hasAlpha = if numTextures == (2 * textureCount) then true else false
--print numTextures
if hasAlpha and numTextures > 1 then
(
local textureSlot = (for item in varTextures where (item.var == idx) collect item.subtex)[1]
local alphaTextureSlot = textureCount + textureSlot
local alpha = getSubTexmap mat alphaTextureSlot
if alpha != undefined then
(
return alpha.filename
)
else
(
return ""
)
)
else return ""
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getTexPlusAlpha mat index =
(
rgbTex = RstGetVariable mat index
alphaTex = getAlphaTexture mat index
return (DataPair rgb:rgbTex alpha:alphaTex)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getTexture mat =
(
matTextures = #()
for i = 1 to (RstGetVariableCount mat) do
(
if (RstGetVariableType mat i) == "texmap" then
(
case (RstGetVariableName mat i) of
(
"Diffuse Texture":
(
append matTextures (DataPair type:"Diffuse" texture:(getTexPlusAlpha mat i))
)
"Bump Texture":
(
append matTextures (DataPair type:"Normal" texture:(getTexPlusAlpha mat i))
)
"Specular Texture":
(
append matTextures (DataPair type:"Specular" texture:(getTexPlusAlpha mat i))
)
)
)
)
--return
matTextures
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn isPropTexture tex =
(
return (matchPattern tex pattern:"*Textures\Props*" ignoreCase:true)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn isHDSplitSet texName =
(
--get tcs
tcsPath = tcsPathRoot + (tolower texName) + ".tcs"
if doesFileExist tcsPath == false then
(
gRsPerforce.sync #(tcsPath)
)
if doesFileExist tcsPath == false then return false
xmlDoc = XMlDocument()
xmlDoc.init()
xmlDoc.load ( tcsPath )
xmlRoot = xmlDoc.document.DocumentElement
imageSplitHDNode = xmlRoot.getElementsByTagName "imageSplitHD"
if imageSplitHDNode.count != 1 then return false else return true
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn buildTextureDataObject theTex =
(
txData = TextureData()
txData.name = getFilenameFile theTex.texture.rgb
txData.alpha = getFilenameFile theTex.texture.alpha
txData.type = theTex.type
txData.path = theTex.texture.rgb
txData.propTexture = isPropTexture theTex.texture.rgb
txData.hdsplit = isHDSplitSet (txData.name + txData.alpha)
txData.imgData = openBitmap theTex.texture.rgb
return txData
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn textureUnique tex =
(
local exists = for item in listTextures where item[1] == (getFilenameFile tex) collect item
if exists.count == 0 then return true else return false
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn checkinReminder =
(
messageBox ("Changed tcs are in changelist: " + (changeListNum as String))
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn doAnalysis =
(
lstPropList.Rows.Clear()
textures = #()
listTextures = #()
materialIDs = #()
listMaterialIDs = #()
theTextures = #()
for obj in $selection where superClassOf obj == GeometryClass do
(
--find the textures on the object
objMat = obj.material
matIds = getAppliedMaterials obj
--Check obj has a material
if objMat == undefined then
(
messageBox ("Object: " + obj.name + " Has no material assigned, ignoring.")
continue
)
if classOf objMat != MultiMaterial then
(
theTexList = getTexture objMat
for theTex in theTexList do
(
if theTex.texture.rgb != undefined then
(
if (findItem theTextures theTex.texture.rgb) == 0 then --not seen before
(
append textures (buildTextureDataObject theTex)
append theTextures theTex
)
)
)
)
else
(
for id in matIds do
(
--check for a none material
if objMat[id] == undefined then continue
theTexList = getTexture objMat[id]
for theTex in theTexList do
(
if theTex.texture.rgb != undefined then --try and sync from p4
(
gRsPerforce.sync #(theTex.texture.rgb)
)
if doesFileExist theTex.texture.rgb == false then append theTextures ("MISSING:"+theTex.texture.rgb)
if (findItem theTextures theTex.texture.rgb) == 0 then --not seen before
(
append textures (buildTextureDataObject theTex)
append theTextures theTex.texture.rgb
append materialIDs id
)
)
)
)
)
--test for size
for t=1 to textures.count do
(
local tex = textures[t]
--check their dimensions
--img = openbitmap tex
--rowString = stringstream ""
--ones over 512 on both sides and live in the prop txtures folder prompt to convert to hdsplit texture process.
minTxSize = ddl_txSize.selected as Integer
if tex.imgData == undefined then
(
hasAlpha = if tex.alpha != "" then hasAlpha = true else false
--print tex.alpha
texName = ""
if hasAlpha then
(
texName = tex.name + tex.alpha
)
else
(
texName = tex.name
)
append listMaterialIDs materialIDs[t]
append listTextures #(tex.name, tex.type, tex.path, tex.propTexture, "ERROR", "ERROR", tex.hdsplit)
)
else if tex.imgData.width > minTxSize and tex.imgData.height > minTxSize then --check location
(
--format "% % PropTexture:%" tex.name tex.path tex.propTexture to:rowString
hasAlpha = if tex.alpha != "" then true else false
--print tex.alpha
combinedTexName = ""
if hasAlpha then
(
combinedTexName = tex.name + tex.alpha
)
else
(
combinedTexName = tex.name
)
append listMaterialIDs materialIDs[t]
append listTextures #(combinedTexName, tex.type, tex.path, hasAlpha, tex.propTexture, tex.imgData.width, tex.imgData.height, tex.hdsplit)
)
)
--update ui list
--lst_txResults.items = listTextures
for row=1 to listTextures.count do
(
local thisRow = listTextures[row]
local rowId = lstPropList.Rows.add thisRow
lstPropList.Rows.item[rowId].tag = listMaterialIDs[row]
)
)
-------------------------------
-- Events dear boy
-------------------------------
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btn_doAnalysis pressed do
(
doAnalysis()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btn_doChanges pressed do
(
--get the list selection
selectedItems = lstPropList.selectedRows
selectedItemsIt = selectedItems.getenumerator()
--create new changelist for the changed tcs
if (changeListNum == undefined) then
(
changeListNum = (gRsPerforce.createChangeList "PropHDSplitter Changed TCS Files")
)
while selectedItemsIt.movenext() != false do
(
--if selectedItemsIt.current.cells.item[6].value == false then
--(
local texName = selectedItemsIt.current.cells.item[0].value
local matId = selectedItemsIt.current.tag
--get the tcs for the textures
local tcsPath = tcsPathRoot + (tolower texName) + ".tcs"
--sync latest
gRsPerforce.sync #(tcsPath)
if doesFileExist tcsPath != false then --make sure the tcs is local
(
--print tcsPath
--modify it with <imageSplitHD value="true" />
xmlDoc = XMlDocument()
xmlDoc.init()
xmlDoc.load ( tcsPath )
xmlRoot = xmlDoc.document.DocumentElement
if xmlRoot != undefined then
(
--check if it has the node already
local hasImageHDSplit = RsGetXmlElement xmlRoot "imageSplitHD"
if (hasImageHDSplit != undefined) then
(
--create the imageSplit node
imageSplitHD = xmlDoc.createElement "imageSplitHD"
imageSplitHDAttr = xmlDoc.createAttribute "value"
imageSplitHDAttr.value = "true"
imageSplitHD.setAttributeNode imageSplitHDAttr
--check for existing imageSplit nodes
imageSplitNodes = xmlRoot.getElementsByTagName "imageSplitHD"
if imageSplitNodes.count == 0 then
(
xmlRoot.appendChild imageSplitHD
)
else --lets remove the imageSplit duplicate nodes and replace with a fresh singular one
(
for i = (xmlRoot.childNodes.count - 1) to 0 by -1 do
(
thisNode = xmlRoot.childNodes.itemOf[i]
if thisNode.name == "imageSplitHD" then
(
xmlRoot.removeChild thisNode
)
)
--make sure we have at least one imageSplitHD node added
xmlRoot.appendChild imageSplitHD
)
gRsPerforce.add_or_edit #( tcsPath ) silent:false
xmlDoc.save ( tcsPath )
gRsPerforce.addToChangelist changeListNum tcsPath
)
else
(
--create the imageSplit node
imageSplitHD = xmlDoc.createElement "imageSplitHD"
imageSplitHDAttr = xmlDoc.createAttribute "value"
imageSplitHDAttr.value = "true"
imageSplitHD.setAttributeNode imageSplitHDAttr
xmlRoot.appendChild imageSplitHD
gRsPerforce.add_or_edit #( tcsPath ) silent:false
xmlDoc.save ( tcsPath )
gRsPerforce.addToChangelist changeListNum tcsPath
)
)
)
else
(
if feedback == undefined then feedback = newscript()
format "Couldn't find this tcs file locally or in p4: % matID: % \n" tcsPath matId to:feedback
)
--)
)
--re-analyse the props
doAnalysis()
--remind checkin
checkinReminder()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btn_removeHDSplit pressed do
(
--get the list selection
selectedItems = lstPropList.selectedRows
selectedItemsIt = selectedItems.getenumerator()
--create new changelist for the changed tcs
if (changeListNum == undefined) then
(
changeListNum = (gRsPerforce.createChangeList "PropHDSplitter Changed TCS Files")
)
while selectedItemsIt.movenext() != false do
(
local texName = selectedItemsIt.current.cells.item[0].value
local matId = selectedItemsIt.current.tag
--get the tcs for the textures
local tcsPath = tcsPathRoot + (tolower texName) + ".tcs"
--sync latest
gRsPerforce.sync #(tcsPath)
if doesFileExist tcsPath != false then --make sure the tcs is local
(
--Remove the <imageSplitHD value="true" />
xmlDoc = XMlDocument()
xmlDoc.init()
xmlDoc.load ( tcsPath )
xmlRoot = xmlDoc.document.DocumentElement
if xmlRoot != undefined then
(
local nodeOfInterest = RsGetXmlElement xmlRoot "imageSplitHD"
if nodeOfInterest != undefined then
(
format "tcs: % has node: % REMOVING\n" tcsPath nodeName
--check it out
gRsPerforce.add_or_edit tcsPath
gRsPerforce.addToChangelist changeListNum tcsPath
xmlroot.removechild nodeOfInterest
xmlDoc.save tcsPath
)
)
)
else
(
if feedback == undefined then feedback = newscript()
format "Couldn't find this tcs file locally or in p4: % matID: % \n" tcsPath matId to:feedback
)
)
--re-analyse the props
doAnalysis()
checkinReminder()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on PropHDSplit_UI open do
(
banner.setup()
init()
if gRsPerforce.connected() == false then gRsPerforce.connect()
)
)
createDialog PropHDSplit_UI width:1250 height:550 style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox)