check_textures.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #!/usr/bin/env python
  2. import os
  3. import re
  4. import struct
  5. # Reads all texture names from the specified directory.
  6. # Textures must end in jpg, png, or bmp.
  7. # Returns a directory with the texture name as key.
  8. def readAllTextures(dir, result):
  9. if type(dir)==type([]):
  10. for i in dir:
  11. readAllTextures(i,result)
  12. return
  13. re_is_texture = re.compile("^.*\.(jpg|png|bmp)$")
  14. for i in os.listdir(dir):
  15. if re_is_texture.match(i):
  16. result[i]=1
  17. # -----------------------------------------------------------------------------
  18. # Reads all texture names specified in a materials.xml file.
  19. def readMaterialsXML(filename):
  20. textures = {}
  21. f = open(filename, "r")
  22. # Crude RE instead of XML parsing
  23. re_texture_name = re.compile("^ *<material name=\"([^\"]*)\"")
  24. for i in f.readlines():
  25. g = re_texture_name.match(i)
  26. if g:
  27. textures[g.groups(1)[0]] = 1
  28. return textures
  29. # -----------------------------------------------------------------------------
  30. def getTexturesFromB3D(filename, textures):
  31. f = open(filename, "r")
  32. s = f.read(4)
  33. if s!="BB3D":
  34. print(filename,"is not a valid b3d file")
  35. f.close()
  36. return
  37. start_texs = 12
  38. f.seek(start_texs)
  39. s = f.read(4)
  40. if s!="TEXS":
  41. print("Can not handle '%s' b3d file - ignored."%filename)
  42. f.close()
  43. return
  44. n = struct.unpack("<i", f.read(4))[0] # Read end of section
  45. n = n - start_texs - 4 # number of bytes to read in tex section
  46. s = f.read(n)
  47. i = 0
  48. while i<n:
  49. tex_name=""
  50. while ord(s[i]):
  51. tex_name = tex_name+s[i]
  52. i=i+1
  53. textures[tex_name] = 1
  54. # Update the offst: add 1 byte string terminator,
  55. # and 7 int/float values
  56. i = i + 7*4 + 1
  57. f.close()
  58. return
  59. # -----------------------------------------------------------------------------
  60. # Reads all textures mentioned in a track.xml or kart.xml file (e.g. icons,
  61. # screenshots, shadows)
  62. def findTrackData(dir, textures, b3dfiles):
  63. f = open(dir+"track.xml", "r")
  64. if f:
  65. r_screenshot = re.compile("^ *screenshot *= \"(.*)\" *$")
  66. for i in f.readlines():
  67. g = r_screenshot.match(i)
  68. if g:
  69. textures[g.group(1)] = 1
  70. f.close()
  71. f = open(dir+"scene.xml", "r")
  72. if f:
  73. r_model = re.compile(" model=\"((.*)\.b3d.?)\"")
  74. for i in f.readlines():
  75. g = r_model.search(i)
  76. if g:
  77. b3dfiles[g.groups(1)[0]] = 1
  78. f.close()
  79. # -----------------------------------------------------------------------------
  80. def findKartData(dir, textures, b3dfiles):
  81. f = open(dir+"scene.xml", "r")
  82. if f:
  83. r_model = re.compile(" model=\"((.*)\.b3d.?)\"")
  84. for i in f.readlines():
  85. g = r_model.search(i)
  86. if g:
  87. b3dfiles[g.groups(1)[0]] = 1
  88. f.close()
  89. return
  90. else:
  91. f = open(dir+"scene.xml", "r")
  92. if not f: return
  93. print("WARNING")
  94. if 1:
  95. print("WARNING - kart.xml not done yet")
  96. f = open(dir+"kart.xml", "r")
  97. if not f: return
  98. r_screenshot = re.compile("^ *screenshot *= \"(.*)\" *$")
  99. for i in f.readlines():
  100. g = r_screenshot.match(i)
  101. if g:
  102. textures[g.group(1)] = 1
  103. f.close()
  104. return
  105. # -----------------------------------------------------------------------------
  106. # Checks if all textures for a specified track- or kart-directory
  107. # are actually used.
  108. def checkDir(dir, shared_textures):
  109. # First read all *png/jpg/bmp files
  110. # ---------------------------------
  111. existing_textures = {}
  112. readAllTextures(dir, existing_textures)
  113. # Find all b3d files in the directory (print warnings for b3dz)
  114. # -------------------------------------------------------------
  115. b3d_files_in_dir = {}
  116. for i in os.listdir(dir):
  117. if i[-4:]==".b3d":
  118. b3d_files_in_dir[i] = 1
  119. elif i[-5:]==".b3dz":
  120. print("Can't handle file '%s'."%i)
  121. # Find all textures listed in materials.xml
  122. # -----------------------------------------
  123. materials = readMaterialsXML(dir+"/materials.xml")
  124. # Find all textures in track.xml and kart.xml files
  125. # -------------------------------------------------
  126. used_textures = {}
  127. used_b3d_files = {}
  128. findTrackData(dir, used_textures, used_b3d_files)
  129. #findKartData(dir, used_textures, used_b3d_files)
  130. # 1) Check if there are any missing b3d files
  131. # ===========================================
  132. for i in used_b3d_files.keys():
  133. if not b3d_files_in_dir.get(i):
  134. print("File '%s' is missing."%(dir+i))
  135. # 2) Check if there are any unnecessary b3d files
  136. # ===============================================
  137. for i in b3d_files_in_dir:
  138. if not used_b3d_files.get(i):
  139. print("File '%s' is not used."%i)
  140. continue
  141. del used_b3d_files[i]
  142. # Load all textures used in this b3d file
  143. getTexturesFromB3D(dir+i, used_textures)
  144. # 3) Check if all textures used can be found
  145. # ==========================================
  146. for i in used_textures:
  147. if not existing_textures.get(i)==1:
  148. if not shared_textures.get(i):
  149. print("Cannot find texture '%s'."%i)
  150. continue
  151. else:
  152. del existing_textures[i]
  153. for i in existing_textures:
  154. print("Texture '%s' is not used anywhere."%(dir+i))
  155. # Now check that all entries in materials.xml are indeed used and exist
  156. # =============================================================================
  157. if __name__=="__main__":
  158. assets = "../stk-assets/"
  159. shared_textures = {}
  160. readAllTextures([assets+"textures",
  161. assets+"/textures/deprecated"],
  162. shared_textures)
  163. for i in os.listdir(assets+"tracks"):
  164. checkDir(assets+"tracks/"+i+"/", shared_textures)
  165. break
  166. #for i in os.listdir(assets+"karts"):
  167. # checkDir(assets+"karts/"+i+"/", shared_textures)