stk-code_catmod/tools/check_textures.py
marjorieB 840771d189
Migration Python2 towards Python3 (#4232)
The modified code stays compatible with Python2.
2020-02-15 14:33:25 +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)