269 lines
9.8 KiB
Python
Executable File
269 lines
9.8 KiB
Python
Executable File
import sys, os, re, glob, xml.dom.minidom, shutil, stat
|
|
from optparse import OptionParser
|
|
from sets import *
|
|
|
|
optparser = OptionParser()
|
|
optparser.add_option("", "--excludetex", dest="ExcludeTextureFile")
|
|
optparser.add_option("", "--excludemodel", dest="ExcludeModelFile")
|
|
optparser.add_option("", "--alwaysincludemodeltex", dest="IncludeModelTex", action="store_true", default=False)
|
|
optparser.add_option("", "--override", dest="OverrideDir")
|
|
|
|
(options, args) = optparser.parse_args()
|
|
|
|
if len(args) != 1:
|
|
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)
|
|
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]
|
|
|
|
ModelTextureDirectoryName = "modeltex"
|
|
|
|
ExitCode = 0
|
|
|
|
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, override):
|
|
masterDependencyList = MakeEmptySetmap()
|
|
|
|
currfxlist = originalFxList[:]
|
|
passNum = 1
|
|
while len(currfxlist) > 0:
|
|
print "Starting Pass %d" % (passNum)
|
|
depList = FindDependencies(currfxlist, override)
|
|
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, override):
|
|
global ExitCode
|
|
depList = MakeEmptySetmap()
|
|
|
|
for fx in fxlist:
|
|
depList["effectrules"].add(fx)
|
|
|
|
emitRuleList = FindTagValues("effectrules", fx, ".effectrule", "emitterRuleName", override)
|
|
depList["emitrules"].update(emitRuleList)
|
|
|
|
ptxRuleList = FindTagValues("effectrules", fx, ".effectrule", "particleRuleName", override)
|
|
depList["ptxrules"].update(ptxRuleList)
|
|
|
|
spawnedRuleList = FindTagValues("effectrules", fx, ".effectrule", "effectRuleName", override)
|
|
depList["spawnedrules"].update(spawnedRuleList)
|
|
|
|
print " Checking ptxrules"
|
|
|
|
for ptxrule in depList["ptxrules"]:
|
|
textures = FindTagValues("ptxrules", ptxrule, ".ptxrule", "textureName", override)
|
|
depList["textures"].update(textures)
|
|
|
|
shaders = FindTagValues("ptxrules", ptxrule, ".ptxrule", "shaderTemplateName", override)
|
|
depList["shaders"].update(shaders)
|
|
|
|
#drawables are a little harder to find
|
|
inDrawables = False
|
|
inSpawnEvent = False
|
|
beginDrawRE = re.compile(r'\s*<drawables>')
|
|
endDrawRE = re.compile(r'\s*</drawables>')
|
|
beginSpawnEventRE = re.compile(r'\s*<effectSpawner.+>')
|
|
endSpawnEventRE = re.compile(r'\s*</effectSpawner.+>')
|
|
nameRE = re.compile(r'\s*<name>(([^<\n])+)')
|
|
|
|
fileName = os.path.join(Path, "ptxrules", override, ptxrule + ".ptxrule")
|
|
if(os.path.exists(fileName)):
|
|
print "Found override at", fileName
|
|
else:
|
|
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))
|
|
if endDrawRE.match(line):
|
|
inDrawables = False
|
|
elif inSpawnEvent:
|
|
match = nameRE.match(line)
|
|
if match:
|
|
depList["spawnedrules"].add(match.group(1))
|
|
if endSpawnEventRE.match(line):
|
|
inSpawnEvent = False
|
|
else:
|
|
if beginDrawRE.match(line):
|
|
inDrawables = True
|
|
elif beginSpawnEventRE.match(line):
|
|
inSpawnEvent = 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, override):
|
|
global Path, ExitCode
|
|
found = []
|
|
tagRE = re.compile(r'\s*<%s>(.*)</%s>' % (tag,tag))
|
|
fileName = os.path.join(Path, folder, override, fxfile + extn)
|
|
if(os.path.exists(fileName)):
|
|
print "Found override at", fileName
|
|
else:
|
|
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)
|
|
if data != "":
|
|
found.append(os.path.basename(data))
|
|
f.close()
|
|
except (IOError):
|
|
print "Error: Couldn't open file", fileName
|
|
ExitCode = 1
|
|
return found
|
|
|
|
|
|
def writeSet(s, extn):
|
|
global FileDir, FileBase, ExitCode
|
|
sortlist = [x for x in s]
|
|
sortlist.sort()
|
|
fileName = os.path.join(FileDir, FileBase + "/" + FileBase + "." + extn)
|
|
try:
|
|
file(fileName, "w").write("\n".join(sortlist))
|
|
except (IOError):
|
|
print "Error: Couldn't open file", fileName, "for writing"
|
|
ExitCode = 1
|
|
|
|
###########################################################
|
|
###########################################################
|
|
###########################################################
|
|
|
|
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, options.OverrideDir)
|
|
|
|
# remove any models that are in the exclude lists
|
|
depList["models"] -= excludeModels
|
|
|
|
# remove any textures that are in the exclude lists
|
|
depList["textures"] -= excludeTextures
|
|
|
|
# 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)
|
|
svaFile.close()
|
|
|
|
if not options.IncludeModelTex:
|
|
# remove any of the newly added model textures that are in the exclude lists
|
|
depList["textures"] -= excludeTextures
|
|
|
|
try:
|
|
os.makedirs(os.path.join(FileDir, FileBase))
|
|
except OSError:
|
|
pass
|
|
|
|
# finally write all the lists
|
|
writeSet(initialFxList, "fxlist")
|
|
writeSet(depList["effectrules"], "effectlist")
|
|
writeSet(depList["emitrules"], "emitlist")
|
|
writeSet(depList["ptxrules"], "ptxlist")
|
|
writeSet(depList["models"], "modellist")
|
|
writeSet(depList["textures"], "texlist")
|
|
|
|
#writeSet(depList["shaders"], "shaderlist")
|
|
|
|
sys.exit(ExitCode)
|