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