587 lines
20 KiB
Plaintext
Executable File
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)
|