601 lines
22 KiB
Plaintext
Executable File
601 lines
22 KiB
Plaintext
Executable File
RSTA_LoadCommonFunction #("FN_RSTA_rageMat.ms")
|
|
|
|
struct struct_PedValidationTool
|
|
(
|
|
private
|
|
_targetPed = undefined,
|
|
_validComponentNames = #("head", "hair", "hand", "uppr", "lowr", "feet", "jbib", "accs", "berd", "task", "teef", "decl",
|
|
"p_head", "p_eyes", "p_ears", "p_lwrist", "p_rwrist"),
|
|
_validPedPresets = #("ped.sps", "ped_nopeddamagedecals.sps", "ped_alpha.sps", "ped_decal.sps", "ped_decal_decoration.sps",
|
|
"ped_hair_cutout_alpha.sps", "ped_hair_spiked.sps", "ped_emissive.sps", "ped_fur.sps"),
|
|
_validRacialTags = #("whi", "ita", "chi", "lat" , "jam", "bla", "ara", "pak", "bal", "kor"),
|
|
_normalSpecExceptionPresets = #("ped_decal.sps", "ped_decal_decoration.sps", "ped_fur.sps"),
|
|
|
|
_validationReport = "",
|
|
_geoValidationReport_Arr = #(),
|
|
_textureValidationReport_Arr = #(),
|
|
_materialValidationReport_Arr = #(),
|
|
|
|
|
|
-- Scaling Validation
|
|
fn fn_ValidateScale =
|
|
(
|
|
local currentScale = #(this._targetPed.scale.x, this._targetPed.scale.y, this._targetPed.scale.z)
|
|
local idealScale = 1.0
|
|
|
|
-- If the scale is not ideal, add an Xform modifier and collapse
|
|
local modifiedScale_arr = for scaleVal in currentScale where scaleVal != idealScale collect scaleVal
|
|
if modifiedScale_arr.count > 0 do
|
|
(
|
|
-- Reset Xform
|
|
resetXform this._targetPed
|
|
deleteModifier this._targetPed 1
|
|
|
|
-- Check if the scale is negative
|
|
local isScaleNegative = false
|
|
for scaleVal in currentScale do
|
|
(
|
|
if scaleVal < 0 do isScaleNegative = true
|
|
break
|
|
)
|
|
|
|
-- If negative, flip the normals
|
|
if isScaleNegative then
|
|
(
|
|
addModifier this._targetPed (Normalmodifier flip:true)
|
|
append this._geoValidationReport_Arr "\nNegative scale found. Xform has been applied and flipped normals reversed."
|
|
)
|
|
else
|
|
(
|
|
append this._geoValidationReport_Arr "\nScaling issues found. Xform has been applied."
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Extracts the component name from the passed name
|
|
fn fn_GetComponentName passedName =
|
|
(
|
|
if passedName == "" do return undefined
|
|
|
|
local compName = undefined
|
|
|
|
if matchPattern passedName pattern:"p_*" then
|
|
(
|
|
-- Prop naming starts with "p_" so join the first and second item to form the name
|
|
local nameElements = filterString passedName "_"
|
|
compName = nameElements[1] + "_" + nameElements[2]
|
|
)
|
|
else
|
|
(
|
|
-- Get the first element in the name string
|
|
compName = (filterString passedName "_")[1]
|
|
)
|
|
|
|
return compName
|
|
),
|
|
|
|
-- Get tne suffix from a geo name
|
|
fn fn_GetSuffix passedName =
|
|
(
|
|
local nameElems = filterString passedName "_"
|
|
local nameSuffix = undefined
|
|
|
|
if matchPattern passedName pattern:"p_*" then nameSuffix = nameElems[4]
|
|
else nameSuffix = nameElems[3]
|
|
|
|
return nameSuffix
|
|
),
|
|
|
|
fn fn_GetSequenceNum passedName isGeo:false isTex:false =
|
|
(
|
|
if passedName == "" do return undefined
|
|
|
|
local seqNum = undefined
|
|
|
|
-- Geo names have pattern <compName>_<seqNum>_<racialTag>
|
|
if isGeo do
|
|
(
|
|
if (matchPattern passedName pattern:"p_*") then seqNum = (filterString passedName "_ ")[3]
|
|
else seqNum = (filterString passedName "_ ")[2]
|
|
)
|
|
|
|
-- Texture names have pattern <compName>_<mapName>_<seqNum>_<racialTag>, so +1 element
|
|
if isTex do
|
|
(
|
|
if (matchPattern passedName pattern:"p_*") then seqNum = (filterString passedName "_")[4]
|
|
else seqNum = (filterString passedName "_")[3]
|
|
)
|
|
|
|
return (seqNum as integer)
|
|
|
|
),
|
|
|
|
fn fn_GetRacialTag passedName isGeo:false isTex:false =
|
|
(
|
|
if passedName == "" do return undefined
|
|
if (matchPattern passedName pattern:"p_*") do return undefined -- Since props have no race tag
|
|
|
|
local racialTag = undefined
|
|
|
|
if isGeo do racialTag = (filterString passedName "_ ")[3]
|
|
if isTex do racialTag = (filterString passedName "_")[5]
|
|
|
|
return racialTag
|
|
),
|
|
|
|
-- Check that the naming of assets is consistent with set standards
|
|
fn fn_ValidateComponentName =
|
|
(
|
|
-- Get all child meshes of selection
|
|
local childGeo = for child in this._targetPed.children where (superClassOf child == GeometryClass) collect child
|
|
|
|
local namingIssues = #()
|
|
for geo in childGeo do
|
|
(
|
|
local componentName = this.fn_GetComponentName geo.name
|
|
if (findItem this._validComponentNames (toLower componentName) == 0) do appendIfUnique namingIssues ("\nGeo component naming issue found: " + geo.name)
|
|
)
|
|
|
|
-- Add any possile issues to the global report arrays
|
|
if namingIssues.count > 0 do
|
|
(
|
|
for issue in namingIssues do
|
|
(
|
|
appendIfUnique this._geoValidationReport_Arr issue
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Compares 2 strings (Used for sorting)
|
|
fn fn_CompareStrings string1 string2 =
|
|
(
|
|
stricmp string1 string2
|
|
),
|
|
|
|
-- Validates Component sequence, Eg: jbib_000_*, jbib_001_*, jbib_0002_*, etc.
|
|
fn fn_ValidateComponentSequence =
|
|
(
|
|
-- Get all child meshes of selection
|
|
local childGeoNames = for child in this._targetPed.children where (superClassOf child == GeometryClass) collect child.name
|
|
|
|
local seqIssues = #()
|
|
|
|
for cgName in childGeoNames do
|
|
(
|
|
cgName_Main = (filterString cgName " ")[1] -- Disregard string data after the space in name
|
|
local componentName = this.fn_GetComponentName cgName_Main
|
|
local compNamePattern = componentName + "_*"
|
|
|
|
-- Using the component name pattern, get other geoNames that have the same prefix
|
|
local seqGeoNames = #()
|
|
for refName in childGeoNames do
|
|
(
|
|
--refName = (filterString refName " ")[1] -- remove whats after the space
|
|
refName_elems = filterString refName "_"
|
|
refName_toConsider = refName_elems[1] + "_" + refName_elems[2] -- only considering component name + component number, eg. accs_001
|
|
if matchPattern refName_toConsider pattern:compNamePattern do appendIfUnique seqGeoNames (toLower refName_toConsider)
|
|
)
|
|
|
|
-- If we find matches
|
|
if seqGeoNames.count > 1 do
|
|
(
|
|
-- Sort the names
|
|
qSort seqGeoNames this.fn_CompareStrings
|
|
|
|
-- Start from 0 and keep checking for a consistent sequence in the matched geos
|
|
local seqErrorFound = false
|
|
local counterNum = 0
|
|
for geoName in seqGeoNames while not seqErrorFound do
|
|
(
|
|
local expectedSeqNum = formattedPrint counterNum format:"03d"
|
|
|
|
-- Get the sequence number from the geo name
|
|
local seqNum = -1
|
|
if (matchPattern geoName pattern:"p_*") then seqNum = (filterString geoName "_")[3] else seqNum = (filterString geoName "_")[2]
|
|
|
|
-- Check if the seqNum matches what we expect
|
|
if seqNum == expectedSeqNum then counterNum += 1 else
|
|
(
|
|
appendIfUnique seqIssues ("\nSequencing issue found: " + geoName)
|
|
seqErrorFound = true
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add any possile issues to the global report arrays
|
|
if seqIssues.count > 0 do
|
|
(
|
|
for issue in seqIssues do
|
|
(
|
|
appendIfUnique this._geoValidationReport_Arr issue
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Validates Mateials and Textures
|
|
fn fn_ValidateMatsAndTex =
|
|
(
|
|
-- Get all child meshes of selection
|
|
local childGeo = for child in this._targetPed.children where (superClassOf child == GeometryClass) collect child
|
|
local materialIssues = #()
|
|
|
|
for geo in childGeo do
|
|
(
|
|
local isEditMesh = false
|
|
|
|
-- If the base object is an Editable Mesh, add an edit-poly mod on top, then clear it later
|
|
if classOf geo == Editable_mesh do
|
|
(
|
|
isEditMesh = True
|
|
addModifier geo (Edit_Poly ())
|
|
)
|
|
|
|
local geoLinkedMats = this.fn_GetLinkedMeshMats geo
|
|
for currentMaterial in geoLinkedMats do
|
|
(
|
|
if currentMaterial != undefined then
|
|
(
|
|
if (rsta_rageMat.isRageMat currentMaterial) then
|
|
(
|
|
this.fn_SingleMatTextureCheck currentMaterial geo
|
|
this.fn_ValidateTextureNaming geo currentMaterial
|
|
)
|
|
-- If currentMaterial is not a Rage_Shader, then it is invalid
|
|
else
|
|
(
|
|
append materialIssues ("\nNot a valid rageMat: " + currentMaterial.name)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
append materialIssues ("\nUndefined materials in " + geo.name)
|
|
)
|
|
)
|
|
|
|
-- Clear the temporary Edit_Poly modifier if it was added in
|
|
if isEditMesh do deleteModifier geo geo.modifiers[1]
|
|
)
|
|
|
|
-- Add any possile tex/mat issues to the global report arrays
|
|
if materialIssues.count > 0 do
|
|
(
|
|
for issue in materialIssues do
|
|
(
|
|
appendIfUnique this._materialValidationReport_Arr issue
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Works in conjunction with fn_ValidateMatsAndTex, to check the Diff/Norm/Spec textures for a single material
|
|
fn fn_SingleMatTextureCheck currentMaterial currentGeo =
|
|
(
|
|
local materialIssues = #()
|
|
local textureIssues = #()
|
|
local currPreset = rsta_rageMat.getShaderType currentMaterial
|
|
|
|
-- Check if material preset is valid
|
|
if (findItem _validPedPresets currPreset == 0) do append materialIssues ("\nInvalid Rage Preset: " + currentGeo.name + ", " + (currPreset as string))
|
|
|
|
-- Check Diff
|
|
local diffMapPath = rsta_rageMat.getDiffuse currentMaterial
|
|
if (diffMapPath != "") and (doesFileExist diffMapPath) then
|
|
(
|
|
local textureDimCheck = this.fn_TextureDimensionCheck diffMapPath 512
|
|
|
|
-- If check fails, add texPath to issue report
|
|
if textureDimCheck == false do appendIfUnique textureIssues ("\nDiffuse texture size mismatch: " + diffMapPath + "(" + currentMaterial.name + ")" )
|
|
)
|
|
else
|
|
(
|
|
if((diffMapPath == undefined) or (diffMapPath == "")) then
|
|
(
|
|
appendIfUnique textureIssues ("\nMissing diffuse texture in " + currentMaterial.name)
|
|
)
|
|
-- If the path exists but the file is not on disk
|
|
else if ((diffMapPath != "") and (not doesFileExist diffMapPath)) do
|
|
(
|
|
appendIfUnique textureIssues ("\nTexture not found on disk: " + diffMapPath)
|
|
)
|
|
)
|
|
|
|
-- Check Normal
|
|
local normalMapPath = rsta_rageMat.getBump currentMaterial
|
|
if (normalMapPath != undefined) and (doesFileExist normalMapPath) then
|
|
(
|
|
local textureDimCheck = this.fn_TextureDimensionCheck normalMapPath 512
|
|
|
|
-- If check fails, add texPath to issue report
|
|
if textureDimCheck == false do appendIfUnique textureIssues ("\nMormal texture size mismatch: " + normalMapPath + "(" + currentMaterial.name + ")")
|
|
)
|
|
else
|
|
(
|
|
if (normalMapPath == undefined) or (normalMapPath == "") then
|
|
(
|
|
-- Check if preset is within exception list
|
|
if not (findItem _normalSpecExceptionPresets currPreset > 0) do
|
|
(
|
|
appendIfUnique textureIssues ("\nMissing normal texture in " + currentMaterial.name)
|
|
)
|
|
)
|
|
-- If the path exists but the file is not on disk
|
|
else if ((normalMapPath != "") and (not doesFileExist normalMapPath)) do
|
|
(
|
|
appendIfUnique textureIssues ("\nTexture not found on disk: " + normalMapPath)
|
|
)
|
|
)
|
|
|
|
-- Check Spec
|
|
local specMapPath = rsta_rageMat.getSpec currentMaterial
|
|
if (specMapPath != undefined) and (doesFileExist specMapPath) then
|
|
(
|
|
local textureDimCheck = this.fn_TextureDimensionCheck specMapPath 256
|
|
|
|
-- If check fails, add texPath to issue report
|
|
if textureDimCheck == false do appendIfUnique textureIssues ("\nSpec texture size mismatch: " + specMapPath + "(" + currentMaterial.name + ")")
|
|
)
|
|
else
|
|
(
|
|
if (specMapPath == undefined) or (specMapPath == "") then
|
|
(
|
|
-- Check if preset is within exception list
|
|
if not (findItem _normalSpecExceptionPresets currPreset > 0) do
|
|
(
|
|
appendIfUnique textureIssues ("\nMissing specular texture in " + currentMaterial.name)
|
|
)
|
|
)
|
|
-- If the path exists but the file is not on disk
|
|
else if ((specMapPath != "") and (not doesFileExist specMapPath)) do
|
|
(
|
|
appendIfUnique textureIssues ("\nTexture not found on disk: " + specMapPath)
|
|
)
|
|
)
|
|
|
|
-- CHECK IF ALL TEXTURES ARE IN THE PROPER TEXTURE DIRECTORY
|
|
local currFileTexDir = pathConfig.appendPath maxFilePath "Textures\\HighRes\\"
|
|
local thisMatTextures = rsta_ragemat.getAllTextures currentMaterial
|
|
|
|
for tex in thisMatTextures do
|
|
(
|
|
local texPath = ""
|
|
if (tex != "") do (texPath = getFileNamePath tex)
|
|
-- If the texture path is wrong, but not empty
|
|
if (stricmp texPath currFileTexDir != 0) and (texPath != "") do
|
|
(
|
|
format "\ncurrFileTexDir: %" currFileTexDir
|
|
format "\ntexPath: %" texPath
|
|
append textureIssues ("\nTexture not in project dir: " + tex + "(" + currentMaterial.name + ")")
|
|
)
|
|
)
|
|
|
|
-- Add any possile issues to the global report arrays
|
|
if textureIssues.count > 0 do
|
|
(
|
|
for issue in textureIssues do
|
|
(
|
|
appendIfUnique this._textureValidationReport_Arr issue
|
|
)
|
|
)
|
|
|
|
if materialIssues.count > 0 do
|
|
(
|
|
for issue in materialIssues do
|
|
(
|
|
appendIfUnique this._materialValidationReport_Arr issue
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Works in conjunction with fn_ValidateMatsAndTex, to open bitmap textures, check against their ideal size and returns false if size mismatch occurs
|
|
fn fn_TextureDimensionCheck texPath idealTexSize =
|
|
(
|
|
-- Open the bitmap
|
|
local texBitmap = openBitmap texPath
|
|
|
|
-- Compare texture w/h against ideal w/h
|
|
if (texBitmap.width > idealTexSize) or (texBitmap.height > idealTexSize) then
|
|
(
|
|
close texBitmap
|
|
return false
|
|
)
|
|
else
|
|
(
|
|
close texBitmap
|
|
return true
|
|
)
|
|
),
|
|
|
|
-- Get all mats associated with a passed material byiterating through the faces
|
|
fn fn_GetLinkedMeshMats passedMesh =
|
|
(
|
|
local linkedMatArr = #()
|
|
local matIndicesArr = #()
|
|
local materialIssues = #()
|
|
|
|
for face in passedMesh.faces do
|
|
(
|
|
-- If some faces have undefined materials
|
|
local facemat = polyOp.getFaceMatID passedMesh face.index
|
|
if facemat != undefined then
|
|
(
|
|
appendIfUnique matIndicesArr facemat
|
|
)
|
|
else
|
|
(
|
|
append materialIssues ("\nUndefined materials in " + passedMesh.name)
|
|
)
|
|
)
|
|
|
|
-- If it is a multimaterial
|
|
if (classOf passedMesh.material == Multimaterial) then
|
|
(
|
|
for matIndex in matIndicesArr do append linkedMatArr passedMesh.material[matIndex]
|
|
)
|
|
-- Else if it is a single mat
|
|
else append matIndicesArr passedMesh.material
|
|
|
|
-- Add any possile mat issues to the global report arrays
|
|
if materialIssues.count > 0 do
|
|
(
|
|
for issue in materialIssues do
|
|
(
|
|
appendIfUnique this._materialValidationReport_Arr issue
|
|
)
|
|
)
|
|
|
|
return linkedMatArr
|
|
),
|
|
|
|
-- Validate texture naming per-geo
|
|
fn fn_ValidateTextureNaming geo mat =
|
|
(
|
|
local texNamingIssues = #()
|
|
|
|
local diffMapPath = rsta_rageMat.getDiffuse mat
|
|
local normalMapPath = rsta_rageMat.getBump mat
|
|
local specMapPath = rsta_rageMat.getSpec mat
|
|
|
|
-- Get texture names
|
|
local diffMapName = ""
|
|
local normalMapName = ""
|
|
local specMapName = ""
|
|
|
|
if (diffMapPath != undefined) do diffMapName = getFileNameFile diffMapPath
|
|
if (normalMapPath != undefined) do normalMapName = getFileNameFile normalMapPath
|
|
if (specMapPath != undefined) do specMapName = getFileNameFile specMapPath
|
|
|
|
local mapNamesArr = #(diffMapName, normalMapName, specMapName)
|
|
|
|
-- COMPONENT NAME CHECK
|
|
local geo_componentName = this.fn_GetComponentName geo.name
|
|
for mapName in mapNamesArr do
|
|
(
|
|
if (mapName != "") do
|
|
(
|
|
local mapCompName = this.fn_GetComponentName mapName
|
|
--if mapCompName != geo_componentName do append texNamingIssues ("\nTexture component mismatch with geo: " + mapName + ", " + geo.name)
|
|
if (stricmp mapCompName geo_componentName != 0) do append texNamingIssues ("\nTexture component mismatch with geo: " + mapName + ", " + geo.name)
|
|
)
|
|
)
|
|
|
|
-- RACIAL TAG CHECK
|
|
-- Note: We only check diffuse map for racial tags
|
|
local geo_racialTag = this.fn_GetRacialTag geo.name isGeo:true
|
|
|
|
if (diffMapName != "") do
|
|
(
|
|
local tex_racialTag = this.fn_GetRacialTag diffMapName isTex:true
|
|
if geo_racialTag == "u" do
|
|
(
|
|
if tex_racialTag != "uni" do append texNamingIssues ("\nTexture racial tag mismatch with geo: " + diffMapName + ", " + geo.name)
|
|
)
|
|
if geo_racialTag == "r" do
|
|
(
|
|
if (findItem this._validRacialTags tex_racialTag == 0) do append texNamingIssues ("\nInvalid racial tag: " + diffMapName + ", " + geo.name)
|
|
)
|
|
)
|
|
|
|
-- SEQ NUM CHECK
|
|
local geo_seqNum_Padded = formattedPrint (this.fn_GetSequenceNum geo.name isGeo:true) format:"03d"
|
|
if geo_seqNum_Padded != undefined do
|
|
(
|
|
for mapName in mapNamesArr do
|
|
(
|
|
if (mapName != "") do
|
|
(
|
|
local tex_seqNum_Padded = formattedPrint (this.fn_GetSequenceNum mapName isTex:true) format:"03d"
|
|
if (tex_seqNum_Padded != geo_seqNum_Padded) do append texNamingIssues ("\nTexture sequence mismatch with geo: " + mapName + ", " + geo.name )
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add any possile issues to the global report arrays
|
|
if texNamingIssues.count > 0 do
|
|
(
|
|
for issue in texNamingIssues do
|
|
(
|
|
appendIfUnique this._textureValidationReport_Arr issue
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Prints out the validation report
|
|
fn fn_PrintValidationReport =
|
|
(
|
|
for issue in this._geoValidationReport_Arr do
|
|
(
|
|
this._validationReport += issue
|
|
)
|
|
for issue in this._materialValidationReport_Arr do
|
|
(
|
|
this._validationReport += issue
|
|
)
|
|
for issue in this._textureValidationReport_Arr do
|
|
(
|
|
this._validationReport += issue
|
|
)
|
|
|
|
if (this._geoValidationReport_Arr.count +
|
|
this._materialValidationReport_Arr.count +
|
|
this._textureValidationReport_Arr.count == 0) do this._validationReport = "ALL CLEAR!"
|
|
|
|
format "\n----------------------------\n"
|
|
format " VALIDATION REPORT"
|
|
format "\n----------------------------\n"
|
|
format "% \n" this._validationReport
|
|
format "\n----------------------------\n"
|
|
|
|
if this._validationReport != "ALL CLEAR!" then
|
|
(
|
|
this.fn_AddErrorsToULog this._validationReport
|
|
)
|
|
else
|
|
(
|
|
this.fn_AddMessageToULog this._validationReport
|
|
)
|
|
),
|
|
|
|
fn fn_AddErrorsToULog validationReport =
|
|
(
|
|
gRsUlog.LogError(validationReport)
|
|
gRsUlog.Validate()
|
|
),
|
|
|
|
fn fn_AddMessageToULog message =
|
|
(
|
|
gRsUlog.LogMessage(message)
|
|
gRsUlog.Validate()
|
|
gRsUlog.ShowDialog()
|
|
),
|
|
|
|
public
|
|
fn fn_BeginValidation =
|
|
(
|
|
-- Initialize
|
|
this._validationReport = ""
|
|
|
|
-- Set the model to validate
|
|
this._targetPed = (selection as array)[1]
|
|
if this._targetPed == undefined do
|
|
(
|
|
format "Please select a valid ped."
|
|
return false
|
|
)
|
|
|
|
-- Check for model scaling issues
|
|
this.fn_ValidateScale()
|
|
|
|
-- Check for model naming issues
|
|
this.fn_ValidateComponentName()
|
|
|
|
-- Check for sequencing issues in name
|
|
this.fn_ValidateComponentSequence()
|
|
|
|
-- texture size checks
|
|
this.fn_ValidateMatsAndTex()
|
|
|
|
-- Print out validation report
|
|
this.fn_PrintValidationReport()
|
|
)
|
|
)
|