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

587 lines
20 KiB
Plaintext
Executable File

-- Additions by Allan Hayburn Jan 15 2013
filein "pipeline/util/RsUniversalLog.ms"
global RsPropagateMaterialsRollout
global gRsPropaMaterialUlogFile = ( RsConfigGetLogDir() + "PropagateMaterials.ulog" )
global gRsPropaMaterialUlog = sRsULog()
try ( destroyDialog RsPropagateMaterialsRollout ) catch ()
struct RsMaxMaterial
(
name = undefined,
matid = undefined,
sps = undefined,
params = #()
)
struct RsMaxObject
(
name = undefined,
handle = undefined,
materials = #()
)
struct RsPropagateMaterials
(
fn storeMaterialData obj mat matid &rsMaxObj = (
local textures = #()
if ( classof mat ) == Rage_Shader then (
if ( RstGetIsAlphaShader mat ) then (
local rsMat = RsMaxMaterial()
rsMat.name = mat.name
rsMat.matid = matid
rsMat.sps = RstGetShaderName mat
local numVars = RstGetVariableCount mat
for varId = 1 to numVars do (
local varName = RstGetVariableName mat varId
local varType = RstGetVariableType mat varId
if varType == "texmap" then (
local diffuseTex = RstGetVariable mat varId
local alphaTex = RstGetAlphaTextureName mat varId
diffuseTex = toLower ( diffuseTex as string )
alphaTex = toLower ( alphaTex as string )
local param = DataPair constantName:varName data:( DataPair diffuseTexture:diffuseTex alphaTexture:alphaTex )
append rsMat.params param
)
)
if rsMat.params.count > 0 then (
append rsMaxObj.materials rsMat
)
)
)
),
fn collectMaterialData obj &sceneData = (
if ( classof obj ) == Editable_Mesh or ( classof obj ) == Editable_Poly then (
local rsObj = RsMaxObject()
rsObj.name = obj.name
rsObj.handle = obj.inode.handle
local mat = obj.material
if mat != undefined then (
if ( classof mat ) == MultiMaterial then (
for matId = 1 to mat.numsubs do (
local subMat = mat[ matId ]
this.storeMaterialData obj subMat matId &rsObj
)
) else (
this.storeMaterialData obj mat undefined &rsObj
)
)
if rsObj.materials.count > 0 then (
append sceneData rsObj
)
)
),
fn getTabs tabLevel = (
local result = ""
for i = 1 to tabLevel do (
result += "\t"
)
result
),
fn createSceneMaterialFile filename sourceFilename sceneData haveRev = (
if sceneData != undefined then (
local fstream = createFile filename
local tabLevel = 1
format "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" to:fstream
format "<scene>\n" to:fstream
format "%<info>\n" ( this.getTabs tabLevel ) to:fstream
tabLevel += 1
format "%<sourceFilename>%</sourceFilename>\n" ( this.getTabs tabLevel ) ( toLower sourceFilename ) to:fstream
format "%<p4revision>%</p4revision>\n" ( this.getTabs tabLevel ) haveRev to:fstream
tabLevel -=1
format "%</info>\n" ( this.getTabs tabLevel ) to:fstream
format "%<objects>\n" ( this.getTabs tabLevel ) to:fstream
tabLevel += 1
for rsObj in sceneData do (
if rsObj != undefined then (
format "%<object name=\"%\" handle=\"%\">\n" ( this.getTabs tabLevel ) rsObj.name rsObj.handle to:fstream
tabLevel += 1
format "%<materials>\n" ( this.getTabs tabLevel ) to:fstream
tabLevel += 1
for rsMat in rsObj.materials do (
format "%<material name=\"%\" matid=\"%\" sps=\"%\">\n" ( this.getTabs tabLevel ) rsMat.name rsMat.matid rsMat.sps to:fstream
tabLevel += 1
for param in rsMat.params do (
format "%<param constantName=\"%\" diffuse=\"%\" alpha=\"%\" />\n" ( this.getTabs tabLevel ) param.constantName param.data.diffuseTexture param.data.alphaTexture to:fstream
)
tabLevel -= 1
format "%</material>\n" ( this.getTabs tabLevel ) to:fstream
)
tabLevel -= 1
format "%</materials>\n" ( this.getTabs tabLevel ) to:fstream
tabLevel -= 1
format "%</object>\n" ( this.getTabs tabLevel ) to:fstream
)
)
tabLevel -= 1
format "%</objects>\n" ( this.getTabs tabLevel ) to:fstream
format "</scene>\n" to:fstream
close fstream
fstream = undefined
gc()
) else (
print "No scene data to export! Wtf..."
)
),
fn exportCurrentSceneMaterials sourceFilename haveRev = (
progressStart "Exporting materials..."
local progress = 0
local sceneData = #()
for obj in objects do (
this.collectMaterialData obj &sceneData
progress += 1
progressUpdate ( 100 * progress / objects.count )
)
this.createSceneMaterialFile ( ( getdir #temp ) + "\\" + ( getFilenameFile sourceFilename ) + ".matxml" ) sourceFilename sceneData haveRev
gRsPropaMaterialUlog.LogMessage ( "Created temporary propagate materials xml file at (" + ( ( getdir #temp ) + "\\" + ( getFilenameFile sourceFilename ) + ".matxml" ) + ")" )
progressEnd()
),
fn importMatXml matxmlFilename = (
local result = undefined
if ( doesFileExist matxmlFilename ) then (
result = #()
local stream = dotNetObject "System.IO.StreamReader" matxmlFilename
local doc = dotNetObject "System.Xml.XmlDocument"
doc.load stream
local root = doc.documentElement
local objectNodes = root.SelectNodes ".//objects/object"
-- Iterate over each object.
for objId = 0 to ( objectNodes.count - 1 ) do (
local objNode = objectNodes.item[ objId ]
local objName = objNode.Attributes.item[ 0 ].value
local objHandle = ( objNode.Attributes.item[ 1 ].value ) as integer
local rsObj = RsMaxObject()
rsObj.name = objName
rsObj.handle = objHandle
local matNodes = objNode.SelectNodes ".//materials/material"
-- Iterate over each material for the object.
for matId = 0 to ( matNodes.count - 1 ) do (
local objMatNode = matNodes.item[ matId ]
local objMatName = objMatNode.Attributes.item[ 0 ].value
local objMatId = ( objMatNode.Attributes.item[ 1 ].value ) as integer
local objMatSps = objMatNode.Attributes.item[ 2 ].value
local rsMat = RsMaxMaterial()
rsMat.name = objMatName
rsMat.matid = objMatId
rsMat.sps = objMatSps
local paramNodes = objMatNode.SelectNodes ".//param"
-- Iterate over each param for the material.
for paramId = 0 to ( paramNodes.count - 1 ) do (
local paramNode = paramNodes.item[ paramId ]
local paramConstantName = paramNode.Attributes.item[ 0 ].value
local paramDiffuseTex = paramNode.Attributes.item[ 1 ].value
local paramAlphaTex = paramNode.Attributes.item[ 2 ].value
if paramAlphaTex == "undefined" then (
paramAlphaTex = undefined
)
local param = DataPair constantName:paramConstantName data:( DataPair diffuseTexture:paramDiffuseTex alphaTexture:paramAlphaTex )
append rsMat.params param
)
append rsObj.materials rsMat
)
append result rsObj
)
root = undefined
stream = undefined
doc = undefined
gc()
) else (
messageBox "The file doesn't exist!" title:"Rockstar"
)
result
),
fn propagate sourceFilename fromRev toRev =
(
gRsPropaMaterialUlog.Init "Propagate Materials" appendToFile:false forceLogFile:gRsPropaMaterialUlogFile
-- Turn off RsRef system.
RSrefAllowUpdate = false
-- Get the file info for the source file.
local fstats = ( gRsPerforce.getFileStats ( sourceFilename ) )[ 1 ]
-- in case "haveRev" or "headRev" = undefined - A.H.
if fstats.Item[ "haveRev" ] != undefined then haveRev = fstats.Item[ "haveRev" ] as integer
if fstats.Item[ "headRev" ] != undefined then headRev = fstats.Item[ "headRev" ] as integer
if toRev > headRev then (
messageBox "Cannot propagate to a file revision greater than the head revision! Aborting." title:"Rockstar"
) else (
clearListener()
local sourceName = getFilenameFile sourceFilename
-- This will be the exported .matxml filename.
local matxmlFilename = ( getDir #temp ) + "\\" + sourceName + ".matxml"
-- Reset max file.
resetMaxFile #noPrompt -- made reset quiet - A.H.
-- Sync to the FROM revision.
gRsPerforce.sync ( sourceFilename + "#" + fromRev as string )
gRsPropaMaterialUlog.LogMessage ( "Synced to version " + fromRev as string + " for file (" + sourceFilename + ")." )
--adding file check - A.H.
checkSyncedFromFile = doesfileExist sourceFilename
if checkSyncedFromFile == false then
(
local msg = "(" + sourceFilename + ") at revision (" + fromRev as string + ") could not be found! Check perforce revision."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
gRsPerforce.sync ( sourceFilename + "#" + toRev as string )
gRsPropaMaterialUlog.validate()
return false
)
local ext = getFilenameType sourceFilename
-- Open the source file.
if ext == ".maxc" then (
local sourceContainer = Containers.CreateInheritedContainer sourceFilename
if sourceContainer != undefined then (
if sourceContainer.CanEditInPlace() then (
sourceContainer.LoadContainer()
sourceContainer.MakeUnique()
if not sourceContainer.IsUnique() then (
local msg = "The container for (" + sourceFilename + ") at revision (" + fromRev as string + ") could not be made unique! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
gRsPropaMaterialUlog.LogMessage "Successfully opened container."
) else (
local msg = "The container for (" + sourceFilename + ") could not be opened! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
) else (
local msg = "Could not inherit the container for (" + sourceFilename + ")! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
) else if ext == ".max" then (
loadMaxFile sourceFilename quiet:true-- made load quiet - A.H.
)
-- Export the scene materials to disk.
this.exportCurrentSceneMaterials sourceFilename fromRev
gRsPropaMaterialUlog.LogMessage "Successfully exported materials."
-- Make sure the .matxml filename exists.
if ( doesFileExist matxmlFilename ) then (
-- Reset the current file.
resetMaxFile #noPrompt
-- Sync to the version of the file we are propagating the materials TO.
gRsPerforce.sync ( sourceFilename + "#" + toRev as string )
gRsPropaMaterialUlog.LogMessage ( "Synced to version " + toRev as string + " for file (" + sourceFilename + ")." )
-- Reopen the TO version of the file.
if ext == ".maxc" then (
local sourceContainer = Containers.CreateInheritedContainer sourceFilename
if sourceContainer != undefined then (
if sourceContainer.CanEditInPlace() then (
sourceContainer.LoadContainer()
if sourceContainer.MakeUnique() then (
sourceContainer.sourceDefinitionFilename = sourceFilename
) else (
local msg = "The container for (" + sourceFilename + ") at revision (" + toRev as string + ") could not be made unique! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
) else (
local msg = "Could not 'Edit in Place' the container for (" + sourceFilename + ")! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
) else (
local msg = "Could not inherit the container for (" + sourceFilename + ")! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
return false
)
) else if ext == ".max" then (
loadMaxFile sourceFilename quiet:true -- made load quiet - A.H.
gRsPropaMaterialUlog.LogMessage ( "Opened file (" + sourceFilename + ")." )
)
-- Import and replace the materials.
local rsObjs = this.importMatXml matxmlFilename
gRsPropaMaterialUlog.LogMessage ( "Successfully imported the propagation material xml file from (" + matxmlFilename + ")." )
if rsObjs != undefined then (
progressStart "Importing materials..."
local progress = 0
for rsObj in rsObjs do (
-- First find the object by handle.
local realObj = maxops.getNodeByHandle rsObj.handle
if realObj != undefined then (
local doContinue = true
-- Check to see if the object was renamed and ask what they'd like to do.
if realObj.name != rsObj.name then (
local msg = "Found an object name mismatch!\n\nObject named (" + rsObj.name + ") in revision (" + fromRev + ") is now named (" + realObj.name + ") in revision (" + toRev + ").\n\nWould you like to propagate materials to this renamed object?"
if ( queryBox msg title:"Rockstar" beep:false ) then (
doContinue = false
)
)
if doContinue then (
if realObj.material != undefined then (
local realMat = realObj.material
if ( classof realMat ) == Multimaterial then (
for prevMat in rsObj.materials do (
if ( findItem realMat.materialIdList prevMat.matid ) != 0 then (
local realSubMat = realMat.materialList[ prevMat.matid ]
if ( classof realSubMat ) == Rage_Shader then (
local spsName = RstGetShaderName realSubMat
local propaMaterialParams = true
if spsName != prevMat.sps then (
local msg = "Found an sps name mismatch between revisions! Attempt to propagate material anyway?\n\nFROM: " + prevMat.sps + "\n\nTO: " + spsName
if ( queryBox msg title:"Rockstar" beep:false ) then (
propaMaterialParams = false
)
)
if propaMaterialParams then (
for param in prevMat.params do (
local numParams = RstGetVariableCount realSubMat
for paramId = 1 to numParams do (
local paramName = RstGetVariableName realSubMat paramId
if paramName == param.constantName then (
RstSetVariable realSubMat paramId param.data.diffuseTexture
if ( RstGetIsAlphaShader realSubMat ) then (
RstSetAlphaTextureName realSubMat paramId param.data.alphaTexture
)
local msg = "Propagated material (" + realSubMat.name + ") on object (" + realObj.name + ") from file revision (" + fromRev as string +") to revision (" + toRev as string + ")."
format "%\n" msg
gRsPropaMaterialUlog.LogMessage msg
)
)
)
) else (
local msg = "Skipping propagation for material (" + realSubMat.name + ") on object (" + realObj.name + ") using material id (" + prevMat.matid as string + ")."
format "[WARNING] %\n" msg
gRsPropaMaterialUlog.LogWarning msg
)
) else (
local msg = "The material (" + realSubMat.name + ") is not a Rage shader, when the old one was! Skipping propagation for this material."
format "[WARNING] %\n" msg
gRsPropaMaterialUlog.LogWarning msg
)
) else (
local msg = "Could not find the material id (" + prevMat.matid as string + ") on material (" + realMat.name + ") on object (" + realObj.name + ")! Skipping propagation for this material."
format "[WARNING] %\n" msg
gRsPropaMaterialUlog.LogWarning msg
)
)
) else (
print "not a multimaterial"
)
) else (
local msg = "The object (" + realObj.name + ") no longer has a material assigned! Cannot propagate this object's material."
messageBox msg title:"Rockstar"
format "[WARNING] %\n" msg
gRsPropaMaterialUlog.LogWarning msg
)
) else (
local msg = "[WARNING] Skipping material propagation for object (" + realObj.name + ")."
gRsPropaMaterialUlog.LogWarning msg
)
) else (
local msg = "Could not find an object named (" + rsObj.name + ") using handle (" + rsObj.handle as string + ")! Skipping material propagation for this object."
messageBox msg title:"Rockstar"
format "[WARNING] %\n" msg
gRsPropaMaterialUlog.LogWarning msg
)
progressUpdate ( 100 * progress / rsObjs.count )
progress += 1
)
progressEnd()
messageBox "Finished propagating materials! Please check to make sure everything propagated correctly." title:"Rockstar"
) else (
local msg = "An unknown error occurred reading in the file (" + matxmlFilename + ")! Aborting material propagation."
messageBox msg title:"Rockstar"
gRsPropaMaterialUlog.LogError msg
)
) else (
local msg = "Could not find the file (" + matxmlFilename + ")! Something went wrong during the material export process.\n\nAborting material propagation."
messageBox msg title:"Rockstar"
)
)
RSrefAllowUpdate = true
gRsPropaMaterialUlog.validate()
)
)
rollout RsPropagateMaterialsRollout "Rockstar - Propagate Materials"
(
local propaMaterials = RsPropagateMaterials()
local haveRev = undefined
local headRev = undefined
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:RsPropagateMaterialsRollout.width
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"propagate materials" filename:(getThisScriptFilename())
edittext etMaxFilename "Max Filename" labelOnTop:true readOnly:true width:348 across:2
button btnPickMaxFilename "..." offset:[ 88, 16 ]
label lbCurrentRevision "Current Revision: " align:#left
label lbSep01 ""
group "Propagate Materials"
(
spinner spFromRevision "From Revision:" type:#integer width:90 across:2 offset:[ -24, 0 ]
spinner spToRevision "To Revision:" type:#integer width:90 offset:[ -90, 0 ]
)
button btnProcess "Process" width:390 height:32
on btnPickMaxFilename pressed do (
result = getOpenFilename filename:( RsConfigGetProjRootDir() + "art\\" ) caption:"Choose a 3dsmax File to Propagate Materials" types:"3dsmax (*.max;*.maxc)|*.max;*.maxc|"
if result != undefined then (
etMaxFilename.text = result
local fstats = ( gRsPerforce.getFileStats ( result ) )[ 1 ]
-- in case "haveRev" or "headRev" = undefined - A.H.
if fstats.Item[ "haveRev" ] != undefined then haveRev = fstats.Item[ "haveRev" ] as integer
if fstats.Item[ "headRev" ] != undefined then headRev = fstats.Item[ "headRev" ] as integer
lbCurrentRevision.text = "Current Revision: " + haveRev as string
spFromRevision.range = [ 1, headRev, haveRev ]
spToRevision.range = [ 1, headRev, headRev ]
)
)
on btnProcess pressed do (
--Added check that there is a filename - A.H.
if etMaxFilename.text != "" then
propaMaterials.propagate etMaxFilename.text spFromRevision.value spToRevision.value
)
on RsPropagateMaterialsRollout open do
(
banner.setup()
)
)
createDialog RsPropagateMaterialsRollout width:400 height:166 style:#(#style_resizing,#style_titlebar, #style_toolwindow, #style_sysmenu)