-- Rockstar Material Utilities -- Rockstar North -- 14/3/2005 -- by Greg Smith -- by Luke Openshaw -- if you get add any functions to get texture maps -- make sure they come out lower case. lots of comparisons -- assume this. RsMakeSafeTextureName will return a lowercase -- name ----------------------------------------------------------------------------- -- Uses ----------------------------------------------------------------------------- --filein "pipeline/util/file.ms" -- loaded on startup by startup.ms --filein "pipeline/util/string.ms" -- loaded on startup by startup.ms --filein "rockstar/util/mapobj.ms" -- loaded on startup by startup.ms --filein "rockstar/export/settings.ms" -- loaded on startup by startup.ms filein "pipeline/util/drawablelod.ms" filein "rockstar/util/lod.ms" filein "pipeline/util/ExcludedTextures.ms" filein "rockstar/util/material_funcs.ms" ----------------------------------------------------------------------------- -- Globals ----------------------------------------------------------------------------- -- Set by RsGetShaderList: global RSshaderList = undefined global RsDiffuseTexMaxSize = 1024 global RsOtherTexMaxSize = 1024 global idxTexOptimised = (getAttrIndex "Gta Texture" "optimised") global gRsCallCountRsGetTexMapsFromObjNoStrip = 0 ----------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------- -------------------------------------------------------------- -- Returns a list of objs without packed textured objects -------------------------------------------------------------- fn RsGetInputObjectList inputObjList outputObjList = ( local idxPackTextures = getattrindex "Gta Object" "Pack Textures" local collectObjs = for obj in inputObjList where (getAttrClass obj != "Gta Object") or (getAttr obj idxPackTextures == False) collect obj join outputObjList collectObjs return outputObjList ) ---------------------------------------------------------------------------------------- -- Is this a Diffuse map-slot name? ---------------------------------------------------------------------------------------- fn RsIsDiffuseMap slotName = ( local retval = case of ( (not isKindOf slotName String):False ((matchPattern slotName pattern:"Diffuse*") and (not matchPattern slotName pattern:"*Palette*")):True (matchPattern slotName pattern:"Color Texture*"):True Default:False ) return retval ) ---------------------------------------------------------------------------------------- -- Is this a Palette map-slot name? ---------------------------------------------------------------------------------------- fn RsIsPaletteMap slotName = ( local retval = false if (isKindOf slotName String) do ( retval = (matchPattern slotName pattern:"*Palette*") ) retval ) ---------------------------------------------------------------------------------------- -- Is this a Specular map-slot name? ---------------------------------------------------------------------------------------- fn RsIsSpecMap slotName = ( local retval = false if (isKindOf slotName String) do ( retval = (matchPattern slotName pattern:"*Specular*") ) retval ) ---------------------------------------------------------------------------------------- -- Is this a Bump map-slot name? ---------------------------------------------------------------------------------------- fn RsIsBumpMap slotName = ( local retval = false if (isKindOf slotName String) do ( retval = (matchPattern slotName pattern:"*Bump*") or (matchPattern slotName pattern:"Normal Map*") ) retval ) ---------------------------------------------------------------------------------------- -- Is this a cable-shader? ---------------------------------------------------------------------------------------- fn RsIsCableTexture objMat = ( local retval = false if (isKindOf objMat Rage_Shader) do ( retval = (matchPattern (RstGetShaderName objMat) pattern:"*cable*") ) return retval ) ---------------------------------------------------------------------------------------- -- Is this a Distance Map map-slot? ---------------------------------------------------------------------------------------- fn RsIsDistanceMap slotName = ( slotName == "Distance Map" ) ---------------------------------------------------------------------------------------- -- Is this a Tint Palette map-slot? ---------------------------------------------------------------------------------------- fn RsIsTintPalette slotName = ( slotName == "Tint Palette" ) ---------------------------------------------------------------------------------------- -- Is this a Terrain Blend map-slot? ---------------------------------------------------------------------------------------- fn RsIsTerrainBlendMap slotName = ( local retval = false if (isKindOf slotName String) do ( retval = (matchPattern slotName pattern:"*Blend Texture *") ) return retval ) ---------------------------------------------------------------------------------------- -- Is this texturemap export-exempt? ---------------------------------------------------------------------------------------- fn RsIsExportExempt mapname = ( (mapname != undefined) and ( RsExcludedTextures.CheckName(mapname) ) ) ----------------------------------------------------------------------------- -- Global flags used to control texturemap-collection functions: ----------------------------------------------------------------------------- struct RsIncTexmaps ( incDefault = true, incDiffuse = true, incSpec = true, incNormal = true, incExempt = false, incPalette = true, -- Set global flags: fn setFlags inDefault diff: spec: normal: palette: = ( incDefault = inDefault if (diff != unsupplied) do (incDiffuse = diff) if (spec != unsupplied) do (incSpec = spec) if (normal != unsupplied) do (incNormal = normal) if (palette != unsupplied) do (incPalette = palette) return OK ), -- Does a given texturemap match the current include-flags? fn isIncluded texmapName texmapType = ( local incMap = incDefault if RsIsDiffuseMap texmaptype do (incMap = incDiffuse) if RsIsPaletteMap texmaptype do (incMap = incPalette) if RsIsTerrainBlendMap texmaptype do (incMap = incDiffuse) if RsIsSpecMap texmaptype do (incMap = incSpec) if RsIsBumpMap texmaptype do (incMap = incNormal) if RsIsExportExempt texmapname do (incMap = incExempt) return incMap ) ) gRsIncTexmaps = RsIncTexmaps() RsSetMapsFlags = gRsIncTexmaps.setFlags ---------------------------------------------------------------------------------------- -- Gets texturemap data from an object's lights: ---------------------------------------------------------------------------------------- fn RsCheckForLighttextures obj texmaplist maxsizelist:#() isbumplist:#() exemptionList:#() texmapobjlist:#() maptypelist:#() texturetemplatelist:#() matIdList:#() = ( if (not isValidNode obj) do return False for childobj in obj.children do ( local lightShadowMap = undefined case of ( (isproperty childobj "shadowprojectormap"): ( lightShadowMap = childobj.shadowprojectormap ) (isKindof childobj RageLight): ( local underlyingLight = childobj while isProperty underlyingLight "delegate" do underlyingLight = underlyingLight.delegate if isproperty underlyingLight "shadowprojectormap" then ( underlyingLight.shadowprojectormap = childobj.lightShadowMap lightShadowMap = childobj.delegate.shadowprojectormap ) ) ) if (lightShadowMap != undefined) and (lightShadowMap.filename != "") do ( if (appendIfUnique texmaplist (toLower lightShadowMap.filename)) do ( append maptypelist "LightMap" append texmapobjlist lightShadowMap append maxsizelist 1024 append isbumplist false append exemptionList false append texturetemplatelist "Diffuse" append matIdList -1 -- Default no-matid value if (not doesFileExist lightShadowMap.filename) do ( gRsUlog.LogWarning ("Texture "+ lightShadowMap.filename +" on light "+childobj.name+" couldn't be found!") context:childobj ) ) ) ) return texmaplist ) fn RsHasLightTxd obj = ( local txList = #() RsCheckForLighttextures obj txList local HasLightTx = (txList.count > 0) for child in obj.children while (not HasLightTx) do ( HasLightTx = RsHasLightTxd child ) return HasLightTx ) ----------------------------------------------------------------- -- Build a list of a material's submaterials of a particular class ----------------------------------------------------------------- fn RSgetMatClassSubMats mat getClass matList:#() = ( case (classOf mat) of ( MultiMaterial: ( for subMat in mat.materiallist do ( RSgetMatClassSubMats subMat getClass matList:matList ) ) getClass: ( appendIfUnique matList mat ) ) matList ) fn RsIsResizeExempt map maptypename objMat = ( local retval = (not getAttr map idxTexOptimised) or (RsIsTintPalette maptypename) or (RsIsDistanceMap maptypename) or (RsIsCableTexture objMat) return retval ) fn RsGetDistanceAlphaMapResultMap distAlphaMap = ( -- Make my name safe: distAlphaMap.name = substituteString distAlphaMap.name " " "_" distAlphaMap.name = substituteString distAlphaMap.name "#" "" -- Make sure result is not downscaled: setAttr distAlphaMap idxTexOptimised False local resultmap = undefined if (distAlphaMap.resultmap != undefined) do ( resultmap = distAlphaMap.resultmap ) -- Check whether it's a valid file path; if not, export it: if (resultmap == undefined) or (resultmap.filename == "") or ((getFileSize resultmap.filename) == 0) do -- Rebuild if necessary ( local diffuseMapPath = "C:\\" if (distAlphaMap.diffusemap != undefined) do ( diffuseMapPath = getFilenamePath distAlphaMap.diffuseMap ) if (distAlphaMap.Create False diffuseMapPath) do ( resultmap = distAlphaMap.resultmap ) format "Building new Distance map to %\n" resultmap.filename --doublecheck whether it worked if (resultmap == "") then ( local msg=stringstream "" format "Result for distanceAlphaMap % could not be created!" distAlphaMap.name to:msg messagebox msg ) ) return resultmap ) ---------------------------------------------------------------------------------------- -- Makes list of texturemaps used on object, the number of -- polys they use, and the faces they use ---------------------------------------------------------------------------------------- fn RsMatGetMapIdsUsedOnObjectWithCount obj mapList mat: polycount: faceidlists: maxMatId: = ( if (mat == unsupplied) do ( mat = obj.material ) if (isKindOf obj col_mesh) do (obj = getColMesh obj) local isMesh = (isKindOf obj Editable_Mesh) or (isKindOf obj TriMesh) local doPolyCount = (polycount != unsupplied) local doFaceIDlists = (faceidlists != unsupplied) local limitMatIds = (maxMatId != unsupplied) if ( ( isMesh or isKindOf obj Editable_Poly or isKindOf obj PolyMeshObject ) and (mat != undefined) and (hasProperty mat "materialList") ) then ( local objGetFaceMatId = if isMesh then getfacematid else polyop.getfacematid for i = 1 to (getnumfaces obj) do ( local matID = objGetFaceMatId obj i if matID != undefined do ( if limitMatIds do ( if (matID > maxMatId) do ( matID = (mod matID maxMatId) as integer if (matID == 0) do (matID = maxMatId) ) ) local idxFound = finditem mapList matID if idxFound == 0 then ( append mapList matID if doPolyCount do (append polycount 1) if doFaceIDlists do (append faceidlists #(i)) ) else ( if doPolyCount do (polycount[idxFound] += 1) if doFaceIDlists do (append faceidlists[idxFound] i) ) ) ) ) else ( append mapList -1 if doPolyCount do (append polycount 0) ) return mapList ) ---------------------------------------------------------------------------------------- -- Makes list of texturemaps used on object ---------------------------------------------------------------------------------------- fn RsMatGetMapIdsUsedOnObject obj mapList mat: maxMatId: = ( RsMatGetMapIdsUsedOnObjectWithCount obj mapList mat:mat maxMatId:maxMatId sort mapList return mapList ) ---------------------------------------------------------------------------------------- -- returns the nth texmap name in the rage shader ---------------------------------------------------------------------------------------- fn RsGetTexMapNameFromRsShader mat texmapidx = ( local retval = undefined local texmapidx = (texmapidx - 1) local numVars = RstGetVariableCount mat local texmapCount = -1 if (numVars != undefined) and (numVars >= 1) do ( for i = 1 to numVars where (RstGetVariableType mat i == "texmap") while (retval == undefined) do ( texmapCount += 1 if (texmapCount == texmapidx) do ( retval = (RstGetVariableName mat i) ) ) ) retval ) ---------------------------------------------------------------------------------------- -- Returns var-index for a given texmap-slot id: ---------------------------------------------------------------------------------------- fn RsGetTexMapIdForRstMtl mat texmapidx = ( texmapidx = texmapidx - 1 numVars = RstGetVariableCount mat texmapCount = -1 retval = undefined if numVars != undefined and numVars >= 1 do ( for i = 1 to numVars where (RstGetVariableType mat i == "texmap") and (retval == undefined) do ( texmapCount += 1 if texmapCount == texmapidx do (retval = i) ) ) retval ) ---------------------------------------------------------------------------------------- -- removes spaces from texture file names ---------------------------------------------------------------------------------------- fn RsMakeSafeTextureName namein = ( toLower (RsMakeSafeSlashes namein) ) ---------------------------------------------------------------------------------------- -- Removes paths from texpath-string -- (which can include multiple paths in one string) -- Returned string will -not- include '+' and '>' tokens ---------------------------------------------------------------------------------------- fn RsStripTexturePath texpath = ( local retval = "" if (texpath != undefined) and (texpath != "") do ( local PathTokens = filterstring texpath "+>" for SubPath in PathTokens do ( local TexName = GetFilenameFile SubPath if (TexName != undefined) do ( retval += TexName ) ) ) return retval ) ---------------------------------------------------------------------------------------- -- Returns a material's variable-index for a given texmap slot 'texmapIdx' ---------------------------------------------------------------------------------------- fn RsGetTexMapVariableIndex mat texmapIdx: byVarName: = ( local result = 0 if (texmapidx == unsupplied) and (byVarName == unsupplied) do return result local texmapCount = 0 local varCount = RstGetVariableCount mat local doByVarName = (byVarName != unsupplied) for i = 1 to varCount while (result == 0) do ( if (RstGetVariableType mat i == "texmap") do ( texmapCount += 1 if doByVarName then ( if ((RstGetVariableName mat i) == byVarName) do ( result = i ) ) else ( if (texmapCount == texmapIdx) do ( result = i ) ) ) ) return result ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsGetProceduralFaces obj mat facesout = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( for i = 1 to mat.materialIDList.count do ( if classof mat.materiallist[i] == RexBoundMtl then ( if RexGetProceduralName mat.materiallist[i] != "" then ( numFaces = getnumfaces obj for j = 1 to numFaces do ( if classof obj == Editable_Mesh then ( matID = getfacematid obj j ) else if classof obj == Editable_Poly or classof obj == PolyMeshObject then ( matID = polyop.getfacematid obj j ) if matID == mat.materialIDList[i] then ( append facesout j ) ) ) ) ) ) else if classof mat == RexBoundMtl then ( if RexGetProceduralName mat != "" then ( numFaces = getnumfaces obj for j = 1 to numFaces do ( append facesout j ) ) ) ) return false ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsGetDoesObjUseProcedurals obj mat = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( matidx = finditem mat.materialIDList matlist[i] if matidx != 0 then ( if RsGetDoesObjUseProcedurals obj mat.materiallist[matidx] == true then ( return true ) ) ) ) else if classof mat == RexBoundMtl then ( if RexGetProceduralName mat != "" then ( return true ) ) ) return false ) fn RsSpecularMapHack obj mat = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined do ( case classof mat of ( MultiMaterial: ( matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( if id == matlist[i] then ( matidx = finditem mat.materialIDList matlist[i] if matidx != 0 then ( RsSpecularMapHack obj mat.materiallist[matidx] ) ) ) ) Rage_Shader: ( numVars = RstGetVariableCount mat for i = 1 to numVars do ( nameVar = RstGetVariableName mat i if nameVar == "Specular Falloff" then ( specVar = RstGetVariable mat i if specVar > 199.0 and specVar < 201.0 then ( RstSetVariable mat i 201.5 ) ) ) ) ) ) ) -- Returns True if shaderName is on the shader-list: fn RsShaderExists shaderName = ( (findItem (::RsGetShaderList()) shaderName) != 0 ) -- Set all shaders in a material to use appropriate Default versions: fn RsSetMaterialToAllDefault mat isPed:false quiet:true = ( case classof mat of ( MultiMaterial: ( for childmat in mat.materiallist do (RsSetMaterialToAllDefault childmat isPed:isPed) ) Rage_Shader: ( local oldName = toLower (getFilenameFile (RstGetShaderName mat)) local defPattern = if isPed then "ped_default*" else "default*" if not matchPattern oldName pattern:defPattern do ( local newName = oldName if isPed and matchPattern oldName pattern:"ped_*" do ( newName = substring oldname 5 -1 ) -- This shader's Default version will just have the first name-token: local nameTokens = filterString newName "_" local newName = nameTokens[1] -- Special-case shader-mappings: case of ( (findItem #("decal", "alpha") newName != 0): ( newName = "cutout" ) ) newName = "default_" + newname if isPed do ( newName = "ped_" + newName ) -- If this new defaulty-name isn't on the shader-list, then use the default defaulty-name: if not RsShaderExists newName do ( newName = if isPed then "ped_default" else "default" ) if (oldName != newName) do ( local logMsg = stringStream "" format "Changing shader to Default version: % to %\n" oldName newName to:logMsg gRsUlog.LogMessage (logMsg as string) context:"RsSetMaterialToAllDefault" quiet:quiet RstSetShaderName mat newName ) ) ) Array: ( for childmat in mat do( RsSetMaterialToAllDefault childmat isPed:isPed quiet:quiet ) ) ) ) fn RsSetMaterialTexturesToLod mat SLOD:false = ( -- CHANGE TEXTUREMAPS TO LOD VERSIONS: (if found) -- Set texturemaps to use LOD/SLOD versions if available: local mainTexLodDir = RsProjectGetArtDir() + "/textures/lod/" local findSuffixes = if SLOD then #("_slod.*", "_slod1.*") else #("_lod.*") local matchSuffixes = for suffix in findSuffixes collect ("*" + suffix) local numTexMap = getNumSubTexmaps mat for n = 1 to numTexMap do ( local subTexMap = getSubTexmap mat n local newTexfile if (subTexMap != undefined) and (subTexMap.filename != "") do ( local texFilename = subTexMap.filename -- Skip files that already have a matching suffix: local doFile = true for suffixPattern in matchSuffixes while doFile do ( if matchPattern texFilename pattern:suffixPattern do ( doFile = false ) ) if doFile do ( local filenameName = toLower (getFilenameFile texFilename) local lodSuffixStart = case of ( (not SLOD and (matchPattern filenameName pattern:"*slod")):(findString filenameName "slod") (SLOD and (matchPattern filenameName pattern:"*lod")):(findString filenameName "lod") default:0 ) local baseFilename = filenameName -- Strip _/s/lod suffix: if (lodSuffixStart != 0) do ( lodSuffixStart -= 1 if filenameName[lodSuffixStart] == "_" do ( lodSuffixStart -= 1 ) baseFilename = subString filenameName 1 lodSuffixStart ) -- Look for matching _lod texture in same folder, lod subfolder, or main lod-texture folder: local fileDir = getFilenamePath texFilename -- Move up from Lod subdirectory, if that's what this is: if matchPattern (pathConfig.stripPathToLeaf fileDir) pattern:"lod*" do ( fileDir = (pathConfig.removePathLeaf fileDir) + "/" ) for findSuffix in findSuffixes while (newTexfile == undefined) do ( local findName = baseFilename + findSuffix local lodFile = #() for checkDir in #(fileDir, fileDir + "lods/", fileDir + "lod/", mainTexLodDir) while (lodFile.count == 0) do ( lodFile = getFiles (checkDir + findName) ) if (lodFile.count != 0) then ( newTexfile = lodFile[1] ) ) ) if (newTexfile != undefined) then ( --format "Changing texture to %LOD version: % to %\n" (if SLOD then "S" else "") texFilename newTexfile subTexMap.filename = newTexfile ) else --flag it up as a missing lod texture ( --format "Missing LOD texture\n" --messageBox ("There is a missing LOD texture for:\n" + (getFilenameFile texFilename)) title:"Missing LOD Texture" gRsULog.LogWarning "Missing lod texture paths\n" files:texFilename ) ) ) ) ---------------------------------------------------------------------------------------- -- Gets list of texmaps used by a material -- 'typeList' and 'matIdList' can be used to return matching lists of texmap-types and matIds ---------------------------------------------------------------------------------------- fn RsGetTexMapListForMat mat texmaplist texmaptypelist:#() matIdList:#() matId:1 = ( case of ( (mat == undefined):() (isKindOf mat MultiMaterial): ( for i = 1 to mat.materiallist.count do ( RsGetTexMapListForMat mat.materiallist[i] texmaplist texmaptypelist:texmaptypelist matIdList:matIdList matId:i ) ) Default: ( isAlphaShader = false numTexMaps = getNumSubTexmaps mat if (RstGetIsAlphaShader mat) do ( isAlphaShader = true numTexMaps = numTexMaps / 2 numTexMaps = numTexMaps + 1 ) numValidTexMaps = 0 for i = 1 to numTexMaps do ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if classOf subTexMap == CompositeTexturemap then ( for t=1 to getNumSubTexmaps subTexMap by 2 do ( local thisSubMap = getSubTexmap subTexMap t if thisSubMap.filename != "" then numValidTexMaps = numValidTexMaps + 1 ) ) if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") do ( numValidTexMaps += 1 ) ) for i = 1 to numTexMaps do ( local subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap CompositeTexturemap) do ( for t=1 to getNumSubTexmaps subTexMap by 2 do ( local thisSubMap = getSubTexmap subTexMap t if (thisSubMap.filename != "") do ( if (isKindOf mat Rage_Shader) then ( texmapType = RsGetTexMapNameFromRsShader mat i append texmaptypelist texmapType ) else ( append texmaptypelist undefined ) append texmaplist thisSubMap append matIdList matId ) ) ) if (isKindOf subTexMap Bitmaptexture) do ( if (subTexMap.filename != "") do ( if (isKindOf mat Rage_Shader) then ( texmapType = RsGetTexMapNameFromRsShader mat i append texmaptypelist texmapType ) else ( append texmaptypelist undefined ) append texmaplist subTexMap append matIdList matId ) ) ) ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the main texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetTexMapList obj mat texmaplist shaderlist matidlist slotlist withIsScaleUv:true shaderid:1 matid:1 = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( matlist = #() RsMatGetMapIdsUsedOnObjectWithCount obj matlist for i = 1 to matlist.count do ( matidx = finditem mat.materialIDList matlist[i] if matidx != 0 do ( RsGetTexMapList obj mat.materiallist[matidx] texmaplist shaderlist matidlist slotlist shaderid:i matid:matidx ) ) ) else if classof mat == XRef_Material then ( RsGetTexMapList obj (mat.getsrcitem()) texmaplist ) else ( isAlphaShader = false numTexMaps = getNumSubTexmaps mat if RstGetIsAlphaShader mat then ( isAlphaShader = true numTexMaps = numTexMaps / 2 numTexMaps = numTexMaps + 1 ) local slotIdx = 1 for i = 1 to numTexMaps do ( local subTexMap = getSubTexmap mat i local isAlpha = false if (isKindOf mat Standardmaterial) and (i == 7) then ( isAlpha = true ) else ( if isAlphaShader and (i == numTexMaps) do ( isAlpha = true ) ) if (isKindOf subTexMap DistanceAlphaMap) do ( --print "validation check 2" subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) do ( if (subTexMap.filename != "") do ( append texmaplist subTexMap append shaderlist shaderid append matidlist matid if isAlpha then ( append slotlist (-1) ) else ( append slotlist slotIdx ) ) if (not isAlpha) do ( slotIdx += 1 ) ) ) ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the main texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetMainTexMapsFromMaterial obj mat texmaplist firstpass:true = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( matidx = finditem mat.materialIDList matlist[i] if matidx != 0 then ( RsGetMainTexMapsFromMaterial obj mat.materiallist[matidx] texmaplist firstpass:false ) ) ) else if classof mat == XRef_Material then ( RsGetMainTexMapsFromMaterial obj (mat.getsrcitem()) texmaplist ) else if classof mat == Standardmaterial then ( diffuseName = "" subTexMap = getSubTexmap mat 2 append texmaplist subTexMap ) else if classof mat == Rage_Shader then ( numTexMap = getNumSubTexmaps mat if numTexMap > 0 then ( subTexMap = getSubTexmap mat 1 append texmaplist subTexMap ) ) else if classof mat == DirectX_9_Shader then ( numTexMap = getNumSubTexmaps mat if numTexMap > 0 then ( subTexMap = getSubTexmap mat 1 append texmaplist subTexMap ) ) if firstpass then ( for childobj in obj.children do ( RsGetMainTexMapsFromMaterial childobj childobj.material texmaplist ) ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the main texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetMainTexMapsFromMaterialByID obj mat id texmaplist = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( if id == matlist[i] then ( matidx = finditem mat.materialIDList matlist[i] if matidx != 0 then ( RsGetMainTexMapsFromMaterial obj mat.materiallist[matidx] texmaplist ) ) ) ) else if classof mat == XRef_Material then ( RsGetMainTexMapsFromMaterial obj (mat.getsrcitem()) texmaplist ) else if classof mat == Standardmaterial then ( diffuseName = "" subTexMap = getSubTexmap mat 2 append texmaplist subTexMap ) else if classof mat == Rage_Shader then ( numTexMap = getNumSubTexmaps mat if numTexMap > 1 then ( subTexMap = getSubTexmap mat 1 append texmaplist subTexMap ) ) ) ) fn RsGetEmptyTexMaps obj mat slotlist objnamelist texmapnamelist currentslot:-1 = ( if obj != undefined and (not isRefObj obj) and (not isInternalRef obj) and mat != undefined then ( if classof mat == MultiMaterial then ( local matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( local matidx = finditem mat.materialIDList matlist[i] if (matidx != 0) do ( RsGetEmptyTexMaps obj mat.materiallist[matidx] slotlist objnamelist texmapnamelist currentslot:matlist[i] ) ) ) else if classof mat == Rage_Shader then ( varCount = RstGetVariableCount mat texmapCount = 0 if (varCount != undefined) and (varCount >= 1) do ( for i = 1 to varCount do ( if retval == undefined and RstGetVariableType mat i == "texmap" then ( texmapCount = texmapCount + 1 if ( getNumSubTexmaps mat < texmapCount ) then continue varName = RstGetVariableName mat i varSubMap = getSubTexmap mat texmapCount if (isKindOf varSubMap DistanceAlphaMap) do ( varSubMap = varSubMap.resultmap ) if (not isKindOf varSubMap CompositeTexturemap) do ( local varFilename = "" if (isKindOf varSubMap Bitmaptexture) and (varSubMap.filename != undefined) and (varSubMap.filename != "") do ( varFilename = RsMakeSafeTextureName(RsStripTexturePath(varSubMap.filename)) ) if varFilename == "" and varName != "Diffuse Texture" do ( append objnamelist obj.name append slotlist currentslot append texmapnamelist varName ) ) ) ) ) ) ) ) ---------------------------------------------------------------------------------------- -- Returns bitArray of matIds used on an object's mesh, -- with no special processing (also works on TriMeshes) ---------------------------------------------------------------------------------------- fn RsGetMatIdsUsedByObj obj = ( local objGetFaceMatID = RsGetFaceMatIDFunc obj local retVal = #{} for faceNum = 1 to (getNumFaces obj) do ( local faceMatId = objGetFaceMatID obj faceNum if (faceMatId != undefined) do ( retVal[faceMatId] = true ) ) return retVal ) ---------------------------------------------------------------------------------------- -- Returns a list of texture-paths used by a material. -- 'matIds' can be used to limit the multimaterial ids used. ---------------------------------------------------------------------------------------- fn RsGetTexPathsFromMat mat matIds:#{} texList:#() = ( case classOf mat of ( MultiMaterial: ( local allMatIds = (matIds.numberSet == 0) local matIdList = #() for matIdx = 1 to mat.materialIDList.count do ( local matId = mat.materialIDList[matIdx] if allMatIds or matIds[matId] do ( RsGetTexPathsFromMat mat.materialList[matIdx] matIds:matIds texList:texList ) ) ) XRef_Material: ( RsGetTexPathsFromMat mat.getsrcitem() matIds:matIds texList:texList ) CompositeTexturemap: -- That's a Texturemap, not material ( local subTexMap = mat local numMaps = getNumSubTexMaps subTexMap for j = 1 to numMaps do ( local subSubTexMap = getSubTexmap mat j RsGetTexPathsFromMat subSubTexMap matIds:matIds texList:texList ) ) UndefinedClass:() default: ( if (isKindOf mat textureMap) then ( local subTexMap = mat if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") then ( local texmapname = (RsMakeSafeTextureName subTexMap.filename) appendIfUnique texList texmapname ) ) else ( local numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( local subTexMap = getSubTexmap mat i RsGetTexPathsFromMat subTexMap matIds:matIds texList:texList ) ) ) ) return texList ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromMaterialWithMap obj mat texmaplist bitmaplist maptypelist:#() matIdList:#() matId:1 incID:-1 = ( RsCheckForLighttextures obj texmaplist texmapobjlist:bitmaplist maptypelist:maptypelist matIdList:matIdList if (obj != undefined) and (not isRefObj obj) and (not isInternalRef obj) and (mat != undefined) do ( if classof mat == MultiMaterial then ( local objMatIds = #() RsMatGetMapIdsUsedOnObject obj objMatIds maxMatId:mat.numSubs for i = 1 to objMatIds.count do ( local matId = objMatIds[i] if (incID == -1) or (incID == matId) then ( local matidx = finditem mat.materialIDList matId if (matidx != 0) do ( RsGetTexMapsFromMaterialWithMap obj mat.materiallist[matidx] texmaplist bitmaplist maptypelist:maptypelist matIdList:matIdList matId:matId incID:incID ) ) ) ) else if classof mat == XRef_Material then ( RsGetTexMapsFromMaterialWithMap obj (mat.getsrcitem()) texmaplist bitmaplist maptypelist:maptypelist matIdList:matIdList matId:matId incID:incID ) else if classof mat == Standardmaterial then ( diffuseName = "" subTexMap = getSubTexmap mat 2 subTexMapMain = getSubTexmap mat 2 if (isKindOf subTexMap DistanceAlphaMap) do ( --print "validation check 4" subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) do ( if (subTexMap.filename != "") do ( texmapname = toLower(subTexMap.filename) diffuseName = texmapname ) subTexMap = getSubTexmap mat 7 if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") do ( texmapname = toLower(subTexMap.filename) diffuseName = diffuseName + "+" + texmapname ) ) if diffuseName != "" do ( diffuseName = RsMakeSafeTextureName(RsStripTexturePath diffuseName) if finditem texmaplist diffuseName == 0 do ( append texmaplist diffuseName append bitmaplist subTexMapMain append maptypelist "Diffuse" append matIdList matId ) ) numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( if (i != 2) and (i != 7) do ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") do ( texmapname = RsMakeSafeTextureName(RsStripTexturePath (subTexMap.filename)) if (finditem texmaplist texmapname == 0) do ( local maptype = case i of ( 4:"Specular" 9:"Bump" Default:"Default" ) append texmaplist texmapname append bitmaplist subTexMap append maptypelist maptype append matIdList matId ) ) ) ) ) else if classof mat == Rage_Shader then ( numTexMap = getNumSubTexmaps mat if RstGetIsAlphaShader mat then ( numTexMap = numTexMap / 2 ) for i = 1 to numTexMap do ( texmapname = "" subTexMap = getSubTexmap mat i if classof subTexMap == DistanceAlphaMap then ( --print "validation check 6" subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if classof subTexMap == Bitmaptexture then ( if subTexMap.filename != "" then ( texmapname = RsMakeSafeTextureName(RsStripTexturePath(subTexMap.filename)) ) if RstGetIsAlphaShader mat then ( local alphaTexMap = getSubTexmap mat (i + numTexMap) if classof alphaTexMap == Bitmaptexture then ( if alphaTexMap.filename != "" then ( texmapname += "+" + RsMakeSafeTextureName(RsStripTexturePath (alphaTexMap.filename)) ) ) ) ) else if classof subTexMap == CompositeTexturemap then ( numMaps = getnumsubtexmaps subTexMap for j = 1 to numMaps do ( subsubTexMap = getSubTexmap subTexMap j if classof subsubTexMap == Bitmaptexture then ( if subsubTexMap.filename != "" then ( if j != 1 then ( texmapname += ">" ) texmapname += RsMakeSafeTextureName(RsStripTexturePath(subsubTexMap.filename)) ) ) ) ) if texmapname != "" then ( if (finditem texmaplist texmapname == 0) do ( local texmaptype = RsGetTexMapNameFromRsShader mat i local addMap = gRsIncTexmaps.isIncluded texmapName texmapType if addMap do ( append texmaplist texmapname append bitmaplist subTexMap append maptypelist texmaptype append matIdList matId ) ) ) ) ) else if classof mat == DirectX_9_Shader then ( numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( texmapname = "" subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) then ( if (subTexMap.filename != "") do ( texmapname = RsMakeSafeTextureName(RsStripTexturePath(subTexMap.filename)) ) if (RstGetIsAlphaShader mat) do ( local alphaTexMap = getSubTexmap mat (i + numTexMap) if (isKindOf alphaTexMap Bitmaptexture) and (alphaTexMap.filename != "") do ( texmapname += "+" + RsMakeSafeTextureName(RsStripTexturePath (alphaTexMap.filename)) ) ) ) if (texmapname != "") do ( if (finditem texmaplist texmapname == 0) do ( append texmaplist texmapname append bitmaplist subTexMap ) ) ) ) else ( numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") do ( texmapname = RsMakeSafeTextureName(RsStripTexturePath (subTexMap.filename)) if (finditem texmaplist texmapname == 0) do ( append texmaplist texmapname append bitmaplist subTexMap append maptypelist "Default" append matIdList matId ) ) ) ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by a material ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromMaterial obj mat texmaplist maxsizelist isbumplist = ( RsCheckForLighttextures obj texmaplist maxsizelist:maxsizelist isbumplist:isbumplist if (obj != undefined) and (not isRefObj obj) and (not isInternalRef obj) and (mat != undefined) do ( if classof mat == MultiMaterial then ( --print "multi" matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( local matidx = finditem mat.materialIDList matlist[i] if (matidx != 0) do ( RsGetTexMapsFromMaterial obj mat.materiallist[matidx] texmaplist maxsizelist isbumplist ) ) ) else if classof mat == XRef_Material then ( RsGetTexMapsFromMaterial obj (mat.getsrcitem()) texmaplist maxsizelist isbumplist ) else if classof mat == Standardmaterial then ( --print "standard" diffuseName = "" doAlpha = false subTexMap = getSubTexmap mat 1 if subTexMap == undefined then ( doAlpha = true subTexMap = getSubTexmap mat 2 ) if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) do ( if ( ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) ) do ( texmapname = toLower(subTexMap.filename) diffuseName = texmapname ) if doAlpha do ( subTexMap = getSubTexmap mat 7 if (isKindOf subTexMap Bitmaptexture) do ( if ( ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) ) do ( texmapname = toLower(subTexMap.filename) diffuseName = diffuseName + "+" + texmapname ) ) ) ) if (diffuseName != "") do ( diffuseName = RsMakeSafeTextureName(RsStripTexturePath diffuseName) if finditem texmaplist diffuseName == 0 then ( --print diffuseName --print RsDiffuseTexMaxSize append texmaplist diffuseName append maxsizelist RsDiffuseTexMaxSize append isbumplist false ) ) numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( if (i != 2) and (i != 7) then ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) and ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) do ( texmapname = RsMakeSafeTextureName(RsStripTexturePath (subTexMap.filename)) if (finditem texmaplist texmapname == 0) then ( append texmaplist texmapname append maxsizelist RsOtherTexMaxSize if (i == 9) then ( append isbumplist true ) else ( append isbumplist false ) ) ) ) ) ) else if classof mat == Rage_Shader then ( --print "rage" numTexMap = getNumSubTexmaps mat if RstGetIsAlphaShader mat then ( numTexMap = numTexMap / 2 ) for i = 1 to numTexMap do ( texmapname = "" subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) then ( if ( ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) ) then ( texmapname = RsMakeSafeTextureName(RsStripTexturePath(subTexMap.filename)) ) if RstGetIsAlphaShader mat then ( local alphaTexMap = getSubTexmap mat (i + numTexMap) if classof alphaTexMap == Bitmaptexture then ( if ( undefined != alphaTexMap.filename and "" != alphaTexMap.filename ) then ( texmapname += "+" + RsMakeSafeTextureName(RsStripTexturePath (alphaTexMap.filename)) ) ) ) ) else if (isKindOf subTexMap CompositeTexturemap) then ( numMaps = getnumsubtexmaps subTexMap for j = 1 to numMaps do ( subsubTexMap = getSubTexmap subTexMap j if (isKindOf subsubTexMap Bitmaptexture) and ( undefined != subsubTexMap.filename ) and ( "" != subsubTexMap.filename ) do ( if (j != 1) do ( texmapname += ">" ) texmapname += RsMakeSafeTextureName(RsStripTexturePath(subsubTexMap.filename)) ) ) ) if ( ( undefined != texmapname ) and ( "" != texmapname ) ) do ( if (finditem texmaplist texmapname == 0) do ( local texmaptype = RsGetTexMapNameFromRsShader mat i local addMap = gRsIncTexmaps.isIncluded texmapname texmapType if addMap do ( --print texmapname append texmaplist texmapname if RsIsBumpMap texmaptype then ( append isbumplist true ) else ( append isbumplist false ) if RsIsDiffuseMap texmaptype then ( --print RsDiffuseTexMaxSize append maxsizelist RsDiffuseTexMaxSize ) else ( --print RsOtherTexMaxSize append maxsizelist RsOtherTexMaxSize ) ) ) ) ) ) else ( numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (classof subTexMap == Bitmaptexture) and (subTexMap.filename != "") do ( texmapname = RsMakeSafeTextureName(RsStripTexturePath (subTexMap.filename)) if (finditem texmaplist texmapname == 0) do ( append texmaplist texmapname append isbumplist false texmapname = RsGetTexMapNameFromRsShader mat i if RsIsDiffuseMap texmapname then ( append maxsizelist RsDiffuseTexMaxSize ) else ( append maxsizelist RsOtherTexMaxSize ) ) ) ) ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by a material ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromMaterialNoStrip obj mat texmaplist maxsizelist isbumplist exemptionList:#() texmapobjlist:#() maptypelist:#() texturetemplatelist:#() materialpresetlist:#() = ( if (isKindOf obj Col_Mesh) do return False RsCheckForLighttextures obj texmaplist maxsizelist:maxsizelist isbumplist:isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist if (not isRefObj obj) and (not isInternalRef obj) and (mat != undefined) do ( case (classof mat) of ( MultiMaterial: ( matlist = #() RsMatGetMapIdsUsedOnObject obj matlist for i = 1 to matlist.count do ( local matidx = finditem mat.materialIDList matlist[i] if matidx != 0 do ( RsGetTexMapsFromMaterialNoStrip obj mat.materiallist[matidx] texmaplist maxsizelist isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist materialpresetlist:materialpresetlist ) ) ) XRef_Material: ( RsGetTexMapsFromMaterialNoStrip obj (mat.getsrcitem()) texmaplist maxsizelist isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist materialpresetlist:materialpresetlist ) Standardmaterial: ( local diffuseName = "" local doAlpha = false local subTexMap = getSubTexmap mat 1 if (subTexMap == undefined) do ( doAlpha = true subTexMap = getSubTexmap mat 2 ) if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) do ( if ( ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) ) do ( texmapname = toLower(subTexMap.filename) diffuseName = texmapname ) if doAlpha do ( local alphaTexMap = getSubTexmap mat 7 if (isKindOf alphaTexMap Bitmaptexture) do ( if ( ( undefined != alphaTexMap.filename ) and ( "" != alphaTexMap.filename ) ) do ( texmapname = toLower(alphaTexMap.filename) diffuseName = diffuseName + "+" + texmapname ) ) ) ) if (diffuseName != "") do ( diffuseName = RsMakeSafeTextureName(diffuseName) if (findItem texmaplist diffuseName == 0) do ( -- format "Texture map: %\n" diffuseName --print RsDiffuseTexMaxSize append texmaplist diffuseName append maptypelist "Diffuse" append texmapobjlist subTexMap append maxsizelist RsDiffuseTexMaxSize append isbumplist false append exemptionList false append texturetemplatelist "Default" ) ) local numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( if (i != 2) and (i != 7) do ( subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) do ( if (undefined != subTexMap.filename) and ("" != subTexMap.filename) do ( texmapname = RsMakeSafeTextureName(subTexMap.filename) if finditem texmaplist texmapname == 0 then ( append texmaplist texmapname append texmapobjlist subTexMap append maxsizelist RsOtherTexMaxSize append exemptionList false if i == 9 then ( append maptypelist "Bump Texture" append isbumplist true append texturetemplatelist "NormalMap" ) else ( append maptypelist "Default" append isbumplist false append texturetemplatelist "Default" ) ) ) ) ) ) ) Rage_Shader: ( numTexMap = getNumSubTexmaps mat if RstGetIsAlphaShader mat do ( numTexMap /=2 ) local materialPresetPath = RstGetMaterialPresetPath mat if (materialPresetPath != undefined) do ( materialPresetPath = (toLower materialPresetPath) ) for i = 1 to numTexMap do ( texmapname = "" subTexMap = getSubTexmap mat i local alphaTexMap = undefined if RstGetIsAlphaShader mat then alphaTexMap = getSubTexmap mat (i + numTexMap) if (isKindOf subTexMap DistanceAlphaMap) do ( if (RstGetIsAlphaShader mat) and (undefined!=alphaTexMap) do ( local requestshader = yesNoCancelBox "Distance map can NOT be used in shaders with separate alpha textures, since it creates its own one. Use another shader or leave alpha slot empty.\nYes: Auto fix by deleting alpha texture of shader.\nNo: Put shader in slot 24 and fix yourself." if #yes==requestshader then ( setSubTexmap mat (i + numTexMap) undefined alphaTexMap = undefined ) else if #no==requestshader then meditmaterials[24] = mat ) subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) then ( if ( ( undefined != subTexMap.filename ) and ( "" != subTexMap.filename ) ) then ( texmapname = RsMakeSafeTextureName(subTexMap.filename) ) if RstGetIsAlphaShader mat then ( if classof alphaTexMap == Bitmaptexture then ( if ( ( undefined != alphaTexMap.filename ) and ( "" != alphaTexMap.filename ) ) then ( texmapname += ("+" + RsMakeSafeTextureName(alphaTexMap.filename)) ) ) ) ) else if (isKindOf subTexMap CompositeTexturemap) do ( numMaps = getnumsubtexmaps subTexMap for j = 1 to numMaps do ( subsubTexMap = getSubTexmap subTexMap j if classof subsubTexMap == Bitmaptexture then ( if ( ( undefined != subsubTexMap.filename ) and ( "" != subsubTexMap.filename ) ) then ( if j != 1 then ( texmapname += ">" ) texmapname += RsMakeSafeTextureName(subsubTexMap.filename) ) ) ) ) if texmapname != "" then ( idxTexMapName = finditem texmaplist texmapname textureTemplateOrder = #( "Diffuse", "Normal", "Specular" ) alreadyInList = false if idxTexMapName != 0 then alreadyInList = true texmaptype = RsGetTexMapNameFromRsShader mat i idxTex = RsGetTexMapIdForRstMtl mat i -- This is nasty but is the only way to deal with materials that have had their -- .fxc files deleted. if idxTex == undefined then ( texturetemplate = "Default" ) else ( texturetemplate = RstGetTextureTemplate mat idxTex ) if texturetemplate == "" then texturetemplate = RstGetTextureTemplateRelative mat idxTex local addMap = gRsIncTexmaps.isIncluded texmapName texmapType if addMap then ( if ( not alreadyInList ) then ( append texmaplist texmapname append maptypelist texmaptype append texmapobjlist subtexmap if (materialPresetPath != undefined) do ( append materialpresetlist materialPresetPath ) --print ("ADDING : " + texturetemplate + " for :" + texmapname) append texturetemplatelist texturetemplate if RsIsBumpMap texmaptype then ( append isbumplist true ) else ( append isbumplist false ) if RsIsResizeExempt subTexMap texmaptype mat then ( append exemptionList true ) else ( append exemptionList false ) if RsIsDiffuseMap texmaptype then ( append maxsizelist RsDiffuseTexMaxSize ) else ( append maxsizelist RsOtherTexMaxSize ) ) -- Already in list so check if the priority of this type is higher -- than the value already in the list, and replace if so else ( -- Template already in list idxCurrentTemplate = findItem textureTemplateOrder texturetemplatelist[idxTexMapName] -- Template being checked idxThisTemplate = findItem textureTemplateOrder texturetemplate --format "Current: %\tThis: %\n" texturetemplatelist[idxTexMapName] texturetemplate --format "idxCurrent: %\t idxThis: %\n" idxCurrentTemplate idxThisTemplate -- If this template isn't found in the list then it'll be 0, but is really -- lowest priority if ( idxThisTemplate != 0 and (idxThisTemplate < idxCurrentTemplate) ) then ( texmaplist[idxTexMapName] = texmapname maptypelist[idxTexMapName] = texmaptype texmapobjlist[idxTexMapName] = subtexmap --print ("CHANGING to : " + texturetemplate + " for :" + texmapname) texturetemplatelist[idxTexMapName] = texturetemplate if RsIsDiffuseMap texmaptype then ( maxsizelist[idxTexMapName] = RsDiffuseTexMaxSize ) else ( maxsizelist[idxTexMapName] = RsOtherTexMaxSize ) ) ) ) ) ) ) Default: ( local numTexMap = getNumSubTexmaps mat for i = 1 to numTexMap do ( local subTexMap = getSubTexmap mat i if (isKindOf subTexMap DistanceAlphaMap) do ( --print "validation check 0" subTexMap = RsGetDistanceAlphaMapResultMap subTexMap ) if (isKindOf subTexMap Bitmaptexture) and (subTexMap.filename != "") do ( texmapname = RsMakeSafeTextureName(subTexMap.filename) if (finditem texmaplist texmapname == 0) do ( --print texmapname append texmaplist texmapname append texmapobjlist subtexmap append isbumplist false append exemptionList false if (materialPresetPath != undefined) do ( append materialpresetlist materialPresetPath ) idxTex = RsGetTexMapIdForRstMtl mat i texmaptype = RsGetTexMapNameFromRsShader mat i texturetemplate = RstGetTextureTemplate mat idxTex if texturetemplate == "" then texturetemplate = RstGetTextureTemplateRelative mat idxTex append maptypelist texmaptype append texturetemplatelist texturetemplate if RsIsDiffuseMap texmaptype then ( --print RsDiffuseTexMaxSize append maxsizelist RsDiffuseTexMaxSize ) else ( --print RsOtherTexMaxSize append maxsizelist RsOtherTexMaxSize ) ) ) ) ) ) ) return True ) ---------------------------------------------------------------------------------------- -- takes a texmaplist and strips the paths in it ---------------------------------------------------------------------------------------- fn RsStripPaths texNameList = ( for i = 1 to texNameList.count do ( texNameList[i] = RsStripTexturePath texNameList[i] ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromObjWithMapsRec obj texmaplist bitmaplist incID:-1 = ( if (obj == undefined) do return #() RsGetTexMapsFromMaterialWithMap obj obj.material texmaplist bitmaplist incID:incID for childobj in obj.children do ( RsGetTexMapsFromObjWithMapsRec childobj texmaplist bitmaplist incID:incID ) if ( RsLodDrawable_HasLowerDetailModel obj ) then ( local ldobj = ( RsLodDrawable_GetLowerDetailModel obj ) -- format "LD Model: RsGetTexMapsFromObjWithMapsRec %\n" ldobj RsGetTexMapsFromObjWithMapsRec ldobj texmaplist bitmaplist incID:incID ) return texmaplist ) ---------------------------------------------------------------------------------------- -- Fills texmaplist with the texture maps used by an object -- If 'id' is used, only texmaps with that matId are returned ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromObjWithMaps obj texmaplist bitmaplist id:-1 = ( RsGetTexMapsFromObjWithMapsRec obj texmaplist bitmaplist incID:id RsStripPaths texmaplist return texmaplist ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromObjRec obj texmaplist maxsizelist isbumplist = ( if obj != undefined then ( RsGetTexMapsFromMaterial obj obj.material texmaplist maxsizelist isbumplist for childobj in obj.children do ( RsGetTexMapsFromObjRec childobj texmaplist maxsizelist isbumplist ) if ( RsLodDrawable_HasLowerDetailModel obj ) then ( local ldobj = ( RsLodDrawable_GetLowerDetailModel obj ) --format "LD Model: RsGetTexMapsFromObjRec %\n" ldobj RsGetTexMapsFromObjRec ldobj texmaplist maxsizelist isbumplist ) ) ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromObj obj texmaplist maxsizelist isbumplist = ( RsGetTexMapsFromObjRec obj texmaplist maxsizelist isbumplist RsStripPaths texmaplist ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by an object ---------------------------------------------------------------------------------------- fn RsGetTexMapsFromObjNoStrip obj texmaplist maxsizelist isbumplist exemptionList:#() texmapobjlist:#() maptypelist:#() texturetemplatelist:#() materialpresetlist:#() = ( gRsCallCountRsGetTexMapsFromObjNoStrip += 1 RsGetTexMapsFromMaterialNoStrip obj obj.material texmaplist maxsizelist isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist materialpresetlist:materialpresetlist for childobj in obj.children do ( RsGetTexMapsFromObjNoStrip childobj texmaplist maxsizelist isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist materialpresetlist:materialpresetlist ) if ( RsLodDrawable_HasLowerDetailModel obj ) then ( local ldobj = ( RsLodDrawable_GetLowerDetailModel obj ) --format "LD Model: RsGetTexMapsFromObjNoStrip %\n" ldobj RsGetTexMapsFromObjNoStrip ldobj texmaplist maxsizelist isbumplist exemptionList:exemptionList texmapobjlist:texmapobjlist maptypelist:maptypelist texturetemplatelist:texturetemplatelist materialpresetlist:materialpresetlist ) return texmaplist ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsMergeTextureUsage texmaplist texmaptypelist texturetemplatelist maxsizelist isbumplist usagelist exemptionlist objtexmaplist objtexmaptypelist objmaxsizelist objisbumplist infiniteusage objexemptionlist objtexturetemplatelist = ( for i = 1 to objtexmaplist.count do ( objtexmap = objtexmaplist[i] isTintPalette = RsIsTintPalette objtexmaptypelist[i] -- B* 990857 - tint palettes are never considered 'infinite usage' idxFound = finditem texmaplist objtexmap if (idxFound == 0) then ( append texmaplist objtexmap append texmaptypelist objtexmaptypelist[i] append maxsizelist objmaxsizelist[i] append isbumplist objisbumplist[i] append exemptionlist objexemptionlist[i] append texturetemplatelist objtexturetemplatelist[i] if (infiniteusage and (not isTintPalette)) then ( append usagelist -1 ) else ( append usagelist 1 ) ) else ( if ( (infiniteusage and (not isTintPalette)) or usagelist[idxFound] == -1 ) then ( usagelist[idxFound] = -1 ) else ( -- Tint palettes are never to go in TXDs. if (not isTintPalette) then ( usagelist[idxFound] = usagelist[idxFound] + 1 ) else ( usagelist[idxFound] = 1 ) ) ) ) ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsIsTXDUsedOnLod txdname srcobjlist:rootnode.children = ( local idxTXD = getAttrIndex "Gta Object" "TXD" local allObjs = #() RsGetMapObjects srcObjList allObjs local retVal = False for obj in allObjs while (not retVal) do ( if (getattrclass obj == "Gta Object") and (not isRefObj obj) and (not isInternalRef obj) do ( retVal = ((matchPattern (getattr obj idxTXD) pattern:txdname) and (::RsIsAnyLOD obj)) ) ) return retVal ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by all objects with specified txd ---------------------------------------------------------------------------------------- fn RsGetTexMapsByTxdNameNoStrip texmaplist maxsizelist isbumplist usagelist txdname srcobjlist: isCutsceneObject:false exemptionlist:#() texmaptypelist:#() texturetemplatelist:#() materialpresetlist:#() heavy_texture_logging:False = ( txdname = toLower txdname idxTXD = getattrindex "Gta Object" "TXD" if (srcObjList == unsupplied) do ( srcObjList = #() join srcObjList rootnode.children ) local allobjs = #() RsGetMapObjects srcobjlist allobjs isCutsceneObject:isCutsceneObject local usedCount = 0 for obj in allobjs do ( if (isKindOf obj Gta_MILO) then ( for childobj in obj.children do ( if (not isRefObj childobj) and (not isInternalRef childobj) and (getattrclass childobj == "Gta Object") do ( if (matchPattern (getattr childobj idxTXD) pattern:txdname) do ( local objtexmaplist = #() local objmaxsizelist = #() local objisbumplist = #() local objexemptionlist = #() local objmaptypelist = #() local objtexturetemplatelist = #() RsGetTexMapsFromObjNoStrip childobj objtexmaplist objmaxsizelist objisbumplist exemptionlist:objexemptionlist maptypelist:objmaptypelist texturetemplatelist:objtexturetemplatelist materialpresetlist:materialpresetlist RsMergeTextureUsage texmaplist texmaptypelist texturetemplatelist maxsizelist isbumplist usagelist exemptionlist objtexmaplist objmaptypelist objmaxsizelist objisbumplist false objexemptionlist objtexturetemplatelist ) ) ) ) else ( if (not isRefObj obj) and (not isInternalRef obj) and (getattrclass obj == "Gta Object") do ( if (matchPattern (getattr obj idxTXD) pattern:txdname) do ( local objtexmaplist = #() local objmaxsizelist = #() local objisbumplist = #() local objexemptionlist = #() local objmaptypelist = #() local objtexturetemplatelist = #() infiniteUsage = false if ( RsIsAnyLOD obj == true ) then infiniteUsage = true RsGetTexMapsFromObjNoStrip obj objtexmaplist objmaxsizelist objisbumplist exemptionlist:objexemptionlist maptypelist:objmaptypelist texturetemplatelist:objtexturetemplatelist materialpresetlist:materialpresetlist if (heavy_texture_logging) do ( format "************************************\n" format "* after RsGetTexMapsFromObjNoStrip\n" format "************************************\n" format "obj.name: %\n" obj.name format "infiniteUsage: %\n" infiniteUsage format "objtexmaplist.count: %\n" objtexmaplist.count for item in objtexmaplist do format " item: %\n" item format "objmaxsizelist.count: %\n" objmaxsizelist.count for item in objmaxsizelist do format " item: %\n" item format "objisbumplist.count: %\n" objisbumplist.count for item in objisbumplist do format " item: %\n" item format "objexemptionlist.count: %\n" objexemptionlist.count for item in objexemptionlist do format " item: %\n" item format "objmaptypelist.count: %\n" objmaptypelist.count for item in objmaptypelist do format " item: %\n" item format "objtexturetemplatelist.count: %\n" objtexturetemplatelist.count for item in objtexturetemplatelist do format " item: %\n" item format "************************************\n" ) RsMergeTextureUsage texmaplist texmaptypelist texturetemplatelist maxsizelist isbumplist usagelist exemptionlist objtexmaplist objmaptypelist objmaxsizelist objisbumplist infiniteUsage objexemptionlist objtexturetemplatelist if (heavy_texture_logging) do ( format "************************************\n" format "* after RsMergeTextureUsage\n" format "************************************\n" format "texmaplist.count: %\n" texmaplist.count for item in texmaplist do format " item: %\n" item format "texmaptypelist.count: %\n" texmaptypelist.count for item in texmaptypelist do format " item: %\n" item format "texturetemplatelist.count: %\n" texturetemplatelist.count for item in texturetemplatelist do format " item: %\n" item format "maxsizelist.count: %\n" maxsizelist.count for item in maxsizelist do format " item: %\n" item format "isbumplist.count: %\n" isbumplist.count for item in isbumplist do format " item: %\n" item format "usagelist.count: %\n" usagelist.count for item in usagelist do format " item: %\n" item format "exemptionlist.count: %\n" exemptionlist.count for item in exemptionlist do format " item: %\n" item format "************************************\n" ) ) ) ) -- Get texmaps for root-bone (if obj has one) to collect light-textures for a skinned object: local skelObj = rexGetSkinRootBone obj if (skelObj != undefined) do ( local skel_texmaplist = #() local skel_maxsizelist = #() local skel_isbumplist = #() local skel_exemptionlist = #() local skel_maptypelist = #() local skel_texturetemplatelist = #() RsGetTexMapsFromObjNoStrip skelObj \ skel_texmaplist skel_maxsizelist skel_isbumplist exemptionlist:skel_exemptionlist maptypelist:skel_maptypelist texturetemplatelist:skel_texturetemplatelist materialpresetlist:materialpresetlist RsMergeTextureUsage \ texmaplist texmaptypelist texturetemplatelist maxsizelist isbumplist usagelist exemptionlist \ skel_texmaplist skel_maptypelist skel_maxsizelist skel_isbumplist false skel_exemptionlist skel_texturetemplatelist ) ) return texmaplist ) ---------------------------------------------------------------------------------------- -- fills texmaplist with the texture maps used by all objects with specified txd ---------------------------------------------------------------------------------------- fn RsGetTexMapsByTxdName texmaplist maxsizelist isbumplist usagelist txdname srcobjlist:rootnode.children isCutsceneObject:false resizeexemptionlist:#() texmaptypelist:#() texturetemplatelist:#() texmaplistnostrip:#() = ( newtexmaplist = #() newtexmaptypelist = #() newmaxsizelist = #() newisbumplist = #() newusagelist = #() newresizeexemptionlist = #() newtexturetemplatelist = #() RsGetTexMapsByTxdNameNoStrip newtexmaplist newmaxsizelist newisbumplist newusagelist txdname srcobjlist:srcobjlist isCutsceneObject:isCutsceneObject exemptionlist:newresizeexemptionlist texmaptypelist:newtexmaptypelist texturetemplatelist:newtexturetemplatelist newtexmaplistnostrip = copy newtexmaplist #nomap RsStripPaths newtexmaplist -- we need to do this because there will be multiple entries if the same texture name -- has been used from a different path or extension for i = 1 to newtexmaplist.count do ( texmap = newtexmaplist[i] idxFound = finditem texmaplist texmap if idxFound == 0 then ( append texmaplist newtexmaplist[i] append texmaptypelist newtexmaptypelist[i] append maxsizelist newmaxsizelist[i] append isbumplist newisbumplist[i] append usagelist newusagelist[i] append resizeexemptionlist newresizeexemptionlist[i] append texturetemplatelist newtexturetemplatelist[i] append texmaplistnostrip newtexmaplistnostrip[i] ) else if usagelist[idxFound] != -1 and newusagelist[i] != -1 then ( usagelist[idxFound] = usagelist[idxFound] + newusagelist[i] ) else if newusagelist[i] == -1 then ( usagelist[idxFound] = -1 ) ) return texmaplist ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsGetTxdFromObject obj txdList: txdObjList: includeRefs:false idxGroupTXD:(getattrindex "Gta Group" "TXD") idxTXD:(getattrindex "Gta Object" "TXD") idxDontExport:(GetAttrIndex "Gta Object" "Dont Export") = ( local txd = unsupplied case of ( (includeRefs and (isRSref obj includeDelegates:true)): ( txd = if (obj.refDef == undefined) then ( "null" ) else ( if (obj.refDef.txd == undefined) do ( RsRefFuncs.loadTxds #(obj.refDef) ) toLower obj.refDef.txd ) ) (includeRefs and isInternalRef obj): ( local srcObj = getIRefSource obj if (getattrclass srcObj == "Gta Object") do ( txd = toLower (getattr srcObj idxTXD) ) ) ((not isInternalRef obj) and (not isRefObj obj) and (getattrclass obj == "Gta Object")): ( valDontExport = getattr obj idxDontExport if valDontExport == false do ( txd = toLower (getattr obj idxTXD) ) ) (isKindOf obj Container): ( -- Iterate through container's children. for child in obj.children do ( RsGetTxdFromObject child txdList:txdList txdObjList:txdObjList includeRefs:includeRefs idxGroupTXD:idxGroupTXD idxTXD:idxTXD idxDontExport:idxDontExport ) ) (isKindOf obj GtaGroup): ( txd = toLower (getattr obj idxGroupTXD) ) ) -- Don't add to lists if they're not being used: if (txd == unsupplied) then ( txd = undefined ) else if (txdList != unsupplied) do ( local idxTxd = finditem txdList txd if (idxTxd == 0) do ( append txdList txd append txdObjList #() idxTxd = txdList.count ) append txdObjList[idxTxd] obj ) return txd ) ---------------------------------------------------------------------------------------- -- get all the txd names for objList ---------------------------------------------------------------------------------------- fn RsGetTxdList objList txdList txdObjList includeRefs:false sorted:false idxGroupTXD:(getattrindex "Gta Group" "TXD") idxTXD:(getattrindex "Gta Object" "TXD") idxDontExport:(GetAttrIndex "Gta Object" "Dont Export") = ( local RsGetTxdListMsg = ("RsGetTxdList count:(" + (objList.count as string) + ")") gRsUlog.ProfileStart RsGetTxdListMsg -- Pre-load RsRef txd-data: if includeRefs do ( -- Flatten obj-list: local flatObjsList = for obj in objList collect obj local objNum = 0 while objNum < flatObjsList.count do ( objNum += 1 join flatObjsList flatObjsList[objNum].children ) local refDefs = for obj in flatObjsList where (isRSref obj includeDelegates:true) and (obj.refDef != undefined) collect obj.refDef RsRefFuncs.loadTxds (makeUniqueArray refDefs) ) for obj in objlist do ( case classof obj of ( Gta_MILO: ( for childObj in obj.children do ( if classof childobj == GtaMloRoom then ( for actualObj in childobj.children do ( RsGetTxdFromObject actualObj txdList:txdList txdObjList:txdObjList includeRefs:includeRefs idxGroupTXD:idxGroupTXD idxTXD:idxTXD idxDontExport:idxDontExport ) ) else ( RsGetTxdFromObject childObj txdList:txdList txdObjList:txdObjList includeRefs:includeRefs idxGroupTXD:idxGroupTXD idxTXD:idxTXD idxDontExport:idxDontExport ) ) ) Default: ( RsGetTxdFromObject obj txdList:txdList txdObjList:txdObjList includeRefs:includeRefs idxGroupTXD:idxGroupTXD idxTXD:idxTXD idxDontExport:idxDontExport ) ) ) local nulltxdsmsg = "Removing Null TXDs" gRsUlog.ProfileStart nulltxdsmsg -- Remove any null txds: local foundNull = true while foundNull do ( foundNull = false local idxItem = finditem txdList "null" if idxItem != 0 then ( foundNull = true deleteItem txdList idxItem deleteItem txdObjList idxItem ) ) gRsUlog.ProfileEnd context:nulltxdsmsg local sortTxdsMsg = "Sorting Txds" gRsUlog.ProfileStart sortTxdsMsg -- Sort txds/objs alphabetically: if sorted do ( -- Staple object-lists to txds: local sortList = for n = 1 to txdList.count collect (dataPair txd:txdList[n] objs:txdObjList[n]) -- Sort list: fn txdSorter v1 v2 = (striCmp v1.txd v2.txd) qsort sortList txdSorter -- Replace previous list-contents with sorted items: txdList.count = 0 txdObjList.count = 0 join txdList (for item in sortList collect item.txd) join txdObjList (for item in sortList collect item.objs) ) gRsUlog.ProfileEnd context:sortTxdsMsg gRsUlog.ProfileEnd context:RsGetTxdListMsg return txdList ) ---------------------------------------------------------------------------------------- -- get all the txd names in the scene ---------------------------------------------------------------------------------------- fn RsGetSceneTxdList includeRefs:false = ( local txdList = #() RsGetTxdList rootnode.children txdlist #() includeRefs:includeRefs return txdList ) ---------------------------------------------------------------------------------------- -- get all the txd names in the scene ---------------------------------------------------------------------------------------- fn RsGetSortedTxdList objlist txdlist includeRefs:false = ( txdobjlist = #() RsGetTxdList objlist txdlist txdobjlist includeRefs:includeRefs sort txdlist ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsStdMatIsMapUsedByObject obj mapidx = ( retval = false objmat = obj.material if objmat != undefined then ( if classof objmat == XRef_Material then ( objmat = objmat.getsrcitem() ) if classof objmat == Standardmaterial then ( if objmat.mapEnables[mapidx] == true then ( retval = true ) ) else if classof objmat == Multimaterial then ( mapList = #() RsMatGetMapIdsUsedOnObject obj mapList for i = 1 to objmat.materialList.count do ( id = objmat.materialIDList[i] if retval == false and finditem mapList id != 0 then ( mat = objmat.materialList[i] if classof mat == Standardmaterial then ( if mat.mapEnables[mapidx] == true then ( retval = true ) ) ) ) ) ) retval ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsDoesObjUseShader obj shaderName = ( retval = false if classof obj == Editable_Mesh or classof obj == Editable_Poly then ( objmat = obj.material if objmat != undefined then ( if classof objmat == XRef_Material then ( objmat = objmat.getsrcitem() ) ) if objmat != undefined then ( if classof objmat == Multimaterial then ( mapList = #() RsMatGetMapIdsUsedOnObject obj mapList --print "MapList: " + (mapList as string) for i = 1 to objmat.materialList.count do ( if retval == false then ( id = objmat.materialIDList[i] if finditem mapList id != 0 then ( mat = objmat.materialList[i] if classof mat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName mat)) == shaderName then ( retval = true ) ) ) ) ) ) if classof objmat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName objmat)) == shaderName then ( retval = true ) ) ) ) retval ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsGetObjFacesUsingShader obj shaderName faceidlistout = ( retval = false if classof obj == Editable_Mesh or classof obj == Editable_Poly then ( objmat = obj.material if objmat != undefined then ( if classof objmat == XRef_Material then ( objmat = objmat.getsrcitem() ) ) if objmat != undefined then ( if classof objmat == Multimaterial then ( mapList = #() polyCountList = #() faceIDLists = #() RsMatGetMapIdsUsedOnObjectWithCount obj mapList polycount:polyCountList faceidlists:faceIDLists -- QUICKER WITH OUT THESE LINES --format "mapList: % \n" (mapList as string) --format "polyCountList: %\n" (polyCountList as string) --format "faceidlists: %\n" (faceIDLists as string) for i = 1 to objmat.materialList.count do ( id = objmat.materialIDList[i] idxFound = finditem mapList id if idxFound != 0 then ( mat = objmat.materialList[i] if classof mat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName mat)) == shaderName then ( for item in faceIDLists[idxFound] do ( append faceidlistout item ) retval = true ) ) ) ) ) if classof objmat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName objmat)) == shaderName then ( for face in obj.faces do append faceidlistout face.index retval = true ) ) ) ) retval ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsCheckIsAlphad obj = ( isAlpha = false if classof obj == Editable_Mesh or classof obj == Editable_Poly then ( objmat = obj.material if objmat != undefined then ( if classof objmat == XRef_Material then ( objmat = objmat.getsrcitem() ) ) if objmat != undefined then ( if classof objmat == Multimaterial then ( mapList = #() RsMatGetMapIdsUsedOnObject obj mapList for i = 1 to objmat.materialList.count do ( id = objmat.materialIDList[i] if finditem mapList id != 0 then ( mat = objmat.materialList[i] if rexHasAlpha obj mat then ( isAlpha = true ) ) ) ) else ( if rexHasAlpha obj objmat then ( isAlpha = true ) ) ) ) isAlpha ) ---------------------------------------------------------------------------------------- -- ---------------------------------------------------------------------------------------- fn RsDoesObjUseGlassShader obj = ( local retVal = false local shadersUsed = ::RsGetShaderListForObjects obj for shaderName in shadersUsed while not retVal do ( retVal = matchPattern shaderName pattern:"*_glass*" ) retVal ) fn GetCompositeFileName fileNameIn = ( -- Sort Wierdness in SpeedTreeCad where sometimes -- the compositefilename stored in the .spt file -- will not have the ".tga" extension amd sometimes it will strExt = substring fileNameIn (fileNameIn.count - 3) 4 if strExt == ".tga" then ( fileNameOut = fileNameIn ) else ( fileNameOut = fileNameIn + ".tga" ) return fileNameOut ) --------------------------------------------------------------------------------- -- Return whether the specified object uses the specified shader -- -- This is an enhanced version of the RsDoesObjUseShader2 above as it also -- considers Standard materials that can be converted to shaders. -- -- [return] true iff object uses shader, false otherwise --------------------------------------------------------------------------------- fn RsDoesObjUseShader2 obj shaderName = ( retval = false if classof obj == Editable_Mesh or classof obj == Editable_Poly then ( objmat = obj.material if objmat != undefined then ( if classof objmat == XRef_Material then ( objmat = objmat.getsrcitem() ) ) if objmat != undefined then ( if classof objmat == Multimaterial then ( mapList = #() RsMatGetMapIdsUsedOnObject obj mapList for i = 1 to objmat.materialList.count do ( if retval == false then ( id = objmat.materialIDList[i] if finditem mapList id != 0 then ( mat = objmat.materialList[i] if classof mat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName mat)) == shaderName then ( retval = true ) ) else if classof mat == Standardmaterial then ( -- Check materials shader equivalent (if available) matShaderName = ( rexStdMatShaderName mat ) if ( String != classof matShaderName ) then continue if ( RsRemoveExtension( matShaderName ) == shaderName ) then ( retval = true ) ) ) ) ) ) if classof objmat == Rage_Shader then ( if (RsRemoveExtension(RstGetShaderName objmat)) == shaderName then ( retval = true ) ) else if classof objmat == Standardmaterial then ( -- Check materials shader equivalent (if available) matShaderName = ( rexStdMatShaderName objmat ) if ( String != classof matShaderName ) then continue if ( RsRemoveExtension( matShaderName ) == shaderName ) then ( retval = true ) ) ) ) retval ) --------------------------------------------------------------------------------- -- Return number of Rage Shader and Standard materials (and submaterials) -- only Standard materials that can be converted to Rage Shaders are included. -- -- [return] Number of Rage Shader supported materials in the scene --------------------------------------------------------------------------------- fn RsGetMaterialCount &numRageShaderMaterials &numShaderStandardMaterials &numStandardMaterials = ( numRageShaderMaterials = 0 numShaderStandardMaterials = 0 numStandardMaterials = 0 for mat in sceneMaterials do ( if ( Rage_Shader == classof mat ) then numRageShaderMaterials += 1 else if ( Standard == classof mat ) then ( shaderName = ( rexStdMatShaderName mat ) if ( String == classof shaderName ) then numShaderStandardMaterials += 1 else numStandardMaterials += 1 ) else if ( Multimaterial == classof mat ) then ( for submat in mat.materialList do ( if ( Rage_Shader == classof submat ) then numRageShaderMaterials += 1 else if ( Standard == classof mat ) then ( shaderName = ( rexStdMatShaderName mat ) if ( String == classof shaderName ) then numShaderStandardMaterials += 1 else numStandardMaterials += 1 ) ) ) ) true ) -- Return list of shaders used by material: fn RsGetShaderListForMat mat shaderList:#() = ( case (classof mat) of ( Rage_Shader: ( appendIfUnique shaderList (RstGetShaderName mat) ) Multimaterial: ( for subMat in mat.materialList do ( RsGetShaderListForMat subMat shaderList:shaderList ) ) ) shaderList ) --------------------------------------------------------------------------------- -- Returns list of available shaders -- (lower-case, with path/extension removed) --------------------------------------------------------------------------------- fn RsGetShaderList = ( if (RSshaderList == undefined) do ( local ShaderPaths = RsFindFilesRecursive ((RsConfigGetCommonDir core:true) + "shaders/db/") #("*.sps", "*.mpt", "*.mps") RSshaderList = for Filename in ShaderPaths collect (toLower (getFilenameFile Filename)) ) return RSshaderList ) --------------------------------------------------------------------------------- -- Return list of shaders in current scene -- -- [return] Array of shader name strings (path and extension removed) --------------------------------------------------------------------------------- fn RsGetSceneShaderList = ( shaderList = #() for mat in sceneMaterials do ( RsGetShaderListForMat mat shaderList:shaderList ) sort shaderList shaderList ) -- Return list of shaders for a set of objects: fn RsGetShaderListForObjects objs = ( local shaderList = #() for obj in objs do ( local ObjMats = ::RsGetMaterialsOnObjFaces Obj for Mat in ObjMats do ( RsGetShaderListForMat Mat shaderList:shaderList ) ) shaderList ) --------------------------------------------------------------------------------- -- Return list of Standard Materials for a set of objects -- -- [in] objs List of objects to get list of Standard Materials for -- [out] matList List of Standard Materials used by objs -- [out[ parentList List of material's in matList's parents (per mat) --------------------------------------------------------------------------------- fn RsGetStdMatListForObjects objs &nameList &matList &parentList = ( nameList = #() matList = #() parentList = #() for o in objs do ( if ( undefined == o.material ) then continue if ( StandardMaterial == classof o.material ) then ( if ( 0 == findItem matList o.material ) then ( append nameList o.name append matList o.material append parentList undefined ) ) else if ( Multimaterial == classof o.material ) then ( for subMat in o.material.materialList do ( if ( StandardMaterial == classof subMat ) then ( if ( 0 == findItem matList subMat ) then ( append nameList o.name append matList subMat append parentList o.material ) ) ) ) ) ) --------------------------------------------------------------------------------- -- Return list of Rage Shader Materials for a set of objects -- -- [in] objs List of objects to get list of Rage Shader Materials for -- [out] matList List of Rage Shader Materials used by objs -- [out] parentList List of material's in matList's parents (per mat) -- [out] objectList Allows us to retrieve source object per mat --------------------------------------------------------------------------------- fn RsGetRageShaderMatListForObjects objs &matList &parentList objectList:#() = ( matList = #() parentList = #() for o in objs do ( if ( undefined == o.material ) then continue if ( Rage_Shader == classof o.material ) then ( if ( 0 == findItem matList o.material ) then ( append matList o.material append parentList undefined append objectList o ) ) else if ( Multimaterial == classof o.material ) then ( for subMat in o.material.materialList do ( if ( Rage_Shader == classof subMat ) then ( if ( 0 == findItem matList subMat ) then ( append matList subMat append parentList o.material append objectList o ) ) ) ) ) ) --------------------------------------------------------------------------------- -- Return list of Rage Nitro Shader Materials for a set of objects -- -- [in] objs List of objects to get list of Rage Shader Materials for -- [out] matList List of Rage Shader Materials used by objs -- [out] parentList List of material's in matList's parents (per mat) -- [out] objectList Allows us to retrieve source object per mat --------------------------------------------------------------------------------- fn RsGetRageNitroShaderMatListForObjects objs &matList &parentList objectList:#() = ( matList = #() parentList = #() for o in objs do ( if ( undefined == o.material ) then continue if ( Rage_Nitro == classof o.material ) then ( if ( 0 == findItem matList o.material ) then ( append matList o.material append parentList undefined append objectList o ) ) else if ( Multimaterial == classof o.material ) then ( for subMat in o.material.materialList do ( if ( Rage_Nitro == classof subMat ) then ( if ( 0 == findItem matList subMat ) then ( append matList subMat append parentList o.material append objectList o ) ) ) ) ) ) --------------------------------------------------------------------------------- -- Return object shader usage counts for object list and shader list -- -- [in] objs List of objects to get usage information for -- [in] shaders List of shaders to get usage information for --------------------------------------------------------------------------------- fn RsGetObjectShaderCounts objs shaders = ( shaderObjectCounts = #() local shaderCount = shaders.count -- Initialise shaderObjectCount entries for sh in shaders do append shaderObjectCounts 0 for i = 1 to shaderCount do ( for o in objs do ( if ( RsDoesObjUseShader2 o shaders[i] ) then ( shaderObjectCounts[i] += 1 ) ) ) shaderObjectCounts ) --------------------------------------------------------------------------------- -- Fetches object shader usage counts and object, materials lists using each shader -- -- [in] objs List of objects to get usage information for -- [in] shaders List of shaders to get usage information for -- [out] shaderObjectLists Array of array of object references per shader --------------------------------------------------------------------------------- fn RsGetObjectShaderUsageData objs shaders &shaderObjectLists &shaderMaterialLists = ( -- Initialise parameter reference data shaderObjectLists = #() local shaderCount = shaders.count -- Now iterate through shaders and objects to collect our usage data for i = 1 to shaderCount do ( shaderObjectList = #() shaderMaterialList = #() for o in objs do ( if ( RsDoesObjUseShader2 o shaders[i] ) then ( append shaderObjectList o if ( Multimaterial == classof o.material ) then ( for mat in o.material.materialList do ( if ( Standard == classof mat ) then ( shaderName = ( rexStdMatShaderName mat ) if ( ( undefined == shaderName ) or ( classof shaderName != String ) ) then continue if ( (RsRemoveExtension(shaderName)) == shaders[i] ) then if ( 0 == findItem shaderMaterialList mat ) then append shaderMaterialList mat ) else if ( Rage_Shader == classof mat ) then ( shaderName = ( RstGetShaderName mat ) if ( (RsRemoveExtension(shaderName)) == shaders[i] ) then if ( 0 == findItem shaderMaterialList mat ) then append shaderMaterialList mat ) ) ) else if ( Standard == classof o.material ) then ( shaderName = ( rexStdMatShaderName o.material ) if ( ( undefined == shaderName ) or ( classof shaderName != String ) ) then continue if ( (RsRemoveExtension(shaderName)) == shaders[i] ) then if ( 0 == findItem shaderMaterialList o.material ) then append shaderMaterialList o.material ) else if ( Rage_Shader == classof o.material ) then ( shaderName = ( RstGetShaderName o.material ) if ( (RsRemoveExtension(shaderName)) == shaders[i] ) then if ( 0 == findItem shaderMaterialList o.material ) then append shaderMaterialList o.material ) ) ) append shaderObjectLists shaderObjectList append shaderMaterialLists shaderMaterialList ) true ) --------------------------------------------------------------------------------------------------- -- Is this a tree-billboard material? --------------------------------------------------------------------------------------------------- fn RsIsBillboardMat mtl = ( (isKindOf mtl Rage_Shader) and ( local shadername = RstGetShaderName mtl matchPattern shaderName pattern:"trees_lod2*" ) ) -- True if obj has any billboard shaders: fn RsFindTreeShader obj mtl treeShaderList: = ( local retVal = False case of ( (isKindOf mtl MultiMaterial): ( local matList = ::RsGetMaterialsOnObjFaces obj material:mtl for subMat in matList do ( local isTreeShader = RsFindTreeShader obj subMat treeShaderList:treeShaderList if isTreeShader then retVal = true ) ) (RsIsBillboardMat mtl): ( if unsupplied!=treeShaderList then appendIfUnique treeShaderList mtl retVal = True ) ) return retVal ) -- -- name: RsIsTreeBillboard -- desc: Determine is the object is a tree-billboard (based on shader name). -- fn RsIsTreeBillboard obj mat = ( return RsFindTreeShader obj mat ) --------------------------------------------------------------------------------------------------- -- Swaps two materials --------------------------------------------------------------------------------------------------- fn RsMatSwapSubMats multiSub mat1Idx mat2Idx = ( if (isKindOf multiSub Multimaterial) then ( -- Get positions of matIDs on material-list, just in case it's been reordered or has non-contigious ID-numbers: local listPos1 = findItem multiSub.materialIDList mat1Idx local listPos2 = findItem multiSub.materialIDList mat2Idx -- Swap submaterials: local tmp = multiSub.materialList[mat1Idx] multiSub.materialList[mat1Idx] = multiSub.materialList[mat2Idx] multiSub.materialList[mat2Idx] = tmp -- Swap material-enableds: local mat1Enabled = multiSub.mapEnabled[listPos1] local mat2Enabled = multiSub.mapEnabled[listPos2] multiSub.mapEnabled[mat1Idx] = mat2Enabled multiSub.mapEnabled[mat2Idx] = mat1Enabled -- Swap submaterial-labels: (not the actual materials' names) local mat1Name = multiSub.names[listPos1] local mat2Name = multiSub.names[listPos2] multiSub.names[mat1Idx] = mat2Name multiSub.names[mat2Idx] = mat1Name for obj in geometry where (obj.mat == multiSub) do ( local objClass = classOf obj local objGetFaceMatID = case objClass of ( Editable_Mesh:getFaceMatID Editable_Poly:polyOp.getFaceMatID ) local objSetFaceMatID = case objClass of ( Editable_Mesh:setFaceMatID Editable_Poly:polyOp.setFaceMatID ) if (objGetFaceMatID != undefined) do ( for faceNum = 1 to obj.numfaces do ( case (objGetFaceMatID obj faceNum) of ( mat1Idx:(objSetFaceMatID obj faceNum mat2Idx) mat2Idx:(objSetFaceMatID obj faceNum mat1Idx) ) ) ) ) true ) else false ) --------------------------------------------------------------------------------------------------- -- Inserts new submaterial into multiSub --------------------------------------------------------------------------------------------------- fn RsMatInsertSubMat multiSub newMatId newMat: = ( if (isKindOf multiSub Multimaterial) then ( if (newMat == unsupplied) do ( local matClass = classOf multiSub.materialList[1] newMat = createInstance matClass ) -- Find the matID closest to newMatId, so that we can insert just before that -- (I'm going through this rigmarole because the multimat may have been reordered or have non-contigious ID-numbers) local insertAt = 1 local insertBeforeID = multiSub.numSubs local getID for n = 1 to multiSub.materialIDList.count do ( getID = multiSub.materialIDList[n] if (getID >= newMatId) do ( if (getID < insertBeforeID) do ( insertBeforeID = getID insertAt = n ) -- Bump up any IDs over newMatId: multiSub.materialIDList[n] += 1 ) ) -- Insert the new material: local newMatList = multiSub.materialList as array local newMatIDList = multiSub.materialIDList as array insertItem newMat newMatList insertAt insertItem newMatId newMatIDList insertAt multiSub.materialList = newMatList multiSub.materialIDList = newMatIDList -- Shuffle the submat enabled-values down the list: for n = multiSub.materialList.count to (insertAt + 1) by -1 do ( multiSub.mapEnabled[n] = multiSub.mapEnabled[n - 1] ) local matObjs = for obj in geometry where (obj.mat == multiSub) collect obj local curMatID for obj in matObjs do ( local objClass = classOf obj local objGetFaceMatID = case objClass of ( Editable_Mesh:getFaceMatID Editable_Poly:polyOp.getFaceMatID ) local objSetFaceMatID = case objClass of ( Editable_Mesh:setFaceMatID Editable_Poly:polyOp.setFaceMatID ) if (objGetFaceMatID != undefined) do ( for faceNum = 1 to obj.numfaces do ( curMatID = objGetFaceMatID obj faceNum if (curMatID >= newMatId) do ( objSetFaceMatID obj faceNum (curMatID + 1) ) ) ) ) true ) else false ) -- Returns list of defined texmaps for a given object/material/texmap: fn RsGetMaterialTexMaps item texMaps:#() = ( -- Recurse through given objects' materials and lightmaps: if (isValidNode item) do ( -- Get materials from object: if (isProperty item #material) do ( RsGetMaterialTexMaps item.material texMaps:texMaps ) -- Get lightmap from light: ( local lightShadowMap = undefined if (isProperty item #delegate) do ( item = item.delegate ) if (isProperty item #shadowProjectorMap) do ( lightShadowMap = item.shadowProjectorMap ) if (lightShadowMap != undefined) do ( RsGetMaterialTexMaps lightShadowMap texMaps:texMaps ) ) return texMaps ) -- Recurse through all sub-materials/textures: case (classOf item) of ( -- Materials: MultiMaterial: ( -- Recurse through submaterials: for subMat in item.materialList do ( RsGetMaterialTexMaps subMat texMaps:texMaps ) ) CompositeMaterial: ( -- Recurse through submaterials: for subMat in item.materialList do ( RsGetMaterialTexMaps subMat texMaps:texMaps ) ) XRef_Material: ( -- Recurse to reffed material: RsGetMaterialTexMaps (item.getsrcitem()) texMaps:texMaps ) Blend: ( RsGetMaterialTexMaps item.map1 texMaps:texMaps RsGetMaterialTexMaps item.map2 texMaps:texMaps ) DoubleSided: ( RsGetMaterialTexMaps item.material1 texMaps:texMaps RsGetMaterialTexMaps item.material2 texMaps:texMaps ) Shellac: ( RsGetMaterialTexMaps item.shellacmtl1 texMaps:texMaps RsGetMaterialTexMaps item.shellacmtl2 texMaps:texMaps ) TopBottom: ( RsGetMaterialTexMaps item.topMaterial texMaps:texMaps RsGetMaterialTexMaps item.bottomMaterial texMaps:texMaps ) -- Texturemaps: Bitmaptexture: ( ------------------------------------------------------------------------- -- Here's where the texturemaps are actually collected: -- ------------------------------------------------------------------------- if (item.filename != undefined) and (item.filename != "") do ( append texMaps item ) ) CompositeTexturemap: ( -- Recurse through sub-texmaps: for n = 1 to (getNumSubTexmaps item) do ( local texMap = getSubTexmap item n RsGetMaterialTexMaps texMap texMaps:texMaps ) ) DistanceAlphaMap: ( -- Get proper texmap for DistanceAlphaMap: local texMap = RsGetDistanceAlphaMapResultMap item RsGetMaterialTexMaps texMap texMaps:texMaps ) -- Ignore undefined materials/textureMaps UndefinedClass:() Default: ( if (isKindOf item material) do ( -- Recurse through material's texturemaps: for n = 1 to (getNumSubTexmaps item) do ( local texMap = getSubTexmap item n RsGetMaterialTexMaps texMap texMaps:texMaps ) ) ) ) return texMaps ) -- Lists all texture-paths used by material/texturemap/object 'item' fn RsGetMaterialTextures item textureList:#() = ( local texMaps = RsGetMaterialTexMaps item -- Make texMaps list only contain unique texmaps: local texMaps = (makeUniqueArray texMaps) -- Set textureList to unique array of non-undefined paths: local newTexPaths = for texMap in texMaps collect texMap.filename newTexPaths = for filename in newTexPaths where (filename != "") and (filename != undefined) collect (toLower filename) -- Don't edit/uniquify textureList if we're not adding anything: if (newTexPaths.count != 0) do ( join textureList newTexPaths newTexPaths = makeUniqueArray textureList -- Replace textureList with ammended version of list: textureList.count = 0 join textureList newTexPaths ) return textureList ) -- Get unique textureMap items used in scene: fn RsGetSceneTexMaps = ( local texMaps = #() -- Get lightmaps from light-objects: for obj in lights do ( RsGetMaterialTexMaps obj texMaps:texMaps ) -- Get texmaps from sceneMaterials: local sceneMats = makeUniqueArray (for mat in sceneMaterials collect mat) for mat in sceneMats do ( RsGetMaterialTexMaps mat texMaps:texMaps ) -- Make unique array: texMaps = makeUniqueArray texMaps return texMaps ) -- Lists all texture-paths used on materials used in the scene. -- (Materials don't have to actually be applied to objects) fn RsGetSceneTextures = ( local texMaps = RsGetSceneTexMaps() local textureList = for texMap in texMaps collect (toLower texMap.filename) textureList = makeUniqueArray textureList return textureList ) -- Perforce-syncs files in textureList to latest versions on Perforce, if they're under the texture-root: fn RsP4syncTextures textureList = ( -- Sync scene-textures if they're in Perforce. Force-syncs if they still don't exist locally after that sync. ::gRsPerforce.syncWithRetry textureList showProgress:true progressTitle:"P4 Sync Textures:" silent:true ) -- Perforce-syncs all textures used in the scene: fn RsP4syncSceneTextures = ( RsP4syncTextures (RsGetSceneTextures()) ) -- Returns all materials actually used on an object, and optionally can pass those materials' face-lists by reference fn RsGetMaterialsOnObjFaces obj material: materials:#() faceLists: mtlIdList:#() = ( local objMat = if (material == unsupplied) then obj.material else material if (classof objMat == XRef_Material) or isRefObj obj then return materials local getMesh = true local doFaceLists = (isKindOf faceLists Array) case of ( ((isKindOf obj editable_mesh) or (isKindOf obj trimesh)): ( getMesh = false ) (isKindOf obj col_mesh): ( obj = getColMesh obj getMesh = false ) (isKindOf obj Editable_Poly): ( if ((polyop.GetHasDeadStructs obj) > 0 ) do ( polyOp.collapseDeadStructs obj ) getMesh = false ) ) if getMesh do ( if (isProperty obj #mesh) AND (classof obj != Targetobject) then ( obj = copy obj.mesh ) else ( return #() ) ) if(obj == undefined) then return #() local objGetFaceMatID = RsGetFaceMatIDFunc obj local numFaces = getNumFaces obj local objSubMatIndex = #() local isMultiMat = isKindOf objMat Multimaterial local matCount = if isMultiMat then objMat.numSubs else 1 -- collect list of the object's faces' matIDs, corrected if isMultiMat then ( local foundMatIds = #() for faceNum = 1 to numFaces do ( local matNum = objGetFaceMatID obj faceNum -- Deal with matIDs that are higher than the material-count: if (matNum > matCount) do ( matNum = (mod matNum matCount) as integer if (matNum == 0) do (matNum = matCount) ) local findNum = foundMatIds[matNum] if (findNum == undefined) do ( local matIdNum = findItem objMat.materialIDList matNum local newMat = if (matIdNum == 0) then undefined else objMat.materialList[matIdNum] findNum = findItem materials newMat if (findNum == 0) do ( append materials newMat if doFaceLists do ( append faceLists #{} ) append mtlIdList matNum findNum = materials.count ) ) if doFaceLists do ( faceLists[findNum][faceNum] = true ) ) ) else ( -- Single-material objects are simpler to process append materials objMat if doFaceLists do ( append faceLists #{1..obj.numFaces} ) append mtlIdList 1 ) return materials ) -- Return the submaterial that will be applied to an face with a particular matId -- (taking into account non-multimaterials and out-of-range material values) fn RsGetSubmatByMatId mat matId = ( if (isKindOf mat MultiMaterial) then ( -- Deal with out-of-range values: local numSubs = mat.numSubs matId = (mod matId numSubs) as integer if (matId == 0) do matId = numSubs local matIdx = findItem mat.materialIDList matId if (matIdx == 0) then return undefined else mat.materialList[matIdx] ) else ( return mat ) ) -- Returns the texturemap paths for materials used on objects in given map-containers: fn RsGetMapTextures maps = ( local textureList = #() local checkObjs = #() for map in maps do ( local mapObjs = for obj in map.objects where (getattrclass obj == "Gta Object") collect obj local refNames = #() local uniqueObjs = #() for obj in mapObjs do ( case of ( -- Only count one of each ref: (isRSref obj includeDelegates:true): ( if (appendIfUnique refNames obj.objectName) do ( append uniqueObjs obj ) ) -- Don't include internalrefs, as their parent-object should already be used: (isRsInternalRef obj):() default: ( append uniqueObjs obj ) ) ) join checkObjs uniqueObjs ) -- Filter out further instances of objects: checkObjs = ::RsGetInstGroupLeaders checkObjs if (checkObjs.count != 0) do ( pushPrompt "Collecting texture-paths..." format "Collecting texture-paths...\n" local timeStart = timestamp() local matsUsed = #() for obj in checkObjs do ( local objMats = RsGetMaterialsOnObjFaces obj join matsUsed objMats ) for mat in (makeUniqueArray matsUsed) do ( RsGetMaterialTextures mat textureList:textureList ) popPrompt() format "Time taken: %s\n" ((timestamp() - timeStart) / 1000.0) ) return textureList ) --RsGetMapTextures(RsMapGetMapContainers()) -- End of script