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