269 lines
9.9 KiB
Python
Executable File
269 lines
9.9 KiB
Python
Executable File
import sys, os, re, glob, xml.dom.minidom, shutil, stat, hashlib
|
|
from optparse import OptionParser
|
|
from sets import *
|
|
|
|
usage = "usage: %prog in.fxlist [c:/outputpath/]"
|
|
optparser = OptionParser(usage=usage)
|
|
optparser.add_option("", "--excludetex", dest="ExcludeTextureFile")
|
|
optparser.add_option("", "--excludemodel", dest="ExcludeModelFile")
|
|
|
|
(options, args) = optparser.parse_args()
|
|
|
|
if ((len(args) != 1) and (len(args) != 2)):
|
|
optparser.error("Incorrect number of arguments.")
|
|
|
|
def GetLineSet(filename):
|
|
s = Set()
|
|
if not filename:
|
|
return s
|
|
f = file(filename)
|
|
for line in f:
|
|
l = line.strip()
|
|
if len(l) == 0 or l[0] == '#':
|
|
continue
|
|
s.add(l.lower())
|
|
return s
|
|
|
|
excludeTextures = GetLineSet(options.ExcludeTextureFile)
|
|
excludeModels = GetLineSet(options.ExcludeModelFile)
|
|
|
|
effectRuleList = []
|
|
emitRuleList = []
|
|
ptxRuleList = []
|
|
|
|
FxFileName = os.path.abspath(sys.argv[1])
|
|
FileDir = os.path.dirname(FxFileName)
|
|
Path = os.path.dirname(FileDir)
|
|
FileBase = os.path.splitext(os.path.basename(FxFileName))[0]
|
|
if (len(args) == 1):
|
|
OutputFileDir = os.path.join(FileDir, FileBase)
|
|
if (len(args) == 2):
|
|
OutputFileDir = os.path.abspath(sys.argv[2])
|
|
|
|
ModelTextureDirectoryName = "modeltex"
|
|
|
|
ExitCode = 0
|
|
|
|
ChecksumString = ""
|
|
|
|
def MakeEmptySetmap():
|
|
return {
|
|
"textures": Set(),
|
|
"shaders": Set(),
|
|
"models": Set(),
|
|
"emitrules": Set(),
|
|
"ptxrules": Set(),
|
|
"effectrules": Set(),
|
|
"spawnedrules": Set()
|
|
}
|
|
|
|
# procedure:
|
|
# Start with initial FxList, find all referenced textures, shaders, models, etc.
|
|
# also gather list of effectrules spawned from effect or ptx rules.
|
|
# take that list, remove any effects that were in the master fxlist
|
|
# repeat until nothing is left in the spawned list.
|
|
|
|
def FindAllDependencies(originalFxList):
|
|
masterDependencyList = MakeEmptySetmap()
|
|
|
|
currfxlist = originalFxList[:]
|
|
passNum = 1
|
|
while len(currfxlist) > 0:
|
|
print "Starting Pass %d" % (passNum)
|
|
depList = FindDependencies(currfxlist)
|
|
for i in ["textures", "shaders", "models", "emitrules", "ptxrules", "effectrules"]:
|
|
# add all the new dependencies to the master list
|
|
masterDependencyList[i].update(depList[i])
|
|
# now find out which of the spawned effects we haven't seen before...
|
|
newSpawns = depList["spawnedrules"].difference(masterDependencyList["effectrules"])
|
|
print "Finished Pass %d with %d effectrules" % (passNum, len(currfxlist))
|
|
currfxlist = [x for x in newSpawns]
|
|
passNum += 1
|
|
return masterDependencyList
|
|
|
|
|
|
def FindDependencies(fxlist):
|
|
global ExitCode
|
|
depList = MakeEmptySetmap()
|
|
|
|
for fx in fxlist:
|
|
depList["effectrules"].add(fx.lower())
|
|
|
|
emitRuleList = FindTagValues("effectrules", fx, ".effectrule", "EmitRuleName")
|
|
depList["emitrules"].update(emitRuleList)
|
|
|
|
ptxRuleList = FindTagValues("effectrules", fx, ".effectrule", "PtxRuleName")
|
|
depList["ptxrules"].update(ptxRuleList)
|
|
|
|
spawnedRuleList = FindTagValues("effectrules", fx, ".effectrule", "EffectName")
|
|
depList["spawnedrules"].update(spawnedRuleList)
|
|
|
|
print " Checking ptxrules"
|
|
|
|
for ptxrule in depList["ptxrules"]:
|
|
textures = FindTagValues("ptxrules", ptxrule, ".ptxrule", "TextureName")
|
|
depList["textures"].update(textures)
|
|
|
|
shaders = FindTagValues("ptxrules", ptxrule, ".ptxrule", "ShaderName")
|
|
depList["shaders"].update(shaders)
|
|
|
|
#drawables are a little harder to find
|
|
inDrawables = False
|
|
inSpawnEffect = False
|
|
beginDrawRE = re.compile(r'\s*<Drawables>')
|
|
endDrawRE = re.compile(r'\s*</Drawables>')
|
|
beginSpawnEffectRE = re.compile(r'\s*<SpawnEffect.>')
|
|
endSpawnEffectRE = re.compile(r'\s*</SpawnEffect.>')
|
|
nameRE = re.compile(r'\s*<Name>(([^<\n])+)')
|
|
fileName = os.path.join(Path, "ptxrules", ptxrule + ".ptxrule")
|
|
try:
|
|
f = file(fileName, "r")
|
|
for line in f:
|
|
if inDrawables:
|
|
match = nameRE.match(line)
|
|
if match:
|
|
depList["models"].add(match.group(1).lower())
|
|
if endDrawRE.match(line):
|
|
inDrawables = False
|
|
elif inSpawnEffect:
|
|
match = nameRE.match(line)
|
|
if match:
|
|
depList["spawnedrules"].add(match.group(1).lower())
|
|
if endSpawnEffectRE.match(line):
|
|
inSpawnEffect = False
|
|
else:
|
|
if beginDrawRE.match(line):
|
|
inDrawables = True
|
|
elif beginSpawnEffectRE.match(line):
|
|
inSpawnEffect = True
|
|
f.close()
|
|
except (IOError):
|
|
print "Error: Couldn't open file", fileName
|
|
ExitCode = 1
|
|
|
|
print " Found %d emitrules, %d ptxrules, %d spawned effects" % (len(depList["emitrules"]), len(depList["ptxrules"]), len(depList["spawnedrules"]))
|
|
return depList
|
|
|
|
|
|
def FindTagValues(folder, fxfile, extn, tag):
|
|
global Path, ExitCode
|
|
found = []
|
|
tagRE = re.compile(r'\s*<%s>(.*)</%s>' % (tag,tag))
|
|
fileName = os.path.join(Path, folder, fxfile + extn)
|
|
try:
|
|
f = file(fileName, "r")
|
|
for line in f:
|
|
match = tagRE.match(line)
|
|
if match:
|
|
data = match.group(1)
|
|
found.append(os.path.basename(data).lower())
|
|
f.close()
|
|
except (IOError):
|
|
print "Error: Couldn't open file", fileName
|
|
ExitCode = 1
|
|
return found
|
|
|
|
|
|
def writeSet(s, extn, baseDir, baseExtn):
|
|
global FileDir, FileBase, ExitCode, OutputFileDir, ChecksumString, Path
|
|
sortlist = [x for x in s]
|
|
sortlist.sort()
|
|
fileName = os.path.join(OutputFileDir, FileBase + "." + extn)
|
|
try:
|
|
file(fileName, "w").write("\n".join(sortlist))
|
|
except (IOError):
|
|
print "Error: Couldn't open file", fileName, "for writing"
|
|
ExitCode = 1
|
|
if baseDir:
|
|
# build up our checksum string here
|
|
for filename in sortlist:
|
|
ChecksumString += "%s/%s\t%s\n" % (baseDir, filename, os.path.getmtime(os.path.join(Path, baseDir, filename + "." + baseExtn)))
|
|
|
|
###########################################################
|
|
###########################################################
|
|
###########################################################
|
|
|
|
try:
|
|
mainFile = file(FxFileName, "r")
|
|
except (IOError):
|
|
print "Error: Couldn't open fxlist file", FxFileName
|
|
sys.exit(1)
|
|
|
|
initialFxList = []
|
|
for i in mainFile:
|
|
fxName = i.strip()
|
|
if len(fxName) == 0 or fxName[0] == '#':
|
|
continue
|
|
initialFxList.append(fxName)
|
|
|
|
depList = FindAllDependencies(initialFxList)
|
|
|
|
# remove any models that are in the exclude lists
|
|
depList["models"] -= excludeModels
|
|
|
|
# now add all the textures referenced by the models in the modellist to the texlist (copy them to the modeltex folder too)
|
|
try:
|
|
os.makedirs(os.path.join(Path, ModelTextureDirectoryName))
|
|
except OSError:
|
|
pass
|
|
for modelName in depList["models"]:
|
|
modelDirPart = os.path.split(modelName.strip())[0]
|
|
modelDir = os.path.join(Path, "models", modelDirPart)
|
|
svaList = glob.glob(os.path.join(modelDir, "*.sva"))
|
|
svaList += glob.glob(os.path.join(modelDir, "*.type"))
|
|
for svaFileName in svaList:
|
|
svaFile = None
|
|
try:
|
|
svaFile = file(svaFileName, "r")
|
|
except (IOError):
|
|
print "Error: Couldn't open file", svaFileName
|
|
ExitCode = 1
|
|
continue
|
|
for svaLine in svaFile:
|
|
toks = svaLine.strip().split()
|
|
if len(toks) == 2 and toks[0] == "grcTexture":
|
|
rawTextureName = toks[1]
|
|
textureName = os.path.splitext(rawTextureName)[0]
|
|
srcTextureName = os.path.join(modelDir, textureName + ".dds")
|
|
dstTextureName = os.path.join(Path, ModelTextureDirectoryName, textureName + ".dds")
|
|
if os.path.exists(dstTextureName) and os.path.getmtime(srcTextureName) != os.path.getmtime(dstTextureName):
|
|
print "overwriting %s with %s" % (dstTextureName, srcTextureName)
|
|
try:
|
|
os.chmod(dstTextureName, stat.S_IWRITE)
|
|
shutil.copy2(srcTextureName, dstTextureName)
|
|
except:
|
|
print "Error: Failed to overwrite %s" % (dstTextureName)
|
|
elif not os.path.exists(dstTextureName):
|
|
print "copying to %s from %s" % (dstTextureName, srcTextureName)
|
|
try:
|
|
shutil.copy2(srcTextureName, dstTextureName)
|
|
except:
|
|
print "Error: Failed to copy %s to %s" % (srcTextureName, dstTextureName)
|
|
depList["textures"].add(rawTextureName.lower())
|
|
svaFile.close()
|
|
|
|
# remove any textures that are in the exclude lists
|
|
depList["textures"] -= excludeTextures
|
|
|
|
try:
|
|
os.makedirs(OutputFileDir)
|
|
except OSError:
|
|
pass
|
|
|
|
# finally write all the lists
|
|
writeSet(depList["textures"], "texlist", "textures", "dds")
|
|
writeSet(depList["shaders"], "shaderlist", None, None)
|
|
writeSet(depList["models"], "modellist", "models", "type")
|
|
writeSet(depList["emitrules"], "emitlist", "emitrules", "emitrule")
|
|
writeSet(depList["ptxrules"], "ptxlist", "ptxrules", "ptxrule")
|
|
writeSet(depList["effectrules"], "fullfxlist", "effectrules", "effectrule")
|
|
writeSet(initialFxList, "fxlist", None, None)
|
|
|
|
hash = hashlib.md5(ChecksumString).hexdigest()
|
|
checksumFile = file(os.path.join(OutputFileDir, "checksum.txt"), "w").write(hash)
|
|
|
|
# finally finally generate a checksum
|
|
|
|
|
|
sys.exit(ExitCode)
|