Download CommonLua/CollapseMaterials.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 6.91 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/CollapseMaterials.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/CollapseMaterials.lua
-
curl -L -o CollapseMaterials.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/CollapseMaterials.lua
6.91 kB
| EngineBinAssetsPrints = {} | |
| EngineBinAssetsPrint = CreatePrint { "", output = function(s) table.insert(EngineBinAssetsPrints, s) end } | |
| EngineBinAssetsPrintf = CreatePrint { "", output = function(s) table.insert(EngineBinAssetsPrints, s) end, format = string.format } | |
| EngineBinAssetsError = CreatePrint { "EB_ERROR", output = function(s) table.insert(EngineBinAssetsPrints, s) end } | |
| EngineBinAssetsErrorf = CreatePrint { "EB_ERROR", output = function(s) table.insert(EngineBinAssetsPrints, s) end, format = string.format } | |
| local function MarkTestEntityTextures(texture_list) | |
| local tex_map = {} | |
| local test_assets_path = ConvertToOSPath("svnAssets/Bin/Common/Materials/") | |
| for texture_id, path in pairs(texture_list) do | |
| local texture_name = path:sub(path:find("[^\\]*$")) | |
| tex_map[texture_name] = { | |
| id = texture_id, | |
| path = path, | |
| skip = string.starts_with(path, test_assets_path), | |
| } | |
| end | |
| return tex_map; | |
| end | |
| local function AddTextureHashes(textures_data, cached_hashes) | |
| local cached_hashes = cached_hashes or {} | |
| for texture_id, texture_data in pairs(textures_data) do | |
| local tex_hash = cached_hashes[texture_id] | |
| if not tex_hash then | |
| local err, hash = AsyncFileToString(texture_data.path, nil, nil, "hash") | |
| if err then | |
| EngineBinAssetsError("AsyncFileToString(" .. texture_data.path .. ") failed: " .. err) | |
| return err | |
| else | |
| tex_hash = tostring(hash) | |
| end | |
| end | |
| texture_data.hash = tex_hash | |
| end | |
| end | |
| local function GetTexturesCachedHashes() | |
| local err, hash_list = FileToLuaValue("svnAssets/BuildCache/TextureHashes.lua") | |
| if err then | |
| EngineBinAssetsError("Could not load hash map with material textures!") | |
| end | |
| local cached_hashes = {} | |
| for filename, v in pairs(hash_list or empty_table) do | |
| cached_hashes[filename:sub(filename:find("[^/]*$"))] = tostring(v.hash) | |
| end | |
| return cached_hashes | |
| end | |
| function MarkUniqueTextures(textures_data) | |
| local sorted_texture_ids = table.keys(textures_data) | |
| table.sort(sorted_texture_ids, function (a, b) return #a == #b and a < b or #a < #b end) | |
| local unique_hashes = {} | |
| for _, texture_id in ipairs(sorted_texture_ids) do | |
| local tex_data = textures_data[texture_id] | |
| if not tex_data.skip then | |
| local tex_alias = unique_hashes[tex_data.hash] | |
| if tex_alias then | |
| tex_data.alias = tex_alias | |
| elseif not tex_data.hash then | |
| EngineBinAssetsError("Missing texture hash for(" .. texture_id .. ")") | |
| else | |
| --tex_data.alias = texture_id -- not needed it its the same | |
| unique_hashes[tex_data.hash] = texture_id | |
| end | |
| end | |
| end | |
| local num_tex = table.count(textures_data) | |
| local num_unique = table.count(unique_hashes) | |
| EngineBinAssetsPrintf("Entity textures: %d (%d Unique, %d Duplicates)", num_tex, num_unique, num_tex - num_unique) | |
| return unique_hashes | |
| end | |
| local function RemapMaterialTextures(mat_name, textures_data, used_tex, ent_textures) | |
| local num_sub_mats = GetNumSubMaterials(mat_name) | |
| for subi=1, num_sub_mats do | |
| local props = GetMaterialProperties(mat_name, subi-1) | |
| local new_props = false | |
| for prop, value in sorted_pairs(props) do | |
| if type(value) == "string" then | |
| local tex_name = value:sub(value:find("[^/]*$")) | |
| if tex_name then | |
| local tex_data = textures_data[tex_name] | |
| if tex_data then | |
| if tex_data.alias then | |
| new_props = new_props or {} | |
| new_props[prop] = textures_data[tex_data.alias].id | |
| ent_textures[tex_data.alias] = true | |
| local alias_data = textures_data[tex_data.alias] | |
| alias_data.used_in = alias_data.used_in or {} | |
| table.insert(alias_data.used_in, mat_name) | |
| else | |
| used_tex[tex_name] = tex_data.path | |
| ent_textures[tex_name] = true | |
| tex_data.used_in = tex_data.used_in or {} | |
| table.insert(tex_data.used_in, mat_name) | |
| end | |
| end | |
| elseif value:find("<unknown>", 1, "plain") then | |
| EngineBinAssetsPrintf("once", "Missing texture Textures/%s in material %s", value:match("Textures/(.*)%.<unknown>"), mat_name) | |
| end | |
| end | |
| end | |
| if new_props then | |
| SetMaterialProperties(mat_name, subi-1, new_props) | |
| end | |
| end | |
| end | |
| local function BuildTextureIdx(used_tex) | |
| local tex_idx = {} | |
| local textures = table.keys(used_tex) | |
| table.sort(textures, function (a, b) return #a == #b and a < b or #a < #b end) | |
| for _, tex_name in ipairs(textures) do | |
| tex_idx[#tex_idx+1] = string.format("Textures/%s=%s", tex_name, used_tex[tex_name]) | |
| end | |
| local filename = "entities.txt" | |
| local path = "svnAssets/BuildCache/win32/TextureIdx/" | |
| local err = AsyncCreatePath(path) | |
| assert(not err, "Error creating textures idx path: " .. tostring(err)) | |
| local err = StringToFileIfDifferent(path .. filename, table.concat(tex_idx, "\r\n")) | |
| assert(not err, "Error writing textures idx: " .. tostring(err)) | |
| end | |
| local function ShortenTexturePaths(textures_data) | |
| for _, texture_data in pairs(textures_data) do | |
| texture_data.path = string.match(texture_data.path, "\\([^\\]+Assets.+)$") | |
| end | |
| end | |
| function CollapseMaterialTextures(texture_list, entities, cached_hashes, shorten_paths) | |
| local textures_data = MarkTestEntityTextures(texture_list) | |
| AddTextureHashes(textures_data, cached_hashes) | |
| if shorten_paths then | |
| ShortenTexturePaths(textures_data) | |
| end | |
| MarkUniqueTextures(textures_data) | |
| local materials_seen, entity_textures, used_tex = {}, {}, {} | |
| for entity, _ in sorted_pairs(entities) do | |
| if entity:sub(1,1) ~= "#" then | |
| local ent_textures = {} | |
| local states = GetStates(entity) | |
| for si=1, #states do | |
| local state = GetStateIdx(states[si]) | |
| local num_lods = GetStateLODCount(entity, state) | |
| for li=1, num_lods do | |
| local material = GetStateMaterial(entity, state, li - 1) | |
| if not materials_seen[material] then | |
| RemapMaterialTextures(material, textures_data, used_tex, ent_textures) | |
| materials_seen[material] = entity | |
| entity_textures[entity] = ent_textures | |
| else | |
| local other_entity = materials_seen[material] | |
| entity_textures[entity] = entity_textures[other_entity] | |
| end | |
| end | |
| end | |
| end | |
| end | |
| return materials_seen, used_tex, textures_data | |
| end | |
| function CollapseAllTextures() | |
| local all_entities = GetAllEntities() | |
| local texture_list = CollectMtlReferencedTextures() | |
| local cached_hashes = GetTexturesCachedHashes() | |
| local materials_seen, used_tex, textures_data = CollapseMaterialTextures(texture_list, all_entities, cached_hashes, true) | |
| BuildTextureIdx(used_tex) | |
| return materials_seen, used_tex, textures_data | |
| end | |
| function CollapseEntitiesTextures(entities) | |
| local texture_list = {} | |
| for entity, _ in sorted_pairs(entities) do | |
| local states = GetStates(entity) | |
| for si=1, #states do | |
| local state = GetStateIdx(states[si]) | |
| local state_textures = GetStateMaterialTextures(entity, state) | |
| table.append(texture_list, state_textures) | |
| end | |
| end | |
| local materials_seen, used_tex, textures_data = CollapseMaterialTextures(texture_list, entities) | |
| return materials_seen, used_tex, textures_data | |
| end |