2279 lines
83 KiB
Plaintext
Executable File
2279 lines
83 KiB
Plaintext
Executable File
theProjectRoot = RsConfigGetProjRootDir()
|
|
theProject = RSConfigGetProjectName()
|
|
theWildWest = RsConfigGetWildWestDir()
|
|
theProjectConfig = RsConfigGetProjBinConfigDir()
|
|
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
filein (RsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms")
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
--Ped Validation functions
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
filein "pipeline/util/RsUniversalLogViewer.ms"
|
|
filein "pipeline/util/RsUniversalLog.ms"
|
|
sRsULog()
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
global theProjectName = undefined
|
|
/*
|
|
-- HACK
|
|
theProjectName = case theproject of
|
|
(
|
|
"rdr3" : "bob"
|
|
"gta5":"gta5"
|
|
)
|
|
--filein (pathToConfigFiles + "project_config_"+theProjectName+".ms")
|
|
*/
|
|
dotnet.LoadAssembly "System.Xml.XPath.dll"
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-- Setup globals
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
global gPedValidationLogFile = ( RsConfigGetLogDir() + "pedValidation.ulog" )
|
|
global gRsPedValidationULog = sRsULog()
|
|
global pedValidation_Floater
|
|
global RsPedValidation = undefined
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct RsPedValidationStruct
|
|
(
|
|
configFile=undefined,
|
|
nmFile=undefined,
|
|
typeFile=undefined,
|
|
metaFile=undefined,
|
|
namelengthMaxFile = undefined,
|
|
textureXMaxFile = undefined,
|
|
textureYMaxFile = undefined,
|
|
pedSuffixFile = undefined,
|
|
pedConfigData = undefined,
|
|
pedNodeError = undefined,
|
|
pedLodError = undefined,
|
|
|
|
fn genPedConfigFile = (configFile=pathToConfigFiles + "characters/ped_data_config.xml"),
|
|
fn genPedNmFile = (nmFile=RsConfigGetToolsDir() + "etc\\config\\characters\\nm.xml"),
|
|
fn genPedTypeFile = (typeFile=theProjectConfig + "characters/ped_type_list.xml"),
|
|
fn genPedMetaFile = (metaFile=RsConfigGetProjRootDir()+ "build\\dev\\common\\data\\peds.meta"),
|
|
fn createPedNodeError = (pedNodeError = true),
|
|
fn createpedLodError = (pedLodError = true),
|
|
|
|
pedConfigFile = genPedConfigFile(),
|
|
pedNmFile = genPedNmFile(),
|
|
pedTypeFile = genPedTypeFile(),
|
|
pedMetaFile = genPedMetaFile(),
|
|
|
|
--=========================================================================
|
|
-- fn getPedConfigData =
|
|
--=========================================================================
|
|
-- Description: gets all the ped config data from ped_data_config.xml
|
|
--=========================================================================
|
|
fn getPedConfigData =
|
|
(
|
|
local dataFileName = pedConfigFile
|
|
if (doesfileexist dataFileName) == true then
|
|
(
|
|
local xmlDoc = dotnetobject "System.XML.XMLDocument"
|
|
xmlDoc.load dataFileName
|
|
local pedConfigArray = #()
|
|
|
|
( -- get Racial identifiers
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/pedraces/item").GetEnumerator()
|
|
local theCountEnum = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/pedraces").GetEnumerator()
|
|
local pedRaceId = #()
|
|
|
|
theCountEnum.MoveNext()
|
|
local theCount = theCountEnum.current.Childnodes.count
|
|
|
|
for sufIndx in 1 to theCount do
|
|
(
|
|
itemIter.MoveNext()
|
|
local thepedRaceId = (tolower (itemIter.current.innertext))
|
|
append pedRaceId thepedRaceId
|
|
)
|
|
append pedConfigArray pedRaceId
|
|
)
|
|
|
|
( -- get ped suffix array
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/pedcomponenttypes/item/pedcomponentsuffix/item").GetEnumerator()
|
|
local pedSuffixArray = #()
|
|
for sufIndx in 1 to 3 do
|
|
(
|
|
itemIter.MoveNext()
|
|
local thepedsuffix = (tolower (itemIter.current.innertext))
|
|
append pedSuffixArray thepedsuffix
|
|
)
|
|
append pedConfigArray pedSuffixArray
|
|
)
|
|
|
|
( -- get max name length
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/ped_global_variables/ped_modelnamelength").GetEnumerator()
|
|
itemIter.MoveNext()
|
|
local maxnamelength = (itemIter.current.attributes.GetNamedItem "value").value as number
|
|
append pedConfigArray maxnamelength
|
|
)
|
|
|
|
( -- get max texture width
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/texturemaxx").GetEnumerator()
|
|
itemIter.MoveNext()
|
|
local xValue = (itemIter.current.attributes.GetNamedItem "value").value as number
|
|
append pedConfigArray xValue
|
|
)
|
|
|
|
( -- get max texture height
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/texturemaxy").GetEnumerator()
|
|
itemIter.MoveNext()
|
|
local yValue = (itemIter.current.attributes.GetNamedItem "value").value as number
|
|
append pedConfigArray yValue
|
|
)
|
|
|
|
( -- get texture types
|
|
local itemIter = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/texturetypes/item").GetEnumerator()
|
|
local theCountEnum = (xmlDoc.selectnodes "//pedData/pedcomponenttextures/texturetypes").GetEnumerator()
|
|
local textureTypeArray = #()
|
|
|
|
theCountEnum.MoveNext()
|
|
local theCount = theCountEnum.current.Childnodes.count
|
|
|
|
for texIter in 1 to theCount do
|
|
(
|
|
itemIter.MoveNext()
|
|
local theTextureType = (tolower (itemIter.current.innertext))
|
|
append textureTypeArray theTextureType
|
|
)
|
|
append pedConfigArray textureTypeArray
|
|
)
|
|
|
|
pedConfigArray
|
|
)
|
|
else
|
|
(
|
|
local msg = "Could not find ped config file"
|
|
gRsPedValidationULog.LogError msg appendToFile:false
|
|
)
|
|
),
|
|
|
|
PedConfigData = getPedConfigData(),
|
|
|
|
--=============================================================--
|
|
------ Reads XML attribute
|
|
-- selectedSet = dotNet xml document navigator selection set, attributeName = Case sensitive XML attribute name
|
|
--=============================================================--
|
|
fn getXMLAttribute selectedSet attributeName =
|
|
(
|
|
-- use the passed in set of nodes to search for our attribute
|
|
local attributeIterator = selectedSet.Current.Select("@" + attributeName)
|
|
local returnValue = attributeIterator.Current.Value
|
|
|
|
if attributeIterator.Count > 0 then
|
|
(
|
|
attributeIterator.MoveNext()
|
|
returnValue = attributeIterator.Current.Value
|
|
)
|
|
returnValue
|
|
),
|
|
|
|
--=============================================================--
|
|
-- loadSettingsXML fileXML selSetXML attributeArra =
|
|
------ Loads in the required XML, returns array of arrays holding the type and values
|
|
-- ARGS:
|
|
-- fileXML = XML file to search
|
|
-- selSetXML = selection to search
|
|
-- attributeArray = attributes to search for
|
|
--=============================================================--
|
|
fn loadSettingsXML fileXML selSetXML attributeArray =
|
|
(
|
|
local settingsFilePath = fileXML
|
|
|
|
-- create an xml instance
|
|
local settingsXML = XmlDocument()
|
|
settingsXML.init()
|
|
settingsXML.Load settingsFilePath
|
|
|
|
-- now create a XML document instance to read from
|
|
local settingsDocument = settingsXML.Document
|
|
|
|
-- create our navigator which we use to survey the xml document
|
|
local settingsNavigator = settingsDocument.CreateNavigator()
|
|
settingsNavigator.MoveToRoot()
|
|
|
|
-- find all of the specific nodes we are looking for
|
|
local settingsSelectionSet = settingsNavigator.Select(settingsNavigator.Compile(selSetXML))
|
|
|
|
local settingsFileFormatted = #()
|
|
-- lets loop through all of the found nodes and then search for each attribute we are looking for, compiling it in an array of values
|
|
while (settingsSelectionSet.MoveNext()) do
|
|
(
|
|
local settingsArray = #()
|
|
for attrIndx= 1 to attributeArray.count do
|
|
(
|
|
local nameAttribute = RsPedValidation.getXMLAttribute settingsSelectionSet attributeArray[attrIndx]
|
|
append settingsArray nameAttribute
|
|
)
|
|
append settingsFileFormatted settingsArray
|
|
)
|
|
settingsFileFormatted
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn filterObjNameToArray theName =
|
|
--=========================================================================
|
|
-- Description: filters the obj name to its component parts as an array
|
|
-- ARGS:
|
|
-- thename = The obj name we are testing
|
|
--=========================================================================
|
|
fn filterObjNameToArray theName =
|
|
(
|
|
if theName != undefined then
|
|
(
|
|
local nameLowerCase = tolower theName
|
|
local removeAppendedName = filterstring nameLowerCase " "
|
|
|
|
local appendedName = ""
|
|
local prefixName = ""
|
|
local objNameArray = #()
|
|
local objNameArrayMain = #()
|
|
local filteredNameArray = #()
|
|
|
|
for nameItr in 2 to removeAppendedName.count do
|
|
(
|
|
append appendedName removeAppendedName[nameItr]
|
|
if nameItr != removeAppendedName.count then append appendedName " "
|
|
)
|
|
|
|
objNameArray = filterstring removeAppendedName[1] "_"
|
|
if objNameArray[1].count < 2 then
|
|
(
|
|
objName = (objNameArray[1]+"_"+objNameArray[2])
|
|
append filteredNameArray objName
|
|
for objIter in 3 to 3 do
|
|
(
|
|
append filteredNameArray objNameArray[objIter]
|
|
)
|
|
if objNameArray[4] != undefined then append filteredNameArray objNameArray[4] else append filteredNameArray ""
|
|
)else
|
|
(
|
|
for objIter in 1 to 2 do
|
|
(
|
|
append filteredNameArray objNameArray[objIter]
|
|
)
|
|
if objNameArray[3] != undefined then append filteredNameArray objNameArray[3] else append filteredNameArray ""
|
|
)
|
|
|
|
append filteredNameArray appendedName
|
|
filteredNameArray
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn doesObjHaveDamageBake theObj =
|
|
--=========================================================================
|
|
-- Description: Does the obj have mapping on map id 2 for damage UVs and id 11 for default vert bake
|
|
-- ARGS:
|
|
-- theObj = The mesh we are testing
|
|
--=========================================================================
|
|
fn doesObjHaveDamageBake theObj =
|
|
(
|
|
-- get the class of theObj
|
|
if theObj != undefined and superclassof theObj == GeometryClass then
|
|
(
|
|
if classof theObj == Editable_mesh then
|
|
(
|
|
local testForID2 = meshop.getMapSupport theObj 2-- if mesh
|
|
local testForID11 = meshop.getMapSupport theObj 11-- if mesh
|
|
)
|
|
else if classof theObj == PolyMeshObject or classof theObj == Editable_Poly then
|
|
(
|
|
local testForID2 = polyop.getMapSupport theObj 2-- if poly
|
|
local testForID11 = polyop.getMapSupport theObj 11-- if poly
|
|
|
|
)
|
|
if testForID2 != true then
|
|
(
|
|
if (tolower (substring theObj.name 1 2)) != "p_" and (tolower (substring theObj.name 1 5)) != "hair_" then
|
|
(
|
|
if (tolower (substring theObj.name 1 5)) != "accs_" then
|
|
(
|
|
local msg = ( "\""+theObj.name+"\" does not have damage UVs")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false
|
|
)
|
|
)
|
|
)
|
|
if testForID11 != true then
|
|
(
|
|
local msg = ( "\""+theObj.name+"\" does not have default vert bake")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false
|
|
)
|
|
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn isMaterialUsed theObj theMatID =
|
|
--=========================================================================
|
|
-- Description: checks the mesh matID to see if the material in a multisub is using it
|
|
-- ARGS:
|
|
-- theObj = The mesh we are testing
|
|
-- theMatID = the Material ID to search for
|
|
--=========================================================================
|
|
fn isMaterialUsed theObj theMatID =
|
|
(
|
|
local usedVal = 0 -- test value
|
|
|
|
-- get the class of theObj
|
|
if theObj != undefined and superclassof theObj == GeometryClass then
|
|
(
|
|
if classof theObj == Editable_mesh then
|
|
(
|
|
local faceGetter = getFaceMatID -- if mesh
|
|
)
|
|
else if classof theObj == PolyMeshObject or classof theObj == Editable_Poly then
|
|
(
|
|
local faceGetter = polyop.getFaceMatID -- if poly
|
|
)
|
|
|
|
try -- making sure theObj will work with getnumfaces
|
|
(
|
|
local numFaces = getNumFaces theObj
|
|
|
|
for faceIdx = 1 to numFaces do
|
|
(
|
|
local getUsedMats = facegetter theObj faceIdx
|
|
if getUsedMats == theMatID then usedVal = usedVal +1
|
|
)
|
|
|
|
if usedVal > 0 then return true else return false
|
|
)
|
|
catch (Print "Not Poly or Ed Mesh ")
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn testRageShaderDiffuse shaderToTest MeshName =
|
|
--=========================================================================
|
|
-- Description: Checks the Rage Shader to verify it has a diffuse texture
|
|
-- ARGS:
|
|
-- shaderToTest = The shader we are testing
|
|
--=========================================================================
|
|
fn testRageShaderDiffuse shaderToTest =
|
|
(
|
|
local returnArray = #(0,0) -- returnArray[1] = does diffuse texture exist, returnArray[2] = is texture a race texture
|
|
|
|
-- identify Diffuse Texture withing Rage Shader Variables
|
|
local rageShaderVariables = #()
|
|
local rageShaderVariableCount = RstGetVariableCount shaderToTest
|
|
|
|
for variableIndx in 1 to rageShaderVariableCount do
|
|
(
|
|
append rageShaderVariables (RstGetVariableName shaderToTest variableIndx)
|
|
)
|
|
|
|
local rageShdrDiffuseTexture = finditem rageShaderVariables "Diffuse Texture"
|
|
|
|
-- check a texture is being used
|
|
local hasDiffuseTexture = RstGetVariable shaderToTest rageShdrDiffuseTexture
|
|
if hasDiffuseTexture == "" then
|
|
(
|
|
returnArray[1]= 0 -- texture does not exist
|
|
|
|
)
|
|
else
|
|
(
|
|
returnArray[1]= 1 -- texture exists
|
|
|
|
local raceArray = rspedvalidation.pedConfigData[1]
|
|
|
|
local textureName = tolower (getFileNameFile hasDiffuseTexture) -- gets texture name
|
|
local hasRaceTextureName = filterstring textureName "_ " -- filters name
|
|
|
|
for chckRace in 1 to raceArray.count do
|
|
(
|
|
local hasRaceTexture = finditem hasRaceTextureName raceArray[chckRace]
|
|
if hasRaceTexture > 0 then returnArray[2] = 1 -- is race texture
|
|
)
|
|
)
|
|
returnArray
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn testMaterialProperties theMesh theMat theMatId=
|
|
--=========================================================================
|
|
-- Description: Checks the Rage Shader to verify it has a diffuse texture
|
|
-- ARGS:
|
|
-- theMesh = The mesh we are testing
|
|
-- theMat = The shader we are looking for
|
|
-- theMatId = The material id on the mesh
|
|
--=========================================================================
|
|
fn testMaterialProperties theMesh theMat theMatId=
|
|
(
|
|
-- check for rage shaders
|
|
local isRageShader = classof theMat
|
|
if isRageShader != Rage_Shader then
|
|
(
|
|
gRsUlog.logWarning ( "\""+theMesh.name+"\" has a material that is not a Rage Shader") context:"shader"
|
|
)
|
|
else
|
|
(
|
|
local objUsesThisShader = RsPedValidation.isMaterialUsed theMesh theMatId -- checks if mesh uses this material
|
|
|
|
if objUsesThisShader == true then
|
|
(
|
|
-- check for diffuse texture
|
|
local testDiffTexture = RsPedValidation.testRageShaderDiffuse theMat
|
|
if testDiffTexture[1]==0 then
|
|
(
|
|
local msg = ( "\""+theMesh.name+"\" has a material with no diffuse texture")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
else
|
|
(
|
|
-- check if it's a racial texture
|
|
if testDiffTexture[2] > 0 then
|
|
(
|
|
local findRacial = filterstring (tolower theMesh.name) "_ "
|
|
local HasRacial = finditem findRacial rspedvalidation.pedConfigData[2][1]
|
|
if HasRacial == 0 then HasRacial = finditem findRacial rspedvalidation.pedConfigData[2][3]
|
|
if HasRacial == 0 then
|
|
(
|
|
local msg = ( "\""+theMesh.name+"\" uses race textures but does not have \"_R\" or \"_U\" race identifier")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn shaderErrorChecks mainMesh =
|
|
--=========================================================================
|
|
-- Description: Uses the passed in meshes to perform various checks relating to
|
|
-- shader requirements
|
|
-- ARGS:
|
|
-- mainMesh = Mesh we are working on actively
|
|
--=========================================================================
|
|
fn shaderErrorChecks mainMesh =
|
|
(
|
|
if mainMesh != undefined and mainMesh.material != undefined then
|
|
(
|
|
-- get the material assigned to the mesh
|
|
local meshMaterial = mainMesh.material
|
|
|
|
if classof meshMaterial == Multimaterial then
|
|
(
|
|
for materialIndx in 1 to meshMaterial.count do
|
|
(
|
|
RsPedValidation.testMaterialProperties mainMesh meshMaterial[materialIndx] materialIndx
|
|
)
|
|
)
|
|
else
|
|
(
|
|
RsPedValidation.testMaterialProperties mainMesh meshMaterial 0
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn nameLengthCheck itemName =
|
|
--=========================================================================
|
|
-- Description: Uses the passed in string to check the name length
|
|
-- is within character limit
|
|
-- ARGS:
|
|
-- itemName = String we are working with
|
|
--=========================================================================
|
|
fn nameLengthCheck itemName =
|
|
(
|
|
-- find the max name length
|
|
local maxNameLength = rspedvalidation.pedConfigData[3]
|
|
|
|
--Ped model name should be within the character limit.
|
|
if classof itemName == String then
|
|
(
|
|
local nameLengthFiltered = (filterstring itemName " ")
|
|
if nameLengthFiltered[1].count > maxNameLength then
|
|
(
|
|
local msg =("\""+itemName+"\" name is too long. More than "+ ( maxNameLength as string) + " characters")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
else "Not a string!"
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn skinningErrorChecks mainMesh =
|
|
--=========================================================================
|
|
-- Description: Uses the passed in meshes to perform various checks relating to
|
|
-- skinning requirements
|
|
-- ARGS:
|
|
-- mainMesh = Mesh we are working on actively
|
|
--=========================================================================
|
|
fn skinningErrorChecks mainMesh =
|
|
(
|
|
if mainMesh != undefined then
|
|
(
|
|
-- check for skinning
|
|
local skinLocation = 0
|
|
local allModifiersOnMesh = mainMesh.modifiers
|
|
for meshIndx in 1 to allModifiersOnMesh.count do --search modifier array for skin modifier
|
|
(
|
|
|
|
if classof allModifiersOnMesh[meshIndx] == Skin then
|
|
(
|
|
skinLocation = meshIndx
|
|
)
|
|
)
|
|
|
|
if skinLocation != 0 then -- Has skin modifier
|
|
(
|
|
skinModifier = allModifiersOnMesh[skinLocation]
|
|
InstanceMgr.MakeModifiersUnique mainMesh skinModifier 1
|
|
modPanel.setCurrentObject allModifiersOnMesh[skinLocation] ui:true
|
|
|
|
---- Skinning is enabled
|
|
if skinModifier.enabled == false then
|
|
(
|
|
local msg =( "\""+mainMesh.name+"\" skin modifier not enabled")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
|
|
---- skinned objects have a limit of 4 effective bones
|
|
if skinModifier.bonelimit > 4 then
|
|
(
|
|
local msg =( "\""+mainMesh.name+"\" has more than the 4 bone per vertex limit")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
|
|
---- No prop meshes "P_" should have skin
|
|
if (tolower (substring mainMesh.name 1 2)) == "p_" then
|
|
(
|
|
local msg =( "\""+mainMesh.name+"\" is prop mesh, but has skin modifier")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
|
|
---- no verts skinned to unused bones,
|
|
---- unused bones being secondary movement bones/attachment bones
|
|
(
|
|
local Vertexfound = 0
|
|
local bonesInSkin = skinOps.GetNumberBones skinModifier
|
|
local boneNameArray = #()
|
|
local badBoneNameArray = #()
|
|
|
|
for boneIndx in 1 to bonesInSkin do
|
|
(
|
|
local boneName = (skinOps.GetBoneName skinModifier boneIndx 0)
|
|
if (substring boneName 1 5) != "SKEL_" and (substring boneName 1 3) != "RB_"then append badBoneNameArray boneName
|
|
if (substring boneName 1 5) == "SKEL_" then append boneNameArray boneName
|
|
)
|
|
|
|
local skinnedVertices = skinOps.GetNumberVertices skinModifier
|
|
|
|
if Vertexfound == 0 then for vertexIndx in 1 to skinnedVertices do
|
|
(
|
|
influenceBones =skinOps.GetVertexWeightCount skinModifier vertexIndx
|
|
for boneIndx in 1 to influenceBones do
|
|
(
|
|
local influenceBoneID = skinOps.GetVertexWeightBoneID skinModifier vertexIndx boneIndx
|
|
local influenceBoneName = (skinOps.GetBoneName skinModifier influenceBoneID 0)
|
|
local influenceBoneinBoneList = finditem badBoneNameArray influenceBoneName
|
|
|
|
if influenceBoneinBoneList > 0 then
|
|
(
|
|
if Vertexfound == 0 then
|
|
(
|
|
local msg = ("\""+mainMesh.name+"\" has vertices influenced by an unused bone")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
Vertexfound = (Vertexfound + 1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- *********************** WANT TO MAKE SURE BONE NUBS COUNT *******************
|
|
-- currently this does not flag if Skel_ NUBs are not in skin. Need to find out if this is correct --
|
|
-- if we want to flag nubs change findAllSkelBones = 1 to findAllSkelBones = 0
|
|
|
|
---- all "skel_" joint should be in the skin of the head mesh
|
|
if (substring mainMesh.name 1 5) == "head_" then
|
|
(
|
|
local MissingBones = 0
|
|
local skelBoneNameArray = for o in $SKEL_* collect o.name -- collect all bones named "Skel_"
|
|
|
|
for boneIndx in 1 to skelBoneNameArray.count do -- check each skelbone is in modifier
|
|
(
|
|
local findAllSkelBones = finditem boneNameArray skelBoneNameArray[boneIndx]
|
|
local nubCheck = (filterstring skelBoneNameArray[boneIndx] "_")
|
|
if (tolower (nubCheck[nubCheck.count])) == "nub" then findAllSkelBones = 1
|
|
if findAllSkelBones == 0 and MissingBones == 0 then
|
|
(
|
|
local msg = ("\""+mainMesh.name+"\"is a head mesh and is missing some SKEL_ bones from the skin modifier" )
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
MissingBones = (MissingBones + 1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
else -- does not have skin modifier
|
|
(
|
|
if (tolower (substring mainMesh.name 1 2)) != "p_" then
|
|
(
|
|
local msg = ("mesh \""+mainMesh.name+"\" does not have valid skin modifier")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
|
|
OutputStringStream
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn checkMeshErrors mainMesh =
|
|
--=========================================================================
|
|
-- Description: Uses the passed in meshes to perform various checks relating to
|
|
-- mesh requirements
|
|
-- ARGS:
|
|
-- mainMesh = Mesh we are working on actively
|
|
--=========================================================================
|
|
fn checkMeshErrors mainMesh =
|
|
(
|
|
if mainMesh != undefined and (tolower (substring mainMesh.name 1 2)) != "p_" then
|
|
(
|
|
local meshToMatIdArray =ped_fullComponentNamesByID
|
|
for meshMatIndx in 1 to meshToMatIdArray.count do
|
|
(
|
|
local meshNameinArray = RsPedValidation.searchFilteredString mainMesh.name "_ " meshToMatIdArray[meshMatIndx]
|
|
if meshNameinArray == true then
|
|
(
|
|
local meshMatIdEqualsName = RsPedValidation.isMaterialUsed mainMesh meshMatIndx
|
|
if meshMatIdEqualsName != true then
|
|
(
|
|
local msg = ("mesh \""+mainMesh.name+"\" does not have correct Mat ID")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
|
|
-- check for scaling
|
|
|
|
local theMeshScale = mainMesh.scale
|
|
return theMeshScale
|
|
if theMeshScale != [1,1,1] then
|
|
(
|
|
local msg = ( "\""+mainMesh.name+"\" has a scale applied")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn searchFilteredString theString theFilter theSearch =
|
|
--=========================================================================
|
|
-- Description: tests string for arg. Uses tolower to remove case from search
|
|
-- returns true or false
|
|
-- ARGS:
|
|
-- theString = the string we are searching
|
|
-- theFilter = how we will filter the string
|
|
-- theSearch = the string to look for
|
|
--=========================================================================
|
|
fn searchFilteredString theString theFilter theSearch =
|
|
(
|
|
if theString != undefined and classof theString == String then -- check string exists and is a string
|
|
(
|
|
local filteredArray = filterString theString theFilter -- filter theString with theFilter
|
|
|
|
local loweredArray = #() -- create an array for the lower case strings
|
|
|
|
for stringIndx in 1 to filteredArray.count do append loweredArray (tolower filteredArray[stringIndx]) -- append lower case strings to array
|
|
|
|
local findString = finditem loweredArray (tolower theSearch) -- lower case array for lower case theSearch
|
|
if findString == 0 then return false else return true
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn checkRaceIDName mainMesh =
|
|
--=========================================================================
|
|
-- Description: Uses the passed in meshes to check there is a race identifier
|
|
-- in the mesh name
|
|
-- ARGS:
|
|
-- mainMesh = Mesh we are working on actively
|
|
--=========================================================================
|
|
fn checkRaceIDName mainMesh =
|
|
(
|
|
if mainMesh != undefined then
|
|
(
|
|
-- check for correct racial identifier naming
|
|
if (tolower (substring mainMesh.name 1 2)) != "p_" then -- makes sure the mesh isnt a prop
|
|
(
|
|
local filterName = (RSPedValidation.filterObjNameToArray mainMesh.name)
|
|
local raceIdent = filterName[3]
|
|
local raceIdentFound = 0
|
|
local identifierArray = rspedvalidation.pedConfigData[2]
|
|
local hasIdentifierRoot = finditem identifierArray raceIdent
|
|
|
|
if hasIdentifierRoot == 0 then
|
|
(
|
|
local msg = ( "\""+mainMesh.name+"\" does not have a racial identifier")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)else
|
|
(
|
|
raceIdentFound = 1
|
|
local texSearchName = (filterName[1]+"_diff_"+filterName[2])
|
|
local texArray = getFiles ( maxfilepath+"Textures\\HighRes\\"+texSearchName+"*")
|
|
for textureIter in 1 to texArray.count do
|
|
(
|
|
local filterTexID = filterstring (getfilenamefile texArray[textureIter]) "_."
|
|
local raceTexID = (tolower filterTexID[filterTexID.count])
|
|
local compareID = finditem rspedvalidation.pedConfigData[1] raceTexID
|
|
if compareID != 0 then
|
|
(
|
|
local theRaceID = rspedvalidation.pedConfigData[1][finditem rspedvalidation.pedConfigData[1] raceTexID]
|
|
if theRaceID != "uni" then
|
|
(
|
|
if raceIdent != "r" then
|
|
(
|
|
local msg = ( "\""+mainMesh.name+"\" uses race textures, but does not use racial identifier naming, \"_r\"")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn findNumeric theString =
|
|
--=========================================================================
|
|
-- Description: Tests for integers within a filtered string
|
|
-- ARGS:
|
|
-- theString = the string to test
|
|
--=========================================================================
|
|
fn findNumeric theString =
|
|
(
|
|
local seperateString = filterString theString "_"
|
|
|
|
for stringIndx in 1 to seperateString.count do
|
|
(
|
|
local isNum = seperateString[stringIndx] as number
|
|
if classof isNum == integer then return isNum
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn checkNodeNamesAreSequential theArray =
|
|
--=========================================================================
|
|
-- Description: Collects the nodes in the scene and finds out if the nodes are
|
|
-- named sequentially
|
|
-- ARGS:
|
|
-- theArray = the array of Meshes to look for similar names
|
|
--=========================================================================
|
|
fn checkNodeNamesAreSequential theArray =
|
|
(
|
|
|
|
if theArray != undefined then
|
|
(
|
|
local checkTheNode = undefined
|
|
local findSiblings = undefined
|
|
local siblingArray = #()
|
|
local siblingNameArray = #()
|
|
|
|
for arrayIndx in 1 to theArray.count do
|
|
(
|
|
checkTheNode = RSPedValidation.filterObjNameToArray theArray[arrayIndx].name
|
|
findSiblings = checkTheNode[1]
|
|
|
|
siblingArray = (execute ("$"+findSiblings+"* as array"))
|
|
|
|
for siblingIter in 1 to siblingArray.count do
|
|
(
|
|
local filterSibLingNameParts = RSPedValidation.filterObjNameToArray siblingArray[siblingIter].name
|
|
local filterSibLingName = filterSibLingNameParts[2]
|
|
local isInArray = finditem siblingNameArray filterSibLingName
|
|
if isInArray == 0 and filterSibLingName != undefined then append siblingNameArray filterSibLingName
|
|
)
|
|
|
|
local sortedArray = sort siblingNameArray
|
|
for numIter in 1 to sortedArray.count do
|
|
(
|
|
local checkNumber = (sortedArray[numIter] as integer + 1)
|
|
if checkNumber != numIter then
|
|
(
|
|
local msg = ("\""+findSiblings+"\" not named sequentially")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
--print msg
|
|
)
|
|
)
|
|
|
|
)
|
|
)
|
|
siblingNameArray
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn getFilesRecursive root pattern =
|
|
--=========================================================================
|
|
-- Description: Recurses through selected folder to find pattern
|
|
-- ARGS:
|
|
-- root = The root folder to search in
|
|
-- pattern = The pattern to search for
|
|
--=========================================================================
|
|
fn getFilesRecursive root pattern =
|
|
(
|
|
local dir_array = GetDirectories (root+"/*")
|
|
for d in dir_array do
|
|
join dir_array (GetDirectories (d+"/*"))
|
|
local my_files = #()
|
|
for f in dir_array do
|
|
join my_files (getFiles (f + pattern))
|
|
my_files
|
|
),
|
|
|
|
--=========================================================================
|
|
--fn highLowCheck Mainmesh =
|
|
--=========================================================================
|
|
-- Description: Tests to see if mesh has a lod and if so, then if they has same shader
|
|
-- ARGS:
|
|
-- Mainmesh = The mesh to perform check on
|
|
--=========================================================================
|
|
fn highLowCheck Mainmesh =
|
|
(
|
|
local lodSets = execute ("$"+(getfilenamefile maxfilename)+"* as array") -- collect all node sets
|
|
if lodSets.count < 2 then
|
|
(
|
|
if pedLodError == undefined then
|
|
(
|
|
createpedLodError()
|
|
local msg = "Could not find Lod collection. It either does not exist or is named incorrectly."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)else
|
|
(
|
|
for setIndx in 1 to lodSets.count do
|
|
(
|
|
if lodSets[setIndx] != (getnodebyname (getfilenamefile maxfilename)) then -- does not check the non LOD set
|
|
(
|
|
local whichLod = filterString lodSets[setIndx].name "-" -- filters the LOD identifier
|
|
local LodName = ""
|
|
if whichLod[2] == "L" then LodName = " LOD" else if whichLod[2] == "l2" then LodName = " LOD2"
|
|
|
|
--- High and Low LOD have the same shader
|
|
if (tolower (substring Mainmesh.name 1 2)) != "p_" then
|
|
(
|
|
if LodName == " LOD2" then
|
|
(
|
|
local lod2Items = #("head","uppr","lowr")
|
|
local lod2Check = filterstring Mainmesh.name "_ "
|
|
itemIsLod2 = (finditem lod2Items (tolower lod2Check[1]))
|
|
if itemIsLod2 > 0 then
|
|
(
|
|
(
|
|
local hasLowMesh = getnodebyname (Mainmesh.name+LodName) -- Selects the LOD
|
|
|
|
if hasLowMesh != undefined then
|
|
(
|
|
local hasSameShader = Mainmesh.material == hasLowMesh.material -- Compares the shaders
|
|
if hasSameShader != true then
|
|
(
|
|
(
|
|
local msg = ("\""+mainMesh.name+"\" and LOD mesh do not use same shader")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
local msg = ("\""+mainMesh.name+"\" has no"+LodName+ " mesh")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn countTexturesInFile =
|
|
--=========================================================================
|
|
-- Description: Collects all the texutures used in the scene and returns an array of them
|
|
--=========================================================================
|
|
fn countTexturesInFile =
|
|
(
|
|
local texturesInFile = #()
|
|
local origAssets = for assetIndx = 1 to AssetManager.GetNumAssets() collect (AssetManager.GetAssetByIndex assetIndx)
|
|
for assetIndx in origAssets do
|
|
(
|
|
local AType = assetIndx.getType()
|
|
if AType == #bitmap then
|
|
(
|
|
local AFile = (tolower (assetIndx.getfilename()))
|
|
if substring AFile 1 1 == "x" then
|
|
(
|
|
local filterHiRes = filterstring (getFilenamePath AFile) "\\"
|
|
if filterHiRes[filterHiRes.count] == "highres" then append texturesInFile AFile
|
|
)
|
|
)
|
|
|
|
)
|
|
texturesInFile
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn textureChecks =
|
|
--=========================================================================
|
|
-- Description: Makes sure scen is using textures relating to
|
|
-- texture requirements
|
|
--=========================================================================
|
|
fn textureChecks =
|
|
(
|
|
--get all .tga files from the maxfilepath+Textures\ConsoleRes and all its subfolders:
|
|
local checkForHighResDir = doesfileexist (maxfilepath+"Textures\\HighRes")
|
|
|
|
if checkForHighResDir == true then
|
|
(
|
|
local texturesInFolder = getFiles (maxfilepath+"Textures\\HighRes\\*.tga")
|
|
|
|
-- check all textures in HighRes folder are right dimensions
|
|
for texIndx in 1 to texturesInFolder.count do
|
|
(
|
|
size = getBitmapInfo texturesInFolder[texIndx]
|
|
if size[3] > rspedvalidation.pedConfigData[4] or size[4] > rspedvalidation.pedConfigData[5] then
|
|
(
|
|
local msg = ((filenameFromPath texturesInFolder[texIndx])+" is larger than recommended. It is "+ (size[3] as string)+"x"+(size[4] as string)+".")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
)
|
|
|
|
-- check all textures in HighRes folder are used
|
|
for texIndx in 1 to texturesInFolder.count do
|
|
(
|
|
local objNameFromTex = (filterstring (getfilenamefile texturesInFolder[texIndx]) "_")
|
|
local objExistsArray = execute ("$"+objNameFromTex[1]+"* as array")
|
|
if objExistsArray.count == 0 then
|
|
(
|
|
local msg =("\""+(getfilenamefile texturesInFolder[texIndx]) + "\" texture in the \"HighRes\" folder, is not used in this ped file")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
)
|
|
|
|
|
|
/*
|
|
-- local texturesInFile = RsPedValidation.countTexturesInFile()
|
|
if texturesInFolder.count > texturesInFile.count then
|
|
(
|
|
local texuredetails = 0
|
|
if texuredetails == 0 then
|
|
(
|
|
local msg =("There are unused textures in the \"HighRes\" folder")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
) else
|
|
(
|
|
for texIter in 1 to texturesInFolder.count do
|
|
(
|
|
local isInFile = findItem texturesInFile texturesInFolder[texIter]
|
|
if isInFile == 0 then
|
|
(
|
|
theTexFileName = getFilenameFile texturesInFolder[texIter]
|
|
local msg =("There are unused textures in the \"HighRes\" folder")
|
|
local msg =(theTexFileName + " in the \"HighRes\" folder, is not used in this Max file")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
*/
|
|
)
|
|
|
|
else
|
|
(
|
|
local msg =("No \"HighRes\" texture folder found")
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"texture"
|
|
)
|
|
),
|
|
|
|
|
|
|
|
--=========================================================================
|
|
-- fn findXMLValue theXml theItem =
|
|
--=========================================================================
|
|
-- Description: find stated item in XML file
|
|
-- ARGS:
|
|
-- theXml = The xml to search
|
|
-- theItem = The item to search for the value
|
|
--=========================================================================
|
|
fn findXMLValue theXml theItem=
|
|
(
|
|
local dataFileName = theXml
|
|
|
|
if (doesfileexist dataFileName) == true then
|
|
(
|
|
local xmlDoc = dotnetobject "System.XML.XMLDocument"
|
|
xmlDoc.load dataFileName
|
|
local itemIter = (xmlDoc.selectnodes theItem).GetEnumerator()
|
|
local theArray = #()
|
|
|
|
while (itemIter.MoveNext()) do
|
|
(
|
|
if itemIter.current.IsEmpty == true then
|
|
(
|
|
-- print "true"
|
|
append theArray (itemIter.current.GetAttribute "value")
|
|
)
|
|
if itemIter.current.IsEmpty == false then
|
|
(
|
|
-- print "false"
|
|
append theArray itemIter.current.InnerText
|
|
)
|
|
)
|
|
)
|
|
theArray
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn checkSkeletonIsValid =
|
|
--=========================================================================
|
|
-- Description: checks that skeleton in file is the same as latest skeleton
|
|
--=========================================================================
|
|
fn checkSkeletonIsValid =
|
|
(
|
|
if maxfilename != "" then
|
|
(
|
|
--- make sure skeletons are up to date in perforce
|
|
local p4Checks = RsPerforce() -- perforce fns
|
|
local skelLocation = (RsConfigGetProjRootDir()+"art\\peds\\Skeletons\\")
|
|
local checklFileInP4 = (p4Checks.exists #((skelLocation+"Male Skeleton.max"),(skelLocation+"Female Skeleton.max"),(skelLocation+"Female Skeleton Heels.max")))
|
|
local compareSkels = false
|
|
local genderSkeleton = undefined
|
|
|
|
if checklFileInP4.count > 0 then
|
|
(
|
|
-- check gender of ped
|
|
local theGenderFilname = filterstring (getfilenamefile maxfilename) "_"
|
|
local theGender = theGenderFilname[2]
|
|
if theGender == "M" then genderSkeleton = (RsConfigGetProjRootDir()+"art\\peds\\Skeletons\\Male Skeleton.max")
|
|
if theGender == "F" then genderSkeleton = (RsConfigGetProjRootDir()+"art\\peds\\Skeletons\\Female Skeleton.max")
|
|
if genderSkeleton != undefined then
|
|
(
|
|
if doesfileexist genderSkeleton != false then
|
|
(
|
|
local getXref =xrefs.addNewXRefFile genderSkeleton
|
|
|
|
-- collect skeleton nodes
|
|
local skelInFile = for obj in $dummy01 collect obj
|
|
local skelInXref = for obj in getXref.tree.children[1] collect obj
|
|
|
|
local skelInfoArray = #(#(),#(),#())
|
|
local skelInfoArrayXref = #(#(),#(),#())
|
|
|
|
sliderTime = 0f -- time to zero in case there is animation on file
|
|
|
|
-- collect file skeleton info
|
|
for skelIndx in 1 to skelInFile.count do
|
|
(
|
|
if (tolower (substring skelInFile[skelIndx].name 1 5)) == "skel_" then
|
|
(
|
|
append skelInfoArray[1] skelInFile[skelIndx].name
|
|
append skelInfoArray[2] skelInFile[skelIndx].transform
|
|
if skelInFile[skelIndx].parent != undefined then append skelInfoArray[3] skelInFile[skelIndx].parent.name else append skelInfoArray[3] ""
|
|
)
|
|
)
|
|
|
|
-- collect xref skeleton info
|
|
for skelIndx in 1 to skelInXref.count do
|
|
(
|
|
if (tolower (substring skelInXref[skelIndx].name 1 5)) == "skel_" then
|
|
(
|
|
append skelInfoArrayXref[1] skelInXref[skelIndx].name
|
|
append skelInfoArrayXref[2] skelInXref[skelIndx].transform
|
|
if skelInXref[skelIndx].parent != undefined then append skelInfoArrayXref[3] skelInXref[skelIndx].parent.name else append skelInfoArrayXref[3] ""
|
|
)
|
|
)
|
|
--compare transforms between file and xref skeletons
|
|
if skelInfoArray[2].count == skelInfoArrayXref[2].count then
|
|
(
|
|
for trsfrmIndx in 1 to skelInfoArray[2].count do
|
|
(
|
|
for pnt3Indx in 1 to 4 do
|
|
(
|
|
local point3Variable = skelInfoArray[2][trsfrmIndx][pnt3Indx]
|
|
local areCloseEnough = assert_point3_equal skelInfoArrayXref[2][trsfrmIndx][pnt3Indx] point3Variable tolerance:0.1
|
|
if areCloseEnough == true then skelInfoArrayXref[2][trsfrmIndx] = skelInfoArray[2][trsfrmIndx]
|
|
)
|
|
)
|
|
)else
|
|
( -- THIS IS JUST FOR DEBUG TO COMPARE SKELETONS IF THEY DONT MATCH --
|
|
/*
|
|
global ss = stringstream ""
|
|
format "File = XREF\n" to:ss
|
|
for i in 1 to skelInfoArray[1].count do format "% = %\n" skelInfoArray[1][i] skelInfoArrayXref[1][i] to:ss
|
|
ns = newscript()
|
|
format (ss as string) to:ns
|
|
*/
|
|
)
|
|
|
|
-- compare everything
|
|
compareSkels = with PrintAllElements on skelInfoArray as string == skelInfoArrayXref as string
|
|
xrefs.deleteAllXRefs()
|
|
if compareSkels != true then
|
|
(
|
|
local msg ="this skeleton does not match the current skeleton in perforce"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
) )else(
|
|
local msg ="you do not have the latest skeletons"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
)else
|
|
(
|
|
local msg ="could not determine gender of ped. check file naming."
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
)else
|
|
(
|
|
local msg ="you do not have the latest skeletons in perforce"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
|
|
compareSkels
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn generatePedList =
|
|
--=========================================================================
|
|
-- Description: creates a list of ped names in ped_type_list.xml file.
|
|
--=========================================================================
|
|
fn generatePedList =
|
|
(
|
|
local pedTypeArray = #("//PedTypes/streamedpeds/file","//PedTypes/componentpeds/file","//PedTypes/cutspeds/file")
|
|
local fileNameArray = #()
|
|
for pedIndx in 1 to pedTypeArray.count do
|
|
(
|
|
local xmlFileArray = RsPedValidation.findXMLValue RsPedValidation.pedConfigFile pedTypeArray[pedIndx]
|
|
|
|
local subfileNameArray = #()
|
|
|
|
for fileIndx in 1 to xmlFileArray.count do
|
|
(
|
|
append subfileNameArray (tolower (getfilenamefile xmlFileArray[fileIndx]))
|
|
)
|
|
|
|
append fileNameArray subfileNameArray
|
|
)
|
|
fileNameArray
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn createPedMetaNameList =
|
|
--=========================================================================
|
|
-- Description: creates a list of all ped names in peds.meta file.
|
|
--=========================================================================
|
|
fn createPedMetaNameList =
|
|
(
|
|
local dataFileName = RsPedValidation.pedMetaFile
|
|
if (doesfileexist dataFileName) == true then
|
|
(
|
|
local fileNameArray = #()
|
|
(
|
|
local subfileNameArray = #()
|
|
local xmlFileArray = RsPedValidation.findXMLValue dataFileName "//CPedModelInfo__InitDataList/InitDatas/Item/Name"
|
|
|
|
for fileIndx in 1 to xmlFileArray.count do
|
|
(
|
|
append subfileNameArray (tolower (getfilenamefile xmlFileArray[fileIndx]))
|
|
)
|
|
append fileNameArray subfileNameArray
|
|
)
|
|
(
|
|
local subfileNameArray = #()
|
|
local xmlFileArray = RsPedValidation.findXMLValue dataFileName "//CPedModelInfo__InitDataList/InitDatas/Item/IsStreamedGfx"
|
|
|
|
for fileIndx in 1 to xmlFileArray.count do
|
|
(
|
|
append subfileNameArray (tolower (getfilenamefile xmlFileArray[fileIndx]))
|
|
)
|
|
append fileNameArray subfileNameArray
|
|
)
|
|
)
|
|
fileNameArray
|
|
),
|
|
|
|
--=========================================================================
|
|
--fn comparePedtexToFile theFile =
|
|
--=========================================================================
|
|
-- Description: Tests to see racial indentifiers in pedtex file compare to meshes
|
|
-- ARGS:
|
|
-- theFile = The file to compare
|
|
--=========================================================================
|
|
fn comparePedtexToFile theFile =
|
|
(
|
|
if doesfileexist theFile == true then
|
|
(
|
|
local theFileArray = #() -- Array for file strings
|
|
|
|
local theFileStream = openFile theFile
|
|
seek theFileStream 0 -- Go to beginning of filestream
|
|
|
|
for stringIndx in 1 to 10000 while (eof theFileStream == false ) do
|
|
(
|
|
append theFileArray (readLine theFileStream) -- append file strings to array
|
|
)
|
|
|
|
|
|
|
|
local filteredArray = #() -- array to contain file strings filtering out uneeded name text
|
|
|
|
for stringIndx in 1 to theFileArray.count do
|
|
(
|
|
local theFileName = (tolower (getFilenameFile theFileArray[stringIndx]))
|
|
local textureFileName = (theFileName + (tolower (getFilenameType theFileArray[stringIndx])) )
|
|
local filteredName = filterstring theFileName "_ ."
|
|
local removeArray =#("diff","normal","spec","a","b","c","d","e","f","g","h")
|
|
local pedTextureTypes = rspedvalidation.pedconfigdata[6]
|
|
for txtrIndx in 1 to pedTextureTypes.count do -- checks against the texturestypes array in the project config max script
|
|
(
|
|
append removeArray (substring pedTextureTypes[txtrIndx] 3 100)
|
|
)
|
|
|
|
for nameIndx in 1 to removeArray.count do -- remove unwanted strings
|
|
(
|
|
local hasString = finditem filteredName removeArray[nameIndx]
|
|
if hasString > 0 then deleteitem filteredName hasstring
|
|
)
|
|
|
|
hasString = finditem filteredName rspedvalidation.pedconfigdata[1][1]
|
|
if hasString > 0 then filteredName[hasstring] = "u" -- if true add identifier to name
|
|
|
|
local filterRaces = rspedvalidation.pedconfigdata[1]
|
|
for i in 2 to filterRaces.count do
|
|
( e
|
|
hasString = finditem filteredName filterRaces[i]
|
|
if hasString > 0 then filteredName[hasstring] = "r" -- if true add identifier to name
|
|
)
|
|
|
|
local createName = "" -- empty string to create node name
|
|
for arrayIndx in 1 to filteredName.count do
|
|
(
|
|
append createName filteredName[arrayIndx]
|
|
if arrayIndx != filteredName.count do append createName "_" -- create node name
|
|
)
|
|
|
|
append filteredArray createName -- add node name to filtered array
|
|
)
|
|
|
|
|
|
|
|
local nodesInScene = RsPedValidation.createMeshList () -- creates a list of nodes
|
|
local filteredNodes = #() -- array for filtered node names
|
|
local objName = ""
|
|
if nodesInScene.count != 0 then
|
|
(
|
|
for nodeIndx in 1 to nodesInScene.count do
|
|
(
|
|
local nameToArray = RsPedValidation.filterObjNameToArray nodesInScene[nodeIndx].name
|
|
objName = (nameToArray[1]+"_"+nameToArray[2])
|
|
if nameToArray[3].count > 0 then append objName ("_"+nameToArray[3])
|
|
append filteredNodes objName-- append filtered name
|
|
)
|
|
|
|
for nodeIndx in 1 to filteredArray.count do -- compare filtered node array to generated node name array
|
|
(
|
|
local findNode = finditem filteredNodes filteredArray[nodeIndx]
|
|
if findNode == 0 then -- if node in file cannot be found then send error
|
|
(
|
|
(
|
|
local msg =("\"" +(getFilenameFile theFileArray[nodeIndx]) + ".tga\" in pedtex file but \""+filteredArray[nodeIndx] + "\" mesh does not exist")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"texture"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
--print filteredArray
|
|
--print "----------------"
|
|
--print filteredNodes
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn doFileChecks =
|
|
--=========================================================================
|
|
-- Description: Runs through all the ped validation external file checks
|
|
--=========================================================================
|
|
fn doFileChecks =
|
|
(
|
|
-- check that the character is in the nm.xml file
|
|
local characterXMLarray = RsPedValidation.loadSettingsXML RsPedValidation.pedNmFile "/xmlmatchs/xmlmatch" #("source")
|
|
local filteredCharacterXMLarray = #()
|
|
|
|
for arrayIndx = 1 to characterXMLarray.count do append filteredCharacterXMLarray (tolower ((filterstring characterXMLarray[arrayIndx][1] "/.")[1]))
|
|
|
|
local isPedInArray = finditem filteredCharacterXMLarray (tolower (getFileNameFile maxfilename))
|
|
if isPedInArray == 0 then gRsUlog.logError "this ped is not in nm.xml. check ped name."
|
|
|
|
-- check that the character is in thepeds.meta file
|
|
local pedMetaNameList = RsPedValidation.createPedMetaNameList()
|
|
local isPedInArray = finditem pedMetaNameList[1] (tolower (getFileNameFile maxfilename))
|
|
local streamedPedData = RsPedValidation.generatePedList() -- generates a list of ped data from ped_type_list.xml
|
|
if isPedInArray == 0 then gRsUlog.logError "this ped is not in peds.meta. check ped name."
|
|
else
|
|
(
|
|
local checkStreamGroup = finditem streamedPedData[2] (tolower (getFileNameFile maxfilename))
|
|
if checkStreamGroup != 0 then
|
|
(
|
|
if pedMetaNameList[2][isPedInArray] != "false " then
|
|
(
|
|
local msg = "this ped is in the component ped list in \"ped_type_list.xml\", but is not flagged \"IsStreamedGfx=false\" in \"peds.meta\" "
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
|
|
--check maps in .pedtex have a mesh in max file
|
|
if maxFileName != "" then RsPedValidation.comparePedtexToFile (maxfilepath+(getfilenamefile maxfilename)+".pedtex")
|
|
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn checkAllInP4 =
|
|
--=========================================================================
|
|
-- Description: checks that all the files are in perforce and up to date
|
|
--=========================================================================
|
|
fn checkAllInP4 =
|
|
(
|
|
-- create array with max file string and pedtex string, file based off of filename
|
|
local doesMaxfileExist = doesFileExist (maxfilepath+maxFileName)
|
|
if doesMaxfileExist == true then
|
|
(
|
|
local p4Checks = RsPerforce() -- perforce fns
|
|
global allFilesToCheck = #((maxfilepath+maxFileName), (maxfilepath+(getFilenameFile maxFileName)+".pedtex"))
|
|
local theGenderFilname = filterstring (getfilenamefile maxfilename) "_"
|
|
local genderSkeleton = undefined
|
|
local theGender = theGenderFilname[2]
|
|
if theGender == "M" then genderSkeleton = (RsConfigGetProjRootDir()+"art\\peds\\Skeletons\\Male Skeleton.max")
|
|
if theGender == "F" then genderSkeleton = (RsConfigGetProjRootDir()+"art\\peds\\Skeletons\\Female Skeleton.max")
|
|
if genderSkeleton != undefined then append allFilesToCheck genderSkeleton
|
|
|
|
-- add texture file strings to to array
|
|
local checkForHighResDir = doesfileexist (maxfilepath+"Textures\\HighRes")
|
|
if checkForHighResDir == true then
|
|
(
|
|
local texturesInFolder = getFiles (maxfilepath+"Textures\\HighRes\\*.tga")
|
|
for fileIndx in 1 to texturesInFolder.count do
|
|
(
|
|
append allFilesToCheck texturesInFolder[fileIndx]
|
|
)
|
|
)
|
|
|
|
-- check that all files are in perforce and up to date
|
|
global checkAllFilesInP4 = (p4Checks.exists allFilesToCheck as array)
|
|
|
|
-- if the returned value is not the same as the string array then recurse and find which files are not in perforce
|
|
if checkAllFilesInP4.count != allFilesToCheck.count then
|
|
(
|
|
for comparefiles in 1 to allFilesToCheck.count do
|
|
(
|
|
local inArray = finditem checkAllFilesInP4 comparefiles
|
|
if inArray == 0 then
|
|
(
|
|
(
|
|
local msg = ("\""+allFilesToCheck[comparefiles]+"\" not in perforce or file not latest")
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
local msg = "The max file has not been saved or does not exist"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn createMeshList =
|
|
--=========================================================================
|
|
-- Description: checks that the root node and the file name match then collects nodes
|
|
--=========================================================================
|
|
fn createMeshList =
|
|
(
|
|
-- Check to see that the character root node name matches the filename
|
|
local NodeMatchesFilename = getNodeByName (getFilenameFile maxFileName)
|
|
if NodeMatchesFilename == undefined then
|
|
(
|
|
(
|
|
local msg = "the character node does not match the max filename or does not exist"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
return #()
|
|
)
|
|
else
|
|
(
|
|
local characterNodeMeshes = for obj in NodeMatchesFilename collect obj --Collect the nodes
|
|
deleteItem characterNodeMeshes 1 -- Remove Parent Dummy node
|
|
if characterNodeMeshes.count == 0 then
|
|
(
|
|
if rsPedValidation.pedNodeError == undefined then
|
|
(
|
|
createPedNodeError()
|
|
local msg = "the ped node has no children, or is not set up correctly"
|
|
gRsPedValidationULog.LogError msg appendToFile:false context:"model"
|
|
)
|
|
characterNodeMeshes
|
|
)else
|
|
(
|
|
characterNodeMeshes
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn validatePed =
|
|
--=========================================================================
|
|
-- Description: Runs through all the ped validation check functions for a pre rigged ped
|
|
--=========================================================================
|
|
fn validatePedPreRig =
|
|
(
|
|
RsPedValidation.dofileChecks() -- run through all the file checks
|
|
RsPedValidation.textureChecks() -- run through all the texture checks
|
|
|
|
local theMeshlist = RsPedValidation.createMeshList()
|
|
if theMeshlist.count > 0 then
|
|
(
|
|
for meshIndx in 1 to theMeshlist.count do
|
|
(
|
|
RsPedValidation.nameLengthCheck theMeshlist[meshIndx].name -- check node name length
|
|
RsPedValidation.checkMeshErrors theMeshlist[meshIndx] -- run through mesh error checks
|
|
RsPedValidation.checkRaceIDName theMeshlist[meshIndx] -- checks race identifiers
|
|
RsPedValidation.shaderErrorChecks theMeshlist[meshIndx] -- run through shader error checks
|
|
RsPedValidation.highLowCheck theMeshlist[meshIndx] -- run through high and low mesh error checks
|
|
RsPedValidation.doesObjHaveDamageBake theMeshlist[meshIndx] -- check mesh for damage UV's
|
|
)
|
|
|
|
RsPedValidation.checkNodeNamesAreSequential theMeshlist -- check that all similar meshes are numbered sequentially
|
|
-- if gRsUlog.HasNewErrorsWarnings() == true then ShowRsUlogDialog()
|
|
)
|
|
return theMeshlist
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn validatePedPostRig =
|
|
--=========================================================================
|
|
-- Description: Runs through all the ped validation check functions for a rigged ped
|
|
--=========================================================================
|
|
fn validatePedPostRig =
|
|
(
|
|
local theMeshlist = RsPedValidation.validatePedPreRig()
|
|
local isSkeletonValid = RsPedValidation.checkSkeletonIsValid()
|
|
if isSkeletonValid == true then
|
|
(
|
|
if theMeshlist.count > 0 then
|
|
(
|
|
max modify mode
|
|
undo on
|
|
(
|
|
with redraw off
|
|
for meshIndx in 1 to theMeshlist.count do
|
|
(
|
|
select theMeshlist[meshIndx] -- select node
|
|
RsPedValidation.skinningErrorChecks theMeshlist[meshIndx] -- run through skinning error checks
|
|
)
|
|
)
|
|
max undo
|
|
)
|
|
-- if gRsUlog.HasNewErrorsWarnings() == true then ShowRsUlogDialog()
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn validatePedPostExprt =
|
|
--=========================================================================
|
|
-- Description: checks data is in perforce
|
|
--=========================================================================
|
|
fn validatePedPostExprt=
|
|
(
|
|
RsPedValidation.checkAllInP4()
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_checkIfBonesSkinned =
|
|
--=========================================================================
|
|
-- Description: checks if verts are skinned to fingers and toe bones
|
|
--=========================================================================
|
|
fn RsTa_checkIfBonesSkinned obj fingerString toeString &fingersFlag &toesFlag=
|
|
(
|
|
max modify mode
|
|
|
|
select obj
|
|
|
|
local numVerts = obj.numVerts
|
|
local theSkin = obj.modifiers[#Skin]
|
|
|
|
local fingerCheck = false
|
|
local toeCheck = false
|
|
|
|
if(theSkin != undefined) then
|
|
(
|
|
modPanel.setCurrentObject theSkin
|
|
for theVert = 1 to numVerts do
|
|
(
|
|
local numBones = skinOps.GetVertexWeightCount theSkin theVert
|
|
for theBone = 1 to numBones do
|
|
(
|
|
local theBoneID = skinOps.GetVertexWeightBoneID theSkin theVert theBone
|
|
local theBoneName = skinOps.GetBoneName theSkin theBoneID 1
|
|
|
|
local stringTest = findString theBoneName fingerString
|
|
|
|
if (stringTest != undefined) then
|
|
(
|
|
local theWeight = skinOps.GetVertexWeight theSkin theVert theBone
|
|
if (theWeight > 0.25) then fingerCheck = true
|
|
)
|
|
else
|
|
(
|
|
stringTest = findString theBoneName toeString
|
|
|
|
if (stringTest != undefined) then
|
|
(
|
|
local theWeight = skinOps.GetVertexWeight theSkin theVert theBone
|
|
if (theWeight > 0.25) then toeCheck = true
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
if (fingerCheck == true) then fingersFlag += 1
|
|
else if (toeCheck == true) then toesFlag += 1
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_validateFingerToes =
|
|
--=========================================================================
|
|
-- Description: validates finger and toe bone skinning
|
|
--=========================================================================
|
|
fn RsTa_validateFingerToes=
|
|
(
|
|
local theSelection = getCurrentSelection()
|
|
local theCount = theSelection.count
|
|
local fingersFlag = 0
|
|
local toesFlag = 0
|
|
|
|
if (theCount != 0) then for obj in theSelection do RsPedValidation.RsTa_checkIfBonesSkinned obj "Finger" "Toe" &fingersFlag &toesFlag
|
|
|
|
if (fingersFlag == 0 and toesFlag == 0) then
|
|
(
|
|
local msg ="Fingers and toes are not skinned."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
else if (fingersFlag == 0) then
|
|
(
|
|
local msg ="Fingers are not skinned."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
else if (toesFlag == 0) then
|
|
(
|
|
local msg ="Toes are not skinned."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_findSkinnedObjects =
|
|
--=========================================================================
|
|
-- Description: Finds objects that are either skinned but not parented for export, or not skinned
|
|
--=========================================================================
|
|
fn RsTa_findSkinnedObjects=
|
|
(
|
|
local unparentedArray = #()
|
|
local unskinnedArray = #()
|
|
|
|
for obj in objects where (classof obj.baseObject == Editable_poly or classOf obj.BaseObject == Editable_mesh) do
|
|
(
|
|
if (obj.modifiers[#Skin] != undefined) then
|
|
(
|
|
if (obj.parent == undefined) then append unparentedArray obj.name
|
|
)
|
|
|
|
else if (obj.modifiers[#Skin] == undefined) then
|
|
(
|
|
local lowerCaseName = toLower obj.name
|
|
if (findString lowerCaseName "mover" == undefined and findString lowerCaseName "p_" == undefined) then append unskinnedArray obj.name
|
|
)
|
|
)
|
|
|
|
if (unparentedArray.count != 0) then
|
|
(
|
|
for str in unparentedArray do
|
|
(
|
|
local msg =("\""+str+"\" is skinned but not parented to the export dummy.")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
|
|
if (unskinnedArray.count != 0) then
|
|
(
|
|
for str in unskinnedArray do
|
|
(
|
|
local msg =("\""+str+"\" is not skinned.")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_findExportObjects =
|
|
--=========================================================================
|
|
-- Description: Finds the file's export dummy, gets exporting objects from it
|
|
--=========================================================================
|
|
fn RsTa_findExportObjects=
|
|
(
|
|
clearSelection()
|
|
|
|
local fileName = filterString maxFileName "."
|
|
fileName = fileName[1]
|
|
local exportDummy = getNodeByName fileName
|
|
|
|
if (exportDummy != undefined) then
|
|
(
|
|
select exportDummy.children
|
|
)
|
|
else
|
|
(
|
|
local msg ="Could not find the export dummy. Please check the dummy exists and is named properly."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_confirmNullsExist =
|
|
--=========================================================================
|
|
-- Description: Validates PH, IK etc nodes exist in scene
|
|
--=========================================================================
|
|
fn RsTa_confirmNullsExist=
|
|
(
|
|
local missingObjs = #()
|
|
local findNameList = #("Dummy01", "IK_Head", "IK_L_Foot", "IK_L_Hand", "IK_R_Foot", "IK_R_Hand", "IK_Root", "PH_L_Foot", "PH_L_Hand", "PH_R_Foot", "PH_R_Hand")
|
|
|
|
for x in findNameList do if (getNodeByName x == undefined) then append missingObjs x
|
|
|
|
if (missingObjs.count != 0) then
|
|
(
|
|
for str in missingObjs do
|
|
(
|
|
local msg =("\""+str+"\" is missing from the scene.")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_traverseXmlTree =
|
|
--=========================================================================
|
|
-- Description: Checks bone tag XML and compares to tags on facial nodes
|
|
--=========================================================================
|
|
fn RsTa_traverseXmlTree ele objList=
|
|
(
|
|
local noTagObjList = #()
|
|
local theCheck = true
|
|
|
|
for obj in objList do
|
|
(
|
|
for i = 0 to ele.childNodes.count-1 do
|
|
(
|
|
local bName = (ele.ChildNodes.itemOf[i].GetAttributeNode "name").value
|
|
local bTag = (ele.ChildNodes.itemOf[i].GetAttributeNode "id").value
|
|
|
|
if (findString obj.name bName != undefined) then
|
|
(
|
|
local uPropTag = getUserProp obj "tag"
|
|
|
|
if (findString obj.name "root" != undefined and findString bName "root" != undefined) then
|
|
(
|
|
if (uPropTag != bTag) then append noTagObjList obj.name
|
|
)
|
|
else if (findString obj.name "root" == undefined) then
|
|
(
|
|
if (uPropTag != bTag) then append noTagObjList obj.name
|
|
)
|
|
|
|
|
|
--format "obj: %\t bTag: %\tuPropTag: %\n" obj bTag uPropTag
|
|
)
|
|
)
|
|
)
|
|
if (noTagObjList.count != 0) then
|
|
(
|
|
local msgString = ""
|
|
for str in noTagObjList do
|
|
(
|
|
local msg =("\""+str+"\" has missing or incorrect bone tag.")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_validateBoneTag =
|
|
--=========================================================================
|
|
-- Description: Opens bone tag XML file, compares tags on facial nodes to the XML
|
|
--=========================================================================
|
|
fn RsTa_validateBoneTag=
|
|
(
|
|
local facialNodes = #()
|
|
for obj in objects do
|
|
(
|
|
if (findString obj.name "FB_" != undefined) then append facialNodes obj
|
|
else if (findString obj.name "FACIAL_" != undefined) then append facialNodes obj
|
|
else if (findString obj.name "facialRoot_" != undefined) then append facialNodes obj
|
|
else if (findString obj.name "FaceRoot_" != undefined) then append facialNodes obj
|
|
)
|
|
|
|
theCount = facialNodes.count
|
|
|
|
if (theCount != 0) then
|
|
(
|
|
xmlPath = (RsConfigGetToolsDir() + "etc/content/animconfig/bone_tags.xml")
|
|
|
|
--Load the xml assembly
|
|
dotNet.loadAssembly "system.xml"
|
|
--Create an xml document object.
|
|
xmlDoc=dotNetObject "system.xml.xmlDocument"
|
|
|
|
if doesFileExist xmlPath then
|
|
(
|
|
--Load the XML file.
|
|
xmlDoc.load xmlPath
|
|
--Check to make sure the xmlDoc has a root element.
|
|
docEle=xmlDoc.documentElement
|
|
|
|
--If the root element exists continue.
|
|
if (docEle!=undefined and docEle.name=="boneids") then
|
|
(
|
|
local subTree = undefined
|
|
|
|
for j = 0 to docEle.childNodes.count-1 do
|
|
(
|
|
if (docEle.ChildNodes.itemOf[j].name == "peds") then subTree = docEle.ChildNodes.itemOf[j]
|
|
)
|
|
|
|
if (subTree != undefined) then
|
|
(
|
|
for j = 0 to subTree.childNodes.count-1 do
|
|
(
|
|
if (subTree.ChildNodes.itemOf[j].name == "boneids") then subTree = subTree.ChildNodes.itemOf[j]
|
|
)
|
|
|
|
--Traverse the XML tree.
|
|
if (subTree.name == "boneids") then RsTa_traverseXmlTree subTree facialNodes
|
|
)
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
local msg ="No facial rig nodes found."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_validateSingleSkeleton =
|
|
--=========================================================================
|
|
-- Description: Checks if more than one dummy01 exists
|
|
--=========================================================================
|
|
fn RsTa_validateSingleSkeleton=
|
|
(
|
|
local dummyCount = 0
|
|
|
|
for o in objects do
|
|
(
|
|
if ((toLower o.name) == "dummy01") then dummyCount += 1
|
|
)
|
|
|
|
if dummyCount > 1 then
|
|
(
|
|
local msg ="More than one Dummy01 found. May be more than one skeleton in file."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_validateHeels =
|
|
--=========================================================================
|
|
-- Description: Looks for heel height slider
|
|
--=========================================================================
|
|
fn RsTa_validateHeels=
|
|
(
|
|
if (getNodeByName "HeelHeight" == undefined) then
|
|
(
|
|
local msg ="HeelHeight slider is missing. If it isn't required then ignore this."
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_addTexture =
|
|
--=========================================================================
|
|
-- Description: Adds scene texture to an array pointer
|
|
--=========================================================================
|
|
fn RsTa_addTexture textureFile &textureList=
|
|
(
|
|
local index = finditem textureList textureFile
|
|
if index == 0 do append textureList textureFile
|
|
),
|
|
|
|
--=========================================================================
|
|
-- fn RsTa_checkTexP4Status =
|
|
--=========================================================================
|
|
-- Description: Checks all scene textures to see if they exist in P4
|
|
--=========================================================================
|
|
fn RsTa_checkTexP4Status=
|
|
(
|
|
local textureList = #()
|
|
local missingList = #()
|
|
enumerateFiles RsTa_addTexture &textureList
|
|
|
|
for i = 1 to textureList.count do textureList[i] = toLower textureList[i]
|
|
|
|
local isCheckedIn = gRsPerforce.exists textureList silent:false
|
|
|
|
for i = 1 to textureList.count do
|
|
(
|
|
if (isCheckedIn[i] == false) then append missingList textureList[i]
|
|
)
|
|
|
|
if (missingList.count > 0) then
|
|
(
|
|
local msgString = ""
|
|
for str in missingList do
|
|
(
|
|
local msg =("\""+str+"\" : texture is not in perforce, or a file is outside of the client view.")
|
|
gRsPedValidationULog.LogWarning msg appendToFile:false context:"model"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
RsPedValidation = RsPedValidationStruct()
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
--3L functions
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
--a function to delete old physic collision bounds and contraints. should be obsolete in almost all scenes
|
|
fn tidyPhysics =
|
|
(
|
|
try
|
|
(
|
|
clearSelection()
|
|
select $collis*
|
|
max delete
|
|
)
|
|
catch ()
|
|
|
|
try
|
|
(
|
|
clearSelection()
|
|
select $constraint*
|
|
max delete
|
|
)
|
|
catch ()
|
|
)
|
|
|
|
-- Take an object and apply/remove an stl check
|
|
fn stlChecker meshObj stlSetValue =
|
|
(
|
|
select meshObj
|
|
|
|
-- If true, then add and activate the STL check
|
|
if stlSetValue == true then
|
|
(
|
|
max modify mode
|
|
addmodifier meshObj (STL_Check ()) ui:on
|
|
$.modifiers[#STL_Check].Check_Now = 1
|
|
--actionMan.executeAction 0 "281" -- Tools: Hide Unselected
|
|
--max tool zoomextents
|
|
)
|
|
|
|
-- If false then remove the STL check
|
|
if stlSetValue == false then
|
|
(
|
|
modPanel.setCurrentObject $.modifiers[#STL_Check]
|
|
STLmod = $.modifiers[#STL_Check]
|
|
if STLmod != undefined then deleteModifier $ STLmod
|
|
)
|
|
)
|
|
|
|
-- We have 2 required named components for rigging.
|
|
fn CheckComponentNames =
|
|
(
|
|
allgood = true
|
|
clearSelection()
|
|
selectByWildcard "head_000"
|
|
curSel = getCurrentSelection()
|
|
|
|
if curSel.count < 1 then
|
|
(
|
|
messagebox "Could not find an object named as a head"
|
|
allgood = false
|
|
)
|
|
|
|
else
|
|
(
|
|
splitname = filterstring $.name " "
|
|
if splitname[1].count != 10 then
|
|
(
|
|
messagebox "Could not find an object named head_000_R - probably almost correct though"
|
|
allgood = false
|
|
)
|
|
)
|
|
|
|
clearSelection()
|
|
selectByWildcard "teef_000"
|
|
curSel = getCurrentSelection()
|
|
|
|
if curSel.count < 1 then
|
|
(
|
|
messagebox "Could not find an object named as teef"
|
|
allgood = false
|
|
)
|
|
|
|
else
|
|
(
|
|
splitname = filterstring $.name " "
|
|
if splitname[1].count != 10 then
|
|
(
|
|
messagebox "Could not find an object named teef_000_R - probably almost correct though"
|
|
allgood = false
|
|
)
|
|
)
|
|
|
|
clearSelection()
|
|
|
|
if allgood == true then messagebox "Components seem good"
|
|
)
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
--UI
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
(
|
|
global pedValidationTools
|
|
try (cui.UnRegisterDialogBar pedValidationTools)catch()
|
|
try(destroyDialog pedValidationTools)catch()
|
|
local LastSubRollout = 1
|
|
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
rollout pedValidation "Ped Validation Tools"
|
|
(
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
on pedValidation open do
|
|
(
|
|
gRsPedValidationULog.Init "ped validation" appendToFile:false forceLogFile:gPedValidationLogFile -- initialize Universal Log
|
|
pedValidationTools.height = 270
|
|
)
|
|
|
|
group "Validate:"
|
|
(
|
|
label lblPBar "Validation Result:" align:#center offset:[-10, 0]
|
|
progressbar pBarValStatus color:green offset:[108, -18] width:20
|
|
button btn_valPreRig "Pre Rig" width:150
|
|
button btn_valPostRig "Post Rig" width:150
|
|
button btn_valPostExp "Post Export" width:150
|
|
button btn_valPreRes "Pre Resource" width:150
|
|
)
|
|
button btn_toggleErrorLog "Toggle Error Log" width:150
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
/*
|
|
Pre-Resource Validation functions
|
|
*/
|
|
on btn_valPreRes pressed do
|
|
(
|
|
if queryBox "Does this character have a 3Lateral setup?" beep:true title:"3L Query" do
|
|
(
|
|
filein (theWildwest + "/script/3dsMax/Characters/Rigging/3Lateral/RSTA_fixThreeLateralAlphAGuiShaders.ms")
|
|
filein (theWildwest + "/script/3dsMax/Characters/Rigging/3Lateral/reconnectWrinkleMaps.ms")
|
|
)
|
|
|
|
gRsPedValidationULog.ClearLogDirectory() --clear the uLog
|
|
pBarValStatus.value = 0--reset the progress bar
|
|
|
|
start = timeStamp()
|
|
|
|
RsPedValidation.RsTa_findExportObjects()
|
|
RsPedValidation.RsTa_validateFingerToes()
|
|
RsPedValidation.RsTa_findSkinnedObjects()
|
|
RsPedValidation.RsTa_confirmNullsExist()
|
|
RsPedValidation.RsTa_validateBoneTag()
|
|
RsPedValidation.RsTa_validateSingleSkeleton()
|
|
RsPedValidation.RsTa_validateHeels()
|
|
RsPedValidation.RsTa_checkTexP4Status()
|
|
|
|
end = timeStamp()
|
|
|
|
local valErrors = gRsPedValidationULog.HasNewErrorsWarnings()
|
|
if (valErrors == true) then
|
|
(
|
|
pBarValStatus.color = orange--make the progress bar colour red
|
|
pBarValStatus.value = 100--set the progress bar to full
|
|
ShowRsUlogDialog()--show the ulog
|
|
)
|
|
else
|
|
(
|
|
pBarValStatus.color = green--make the progress bar colour green
|
|
pBarValStatus.value = 100
|
|
)
|
|
|
|
format "Processing took % seconds\n" ((end - start) / 1000.0)
|
|
)
|
|
|
|
on btn_valPreRig pressed do --Validate - Pre Rig
|
|
(
|
|
pBarValStatus.value = 0--reset the progress bar
|
|
gRsPedValidationULog.Init "" appendToFile:false
|
|
RsPedValidation.validatePedPreRig()
|
|
local valErrors = gRsPedValidationULog.HasNewErrorsWarnings()
|
|
if valErrors == true then
|
|
(
|
|
pBarValStatus.color = red--make the progress bar colour red
|
|
pBarValStatus.value = 100--set the progress bar to full
|
|
ShowRsUlogDialog()--show the ulog
|
|
)
|
|
else--if the validation completed without errors
|
|
(
|
|
pBarValStatus.color = green--make the progress bar colour green
|
|
pBarValStatus.value = 100
|
|
)
|
|
)
|
|
|
|
on btn_valPostRig pressed do --Validate - Post Rig
|
|
(
|
|
pBarValStatus.value = 0--reset the progress bar
|
|
gRsPedValidationULog.Init "" appendToFile:false
|
|
RsPedValidation.validatePedPostRig()
|
|
local valErrors = gRsPedValidationULog.HasNewErrorsWarnings()
|
|
if valErrors == true then
|
|
(
|
|
pBarValStatus.color = red
|
|
pBarValStatus.value = 100
|
|
ShowRsUlogDialog()
|
|
)
|
|
else
|
|
(
|
|
pBarValStatus.color = green
|
|
pBarValStatus.value = 100
|
|
)
|
|
)
|
|
on btn_valPostExp pressed do --Validate Post Export
|
|
(
|
|
pBarValStatus.value = 0--reset the progress bar
|
|
gRsPedValidationULog.Init "" appendToFile:false
|
|
RsPedValidation.validatePedPostExprt()
|
|
local valErrors = gRsPedValidationULog.HasNewErrorsWarnings()
|
|
if valErrors == true then
|
|
(
|
|
pBarValStatus.color = red
|
|
pBarValStatus.value = 100
|
|
ShowRsUlogDialog()
|
|
)
|
|
else
|
|
(
|
|
pBarValStatus.color = green
|
|
pBarValStatus.value = 100
|
|
)
|
|
)
|
|
|
|
on btn_toggleErrorLog pressed do --show the ulog window
|
|
(
|
|
case of
|
|
(
|
|
(gRsUlogDialog.isvisible == false): ShowRsUlogDialog()--if the ulog is closed show it
|
|
(gRsUlogDialog.isvisible == true): gRsUlogDialog.close()--if the ulog is open close it
|
|
)
|
|
)
|
|
)--end pedValidation rollout
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
rollout threeLValidation "3L Validation Tools"
|
|
(
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
button btnCheckComponentNames "Check Component Names" width:160 height:25
|
|
button btnCheckTeef "Check Teef" width:160 height:25
|
|
button btnSTLCheckOn "Add STL Checks" width:160 height:25
|
|
button btnSTLCheckOff "Remove STL Checks" width:160 height:25
|
|
--button btntidyPhysics "Remove Collision Constraints" width:160 height:25
|
|
button btnCheckForSkeleton "Check For Skeleton" width:160 height:25
|
|
button btnCheckForSkin "Check For Skin" width:160 height:25
|
|
button btnHideNonMesh "Hide Bones/Helpers" width:160 height:25
|
|
button btnFinalViews "Final Views" width:160 height:25
|
|
button btnExportHeadOBJ "Export Head OBJ" width:160 height:25
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
on threeLValidation open do
|
|
(
|
|
sliderTime = 0f
|
|
pedValidationTools.theSubRollout.height = 565
|
|
pedValidationTools.height = 370
|
|
)
|
|
|
|
on btnCheckComponentNames pressed do CheckComponentNames()
|
|
|
|
on btnSTLCheckOn pressed do
|
|
(
|
|
selectByWildcard "head_000_R"
|
|
headmesh = getcurrentSelection()
|
|
|
|
selectByWildcard "teef_000_U"
|
|
teethmesh = getcurrentSelection()
|
|
|
|
stlChecker headmesh true
|
|
stlChecker teethmesh true
|
|
|
|
select headmesh
|
|
selectmore teethmesh
|
|
)
|
|
|
|
on btnCheckTeef pressed do
|
|
(
|
|
DefaultTeefValue = 1000
|
|
|
|
try
|
|
(
|
|
selectByWildcard "teef_000_U"
|
|
teethmesh = getcurrentSelection()
|
|
teethmesh = teethmesh[1]
|
|
theVertCount = getNumVerts teethmesh
|
|
|
|
if theVertCount > DefaultTeefValue do
|
|
(
|
|
messageBox "Teef ok"
|
|
)
|
|
|
|
if theVertCount < DefaultTeefValue do
|
|
(
|
|
messageBox "You should check the teef"
|
|
)
|
|
)
|
|
catch (messageBox "no teef object")
|
|
)
|
|
|
|
on btnSTLCheckOff pressed do
|
|
(
|
|
selectByWildcard "head_000_R"
|
|
headmesh = getcurrentSelection()
|
|
|
|
selectByWildcard "teef_000_U"
|
|
teethmesh = getcurrentSelection()
|
|
|
|
stlChecker headmesh false
|
|
stlChecker teethmesh false
|
|
)
|
|
|
|
on btntidyPhysics pressed do (tidyPhysics())--redundant button, added to hide bones/helpers
|
|
|
|
on btnCheckForSkeleton pressed do
|
|
(
|
|
clearSelection()
|
|
select ped_rootbone
|
|
for thebone in selection do
|
|
(
|
|
try (selectmore thebone.children) catch ()
|
|
)
|
|
|
|
selectedbones = $
|
|
if selectedbones.count < 70 then
|
|
(messagebox ("Skeleton seems wrong, found " + (selectedbones.count as string)+ ", expected at least 70"))
|
|
else
|
|
(messagebox "Skeleton seems to be OK")
|
|
)
|
|
|
|
on btnCheckForSkin pressed do
|
|
(
|
|
selectByWildcard "uppr_000_"
|
|
uppermesh = getcurrentSelection()
|
|
skinmod = $.modifiers[#Skin]
|
|
if skinmod == undefined then
|
|
(messagebox "Couldn't find a skin on the upper, assuming no skinning in scene")
|
|
else
|
|
(messagebox "Found a skin on the upper, assuming there is skinning in scene - but double check")
|
|
)
|
|
|
|
on btnHideNonMesh pressed do
|
|
(
|
|
tidyPhysics()
|
|
hideByCategory.all()
|
|
hideByCategory.geometry = false
|
|
try
|
|
(
|
|
select $mover
|
|
max hide selection
|
|
)
|
|
catch()
|
|
)
|
|
|
|
on btnFinalViews pressed do
|
|
(
|
|
max vpt front
|
|
max tool zoomextents
|
|
)
|
|
|
|
on btnExportHeadOBJ pressed do
|
|
(
|
|
clearSelection()
|
|
selectByWildcard "head_000"
|
|
OBJOutputPath = "c:/temp/headOBJs"
|
|
makeDir (OBJOutputPath)
|
|
OBJOutputName = OBJOutputPath + "/" + (getFilenameFile maxFileName)
|
|
|
|
exportClasses =exporterPlugin.classes
|
|
--find the obj index
|
|
objExpIndex = undefined
|
|
for exportclassIndex = 1 to exportClasses.count do
|
|
(
|
|
ec = exportClasses[exportclassIndex]
|
|
if (uppercase (substring (ec as string) 1 3 )) == "OBJ" then objExpIndex = exportclassIndex
|
|
)
|
|
|
|
-- Export the the obj
|
|
exportFile (OBJOutputName) using:exportClasses[objExpIndex] selectedOnly:true
|
|
)
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
)--end threeLValidation rollout
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
pedValidationTools_Rollouts = #(#("Ped Validation",#(pedValidation)), #("3L Validation",#(threeLValidation)))
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
rollout pedValidationTools "Ped Validation Toolkit"
|
|
(
|
|
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:pedValidationTools.width
|
|
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"Ped_Validation_Toolkit" doOutline:false filename:(getThisScriptFilename())
|
|
|
|
dotNetControl dn_tabs "System.Windows.Forms.TabControl" height:20 width:155 align:#left
|
|
subRollout theSubRollout width:185 height:285 align:#center
|
|
|
|
on dn_tabs Selected itm do
|
|
(
|
|
if LastSubRollout != (itm.TabPageIndex+1) do --do not update if the same tab clicked twice
|
|
(
|
|
for subroll in pedValidationTools_Rollouts[LastSubRollout][2] do
|
|
removeSubRollout theSubRollout subroll
|
|
for subroll in pedValidationTools_Rollouts[LastSubRollout = itm.TabPageIndex+1][2] do
|
|
addSubRollout theSubRollout subroll
|
|
)
|
|
)--end tabs clicked
|
|
-------------------------------------------------------------------------------------------------------------------------
|
|
on pedValidationTools open do
|
|
(
|
|
rs_dialogPosition "get" pedValidationTools --load the ui position
|
|
banner.setup()
|
|
for aTab in pedValidationTools_Rollouts do
|
|
(dn_tabs.TabPages.add aTab[1])
|
|
for subroll in pedValidationTools_Rollouts[1][2] do
|
|
addSubRollout theSubRollout subroll
|
|
)
|
|
---------------------------------------------------------
|
|
on pedValidationTools close do
|
|
(
|
|
rs_dialogPosition "set" pedValidationTools --store the ui position
|
|
)
|
|
)
|
|
)
|
|
createDialog pedValidationTools 185 280 |