stk-code_catmod/tools/check_textures.py
2016-11-11 09:06:06 +08:00

199 lines
6.1 KiB
Python
Executable File

#!/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)