#!/usr/bin/python import os import string import sys import re import glob import scriptutil #from DebugMessage import stdMsg, dbgMsg, errMsg, setDebugging LOGFILE="reorg_logfile.txt" #SrcPath="/cygdrive/d/Home/cygwin/gruberg/darkmod" #DstPath="/cygdrive/d/Home/cygwin/gruberg/darkmod_reorg" SrcPath="/home/sparhawk/darkmod" DstPath="/home/sparhawk/darkmod_reorg" material_list = {} class MaterialLine: def __init__(self): self.LineNumber = -1 self.Type = 'l' self.Indentation = 0 self.Text = "" def __repr__(self): return "[ " + self.LineNumber.__repr__() + ", '" + self.Type + "', " + self.Indentation.__repr__() + ", '" + self.Text + "' ]" class Material: def __init__(self, name): self.Filename = name self.Modified = 0 self.Buffer = None self.Line = [] self.CacheFile() def __repr__(self): return "[ '"+self.Filename+"', "+self.Modified.__repr__()+", "+len(self.Line).__repr__()+" ]" def CacheFile(self): f = open(SrcPath+"/"+self.Filename) self.Buffer = f.read() f.close() b = self.Buffer.split("\n") last = None r = MaterialLine() ind = 0 prevind = 0 nr = 0 for l in b: t = l.split("\r") if(len(t) > 1): l = t[0] s = l.strip() if s[0:1] == '{': ind = ind + 1 elif s[0:1] == '}': ind = ind - 1 nr = nr + 1 r.Indentation = ind r.Text = l r.LineNumber = nr # Check if we have found a material name if ind == 1 and prevind == 0: last.Type = 'n' self.Line.append(r) last = r r = MaterialLine() prevind = ind return class Texture: def __init__(self): self.TextureName = "" self.TextureExt = "" self.TextureMaterial = "" self.TexturePath = "" def __repr__(self): return "['"+self.TexturePath+"', '" +self.TextureName + "', '" + self.TextureExt + "', " + self.TextureMaterial +"']" class TextureRecord: def __init__(self): self.mNew = Texture() self.mOld = Texture() self.MaterialFilename = {} def __repr__(self): mat = "" if self.MaterialFilename == None: mat = "None" else: for i in self.MaterialFilename: mat += "'"+i+"', " mat = mat[0:len(mat)-2] return "[* "+mat + "\n **" + self.mOld.__repr__() + "\n **" + self.mNew.__repr__()+" *]\n" class TextureReorg: def __init__(self, Logfile, SrcPath, DstPath, InputFile): self.mLogFile = self.OpenFile(Logfile, "w+b") self.mInput = self.OpenFile(InputFile, "r+b") self.mSrcPath = SrcPath self.mDstPath = DstPath self.TextureRecord = [] self.MaterialFile = {} self.CacheMaterials() try: os.mkdir(DstPath + "/textures") except OSError: pass try: os.mkdir(DstPath + "/dds") except OSError: pass try: os.mkdir(DstPath + "/dds/textures") except OSError: pass try: os.mkdir(DstPath + "/materials") except OSError: pass def CacheMaterials(self): print "Caching material files..." name = glob.glob(SrcPath+"/materials/*") for i in name: i = i.split(SrcPath+"/")[1] t = i.split("replacements.txt") if(len(t) > 1): continue t = i.split("gildoran_notes.txt") if(len(t) > 1): continue #print i self.MaterialFile[i] = Material(i) return def OpenFile(self, name, mode): try: fl = file(name, mode) except IOError: print "Couldn't open "+name sys.exit(1) return fl def ParseInput(self): bSVN = 0 bDir = 0 dir = [] path = "" while 1: ln = self.mInput.readline() if not ln: break ln = ln.strip() if(len(ln) == 0): continue if(len(ln.split("Volume")) > 1): continue if(len(ln.split("File(s)")) > 1): continue if(len(ln.split("Total Files Listed:")) > 1): continue if(len(ln.split("Dir(s)")) > 1): continue if(len(ln.split("")) > 1): continue # We need to get all directory names ... t = ln.split("Directory of") if(len(t) > 1): bSVN = 0 bDir = 1 # ... but only if it's not part of SVN if(len(ln.split(".svn")) > 1): bSVN = 1 if(bSVN == 1): continue if(bDir == 1): bDir = 0 if(len(dir) != 0): self.TextureRecord.append(dir) path = (t[1].strip().replace("\\", "/").split("D:/temp2/")[1]).strip() try: os.mkdir(DstPath + "/" + path) os.mkdir(DstPath + "/dds/" + path) except OSError: pass #print path dir = [] continue t = ln[39:] v = t.split(".") record = TextureRecord() record.mNew.TexturePath = path if(len(v) == 2): #print "Texture has only one name:"+t record.mNew.TextureName = v[0].strip() record.mNew.TextureExt = v[1].strip() record.mOld.TextureName = v[0].strip() record.mOld.TextureExt = v[1].strip() elif(len(v) == 4): record.mOld.TextureName = v[2].strip() record.mOld.TextureExt = v[3].strip() record.mNew.TextureName = v[0].strip() record.mNew.TextureExt = v[1].strip() else: print "Wrong number of arguments: "+ln dir.append(record) m = self.TextureMaterial(record.mOld.TextureName, record.MaterialFilename) if(m == None): record.MaterialFilename = {} print "No material: ["+ path +"] "+record.mOld.TextureName, t self.mInput.close() def SearchTexture(self, path, texname): rc = None flist = scriptutil.ffind(path, namefs=(lambda s: '.svn' not in s, lambda s: texname in s,)) #print len(flist), flist, path, texname if len(flist) == 1: rc = flist[0] elif len(flist) > 1: print "File ["+texname+"] in more then one directory!", flist return rc def Exists(self, matarray, matname): b = 0; for i in matarray: if(matname == i): #print matname + " Exists", matarray b = 1 break return b def TextureMaterial(self, tname, matarray): rc = None for n in self.MaterialFile: m = self.MaterialFile[n] t = m.Buffer.split(tname) if(len(t) > 1): matarray[n] = m rc = m return rc def ReplaceTexture(self, mat, oname, nname, record): rc = 0 if oname == nname: return rc m = self.MaterialFile[mat] ind = 0 for l in m.Line: if(l.Type == 'n'): ind = l.LineNumber-1 continue # Only check lins where the indentation is not 0 # as this definitely can not be a valid textureline if(l.Indentation > 0): # Check if the texture is contained in that # material line and if it is the real name. # We have to check for the real name because # otherwise partial names would also match # which causes wrong entries. t = l.Text.split(oname) if(len(t) > 1): if(len(t[1]) == 0 or t[1][0] == '.'): sl = "textures/" p = t[0].split(sl) if(len(p) == 1): p = t[0].split("textures\\") if(len(p) == 1): sl = "models/" p = t[0].split(sl) if(len(p) == 1): p = t[0].split("models\\") t = p[1] t = t[0:len(t)-1].replace("\\", "/") record.mOld.TexturePath = sl+t # Update the line in the material with the new texturepath l.Text = p[0]+record.mNew.TexturePath+"/"+nname m.Modified = m.Modified+1 rc = 1 #print "Updating material: "+mat,m.Line[ind].Text, oname, nname, rc list = {} try: list = material_list[mat] except KeyError: list = {} material_list[mat] = list namelist = [] try: namelist = list[m.Line[ind].Text] except KeyError: namelist = {} list[m.Line[ind].Text] = namelist namelist[oname] = nname return rc def DumpMaterial(self, name): #print "Material: "+name m = self.MaterialFile[name] if(m.Modified == 0): return #print "Updating: "+DstPath+"/"+name fl = self.OpenFile(DstPath+"/"+name, "w+b") for i in m.Line: fl.write(i.Text+"\n") fl.close() return def ProcessReorg(self): for dir in self.TextureRecord: for record in dir: for matname in record.MaterialFilename: self.ReplaceTexture(matname, record.mOld.TextureName, record.mNew.TextureName, record) for n in self.MaterialFile: self.DumpMaterial(n) return def CreateUnusedTextureMaterials(self): fl = self.OpenFile(DstPath+"/materials/"+"unknown.mtr", "w+b") fl.write("# This file was automatically created by sparhawk for the texture reorganization\n") fl.write("# materials here should be reviewed and then copied to the appropriate file.\n\n\n") for dir in self.TextureRecord: for record in dir: if(len(record.MaterialFilename) == 0): fl.write(record.mNew.TexturePath+"/"+record.mNew.TextureName+"\n") fl.write("{\n") fl.write(" diffusemap "+record.mNew.TexturePath+"/"+record.mNew.TextureName+"\n") fl.write(" {\n") fl.write(" if ( parm11 > 0 )\n") fl.write(" blend gl_dst_color, gl_one\n") fl.write(" map _white.tga\n") fl.write(" rgb 0.40 * parm11\n") fl.write(" }\n") fl.write(" {\n") fl.write(" if ( parm11 > 0 )\n") fl.write(" blend add\n") fl.write(" map "+record.mNew.TexturePath+"/"+record.mNew.TextureName+"\n") fl.write(" rgb 0.15 * parm11\n") fl.write(" }\n") fl.write("}\n\n\n") fl.close() return def SearchTexturePath(self, tname): rc = None p1 = scriptutil.ffind(SrcPath+"/textures", namefs=(lambda s: '.svn' not in s, lambda s: tname in s,)) p2 = scriptutil.ffind(SrcPath+"/dds/textures", namefs=(lambda s: '.svn' not in s, lambda s: tname in s,)) path = p1 + p2 if(len(path) == 0): print "No texturefile found: "+tname elif(len(path) > 1): for i in path: t = i.split(tname) if(len(t[1]) == 0 or t[1][0] == '.'): rc = [i] break if(rc == None): print "Multiple textures found: ", path else: rc = path return rc def CopyTextures(self): for dir in self.TextureRecord: for record in dir: sname = SrcPath+"/"+record.mOld.TexturePath+"/"+record.mOld.TextureName+"."+record.mOld.TextureExt if(len(record.mOld.TexturePath) == 0): if(self.SearchTexturePath(record.mOld.TextureName) == None): print "No valid path for: "+record.mOld.TextureName continue tname = DstPath+"/"+record.mNew.TexturePath+"/"+record.mNew.TextureName+"."+record.mNew.TextureExt b = None try: sfl = file(sname, "r+b") b = sfl.read() except IOError: try: sname = SrcPath+"/dds/"+record.mOld.TexturePath+"/"+record.mOld.TextureName+"."+record.mOld.TextureExt tname = DstPath+"/dds/"+record.mNew.TexturePath+"/"+record.mNew.TextureName+"."+record.mNew.TextureExt sfl = file(sname, "r+b") b = sfl.read() except IOError: path = self.SearchTexturePath(record.mOld.TextureName) if(path == None): print "path lookup failed, giving up: ", record.mOld.TextureName continue try: sname = path[0] sfl = file(sname, "r+b") b = sfl.read() except IOError: print "Couldn't open target: "+sname continue try: tfl = file(tname, "w+b") tfl.write(b) except IOError: print "Couldn't open target: "+tname sfl.close() continue sfl.close() tfl.close() print "svn move " + sname.split(SrcPath+"/")[1] + " " + tname.split(DstPath+"/")[1] return if __name__ == '__main__': if len(sys.argv) <= 1: print "USAGE: reorg Inputfile" sys.exit(1) reorg = TextureReorg(LOGFILE, SrcPath, DstPath, sys.argv[1]) reorg.ParseInput() reorg.ProcessReorg() reorg.CreateUnusedTextureMaterials() reorg.CopyTextures() for n in material_list: print "\n"+n ml = material_list[n] for n in ml: print " "+n names = ml[n] for old in names: print " ", old, names[old] print sys.exit(0)