#!/usr/bin/env python import os import re import struct # Reads all texture names from the specified directory. # Textures must end in jpg, png, or bmp. # Returns a directory with the texture name as key. def readAllTextures(dir, result): if type(dir)==type([]): for i in dir: readAllTextures(i,result) return re_is_texture = re.compile("^.*\.(jpg|png|bmp)$") for i in os.listdir(dir): if re_is_texture.match(i): result[i]=1 # ----------------------------------------------------------------------------- # Reads all texture names specified in a materials.xml file. def readMaterialsXML(filename): textures = {} f = open(filename, "r") # Crude RE instead of XML parsing re_texture_name = re.compile("^ *<material name=\"([^\"]*)\"") for i in f.readlines(): g = re_texture_name.match(i) if g: textures[g.groups(1)[0]] = 1 return textures # ----------------------------------------------------------------------------- def getTexturesFromB3D(filename, textures): f = open(filename, "r") s = f.read(4) if s!="BB3D": print filename,"is not a valid b3d file" f.close() return start_texs = 12 f.seek(start_texs) s = f.read(4) if s!="TEXS": print "Can not handle '%s' b3d file - ignored."%filename f.close() return n = struct.unpack("<i", f.read(4))[0] # Read end of section n = n - start_texs - 4 # number of bytes to read in tex section s = f.read(n) i = 0 while i<n: tex_name="" while ord(s[i]): tex_name = tex_name+s[i] i=i+1 textures[tex_name] = 1 # Update the offst: add 1 byte string terminator, # and 7 int/float values i = i + 7*4 + 1 f.close() return # ----------------------------------------------------------------------------- # Reads all textures mentioned in a track.xml or kart.xml file (e.g. icons, # screenshots, shadows) def findTrackData(dir, textures, b3dfiles): f = open(dir+"track.xml", "r") if f: r_screenshot = re.compile("^ *screenshot *= \"(.*)\" *$") for i in f.readlines(): g = r_screenshot.match(i) if g: textures[g.group(1)] = 1 f.close() f = open(dir+"scene.xml", "r") if f: r_model = re.compile(" model=\"((.*)\.b3d.?)\"") for i in f.readlines(): g = r_model.search(i) if g: b3dfiles[g.groups(1)[0]] = 1 f.close() # ----------------------------------------------------------------------------- def findKartData(dir, textures, b3dfiles): f = open(dir+"scene.xml", "r") if f: r_model = re.compile(" model=\"((.*)\.b3d.?)\"") for i in f.readlines(): g = r_model.search(i) if g: b3dfiles[g.groups(1)[0]] = 1 f.close() return else: f = open(dir+"scene.xml", "r") if not f: return print "WARNING" if 1: print "WARNING - kart.xml not done yet" f = open(dir+"kart.xml", "r") if not f: return r_screenshot = re.compile("^ *screenshot *= \"(.*)\" *$") for i in f.readlines(): g = r_screenshot.match(i) if g: textures[g.group(1)] = 1 f.close() return # ----------------------------------------------------------------------------- # Checks if all textures for a specified track- or kart-directory # are actually used. def checkDir(dir, shared_textures): # First read all *png/jpg/bmp files # --------------------------------- existing_textures = {} readAllTextures(dir, existing_textures) # Find all b3d files in the directory (print warnings for b3dz) # ------------------------------------------------------------- b3d_files_in_dir = {} for i in os.listdir(dir): if i[-4:]==".b3d": b3d_files_in_dir[i] = 1 elif i[-5:]==".b3dz": print "Can't handle file '%s'."%i # Find all textures listed in materials.xml # ----------------------------------------- materials = readMaterialsXML(dir+"/materials.xml") # Find all textures in track.xml and kart.xml files # ------------------------------------------------- used_textures = {} used_b3d_files = {} findTrackData(dir, used_textures, used_b3d_files) #findKartData(dir, used_textures, used_b3d_files) # 1) Check if there are any missing b3d files # =========================================== for i in used_b3d_files.keys(): if not b3d_files_in_dir.get(i): print "File '%s' is missing."%(dir+i) # 2) Check if there are any unnecessary b3d files # =============================================== for i in b3d_files_in_dir: if not used_b3d_files.get(i): print "File '%s' is not used."%i continue del used_b3d_files[i] # Load all textures used in this b3d file getTexturesFromB3D(dir+i, used_textures) # 3) Check if all textures used can be found # ========================================== for i in used_textures: if not existing_textures.get(i)==1: if not shared_textures.get(i): print "Cannot find texture '%s'."%i continue else: del existing_textures[i] for i in existing_textures: print "Texture '%s' is not used anywhere."%(dir+i) # Now check that all entries in materials.xml are indeed used and exist # ============================================================================= if __name__=="__main__": assets = "../stk-assets/" shared_textures = {} readAllTextures([assets+"textures", assets+"/textures/deprecated"], shared_textures) for i in os.listdir(assets+"tracks"): checkDir(assets+"tracks/"+i+"/", shared_textures) break #for i in os.listdir(assets+"karts"): # checkDir(assets+"karts/"+i+"/", shared_textures)