You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
6.2 KiB
226 lines
6.2 KiB
|
|
import msvcrt, os, sys, re, WildcardSearch, VisitFiles |
|
|
|
|
|
def GetArg( argName, ifAtEnd='' ): |
|
for i in range( 1, len( sys.argv ) ): |
|
if argName.upper() == sys.argv[i].upper(): |
|
if i+1 >= len( sys.argv ): |
|
return ifAtEnd |
|
else: |
|
return sys.argv[i+1] |
|
return None |
|
|
|
|
|
def PrintUsage(): |
|
print r'port_models.py -srcdir <directory with the QCs> -vproject <game directory>' |
|
print r'Note: -srcdir represents the ROOT of the models directory, but it points at the model sources' |
|
print r' instead of the model content.' |
|
print r'ex: port_models.py -srcdir c:\hl2\models\tfc -vproject c:\hl2\tfc' |
|
sys.exit( 1 ) |
|
|
|
|
|
def FixFilename( filename ): |
|
filename = filename.replace( '/', '\\' ) |
|
if filename == '.\\': |
|
return filename |
|
else: |
|
return re.compile( r'[^\.]?\.\\' ).sub( '', filename ) |
|
|
|
|
|
def GetDirName( fullFilename ): |
|
a = fullFilename.rfind( '/' ) |
|
b = fullFilename.rfind( '\\' ) |
|
if a == -1 and b == -1: |
|
return FixFilename( fullFilename ) |
|
else: |
|
return FixFilename( fullFilename[0 : max(a,b)] ) |
|
|
|
|
|
g_bAlwaysContinue = 0 |
|
def CheckContinue(): |
|
global g_bAlwaysContinue |
|
if g_bAlwaysContinue: |
|
return 1 |
|
else: |
|
sys.stdout.write( 'Continue [(Y)es/(N)o/(A)lways]? ' ) |
|
r = str( msvcrt.getch() ).upper() |
|
if r == 'Y': |
|
return 1 |
|
elif r == 'A': |
|
g_bAlwaysContinue = 1 |
|
return 1 |
|
else: |
|
return 0 |
|
|
|
|
|
# |
|
# Get command line args. |
|
# |
|
modelSourceDir = GetArg( '-srcdir' ) |
|
vprojectDir = GetArg( '-vproject' ) |
|
if not modelSourceDir or not vprojectDir: |
|
PrintUsage() |
|
|
|
binDir = vprojectDir + '\\..\\bin' |
|
|
|
studiomdlFilename = binDir + '\\studiomdl.exe' |
|
vtexFilename = binDir + '\\vtex.exe' |
|
xwadFilename = binDir + '\\xwad.exe' |
|
if not os.access( studiomdlFilename, os.F_OK ) or not os.access( vtexFilename, os.F_OK ) or not os.access( xwadFilename, os.F_OK ): |
|
print 'Can\'t find vtex.exe, xwad.exe, or studiomdl.exe in bin directory %s.' % (binDir) |
|
sys.exit( 1 ) |
|
|
|
|
|
|
|
# |
|
# |
|
# REGEX's and code to convert the QC file. |
|
# |
|
# |
|
reModelName = re.compile( r'(?P<start>\$modelname\s+)(?P<stripout>.*models(\\|\/))(?P<keep>.+)', re.IGNORECASE ) |
|
reCDTexture = re.compile( r'(?P<start>\$(cdTexture|cdmaterials)\s+)(?P<stripout>.*models(\\|\/))(?P<keep>.+)', re.IGNORECASE ) |
|
reCD = re.compile( r'\$cd\s', re.IGNORECASE ) |
|
|
|
def ident( name=None ): |
|
if name: |
|
return r'(?P<' + name + r'>\s+((\".*?\")|([^\"]\S*)))' |
|
else: |
|
return r'\s+((\".*?\")|([^\"]\S*))' |
|
|
|
reAttachmentLine = re.compile( r'(?P<keep>.*\$attachment'+ident()+ident()+ident()+ident()+ident() + ')' + ident()+ident(), re.IGNORECASE ) |
|
|
|
g_DirToMaterialsMap = {} |
|
|
|
def EditQCFile( fullFilename ): |
|
f = open( fullFilename, 'rt' ) |
|
lines = f.readlines() |
|
f.close() |
|
|
|
bDidMaterials = 0 |
|
|
|
outLines = [] |
|
for line in lines: |
|
if not reCD.search( line ): |
|
# Strip out stuff before /models in the $modelname line. |
|
m = reModelName.search( line ) |
|
if m: |
|
line = m.group('start') + m.group('keep' ) + '\n' |
|
else: |
|
m = reCDTexture.search( line ) |
|
if m: |
|
materialsDirName = 'models/' + m.group('keep') |
|
bmpDir = m.group('keep') |
|
g_DirToMaterialsMap[FixFilename(bmpDir.upper())] = materialsDirName |
|
bDidMaterials = 1 |
|
line = '$cdmaterials %s\n' % materialsDirName |
|
|
|
# Strip out the last 2 args on the $attachment line if they're using too many. |
|
# Goldsrc studiomdl allowed 2 extra args but it ignored them. |
|
m = reAttachmentLine.search( line ) |
|
if m: |
|
line = m.group('keep') |
|
|
|
outLines.append( line ) |
|
|
|
if not bDidMaterials: |
|
print 'No $cdtexture line in %s so we don\'t know where to convert the BMPs into.' % (fullFilename) |
|
sys.exit( 1 ) |
|
|
|
# |
|
# Write the QC back out. |
|
# |
|
try: |
|
f = open( fullFilename, 'wt' ) |
|
except IOError: |
|
print 'Can\'t open %s for writing.\nMake sure it is not read-only.' % fullFilename |
|
sys.exit( 1 ) |
|
f.writelines( outLines ) |
|
f.close() |
|
|
|
|
|
|
|
# |
|
# Convert all the QC files and backup the old ones. |
|
# |
|
print '--- Converting QC files and running studiomdl ---' |
|
|
|
def QCFileCallback( filename, relativeName, fullFilename ): |
|
print '\t' + relativeName |
|
|
|
# First, backup the QC. |
|
os.system( 'copy \"%s\" \"%s\" > out' % (fullFilename, fullFilename + ".OLD") ) |
|
|
|
# |
|
# Now, make some edits. |
|
# |
|
EditQCFile( fullFilename ); |
|
|
|
# |
|
# Run studiomdl on it. |
|
# |
|
cmd = '%s -vproject \"%s\" \"%s\" > out' % (studiomdlFilename, vprojectDir, fullFilename) |
|
if os.system( cmd ) != 0: |
|
lines = open( 'out', 'rt' ).readlines() |
|
sys.stdout.writelines( lines ) |
|
sys.exit( 1 ) |
|
|
|
VisitFiles.VisitFiles( modelSourceDir, WildcardSearch.GetRegExForDOSWildcard( '*.qc' ), QCFileCallback, None ) |
|
|
|
|
|
# |
|
# Now convert all the BMP files. |
|
# |
|
print '\n--- Converting BMP files and running vtex ---' |
|
def BMPFileCallback( filename, relativeName, fullFilename ): |
|
print '\t' + relativeName |
|
|
|
# Find out where we want to store this BMP's files under materials. |
|
dirName = GetDirName( relativeName ) |
|
|
|
try: |
|
cdMaterials = g_DirToMaterialsMap[dirName.upper()] |
|
except: |
|
#print '\tWarning: couldn\'t convert %s (don\'t know where to put it).' % (relativeName) |
|
pass |
|
else: |
|
# |
|
# Run XWAD. |
|
# |
|
cmd = '%s -quiet -bmpfile \"%s\" -basedir \"%s\"' % (xwadFilename, fullFilename, vprojectDir) |
|
if os.system( cmd ) != 0: |
|
print '\tError running xwad on %s' % fullFilename |
|
if not CheckContinue(): |
|
print '\tcmd: %s' % cmd |
|
sys.exit( 1 ) |
|
|
|
# |
|
# Move the TGA it generated into the right directory. |
|
# |
|
materialsrcDir = '%s\\materialsrc\\%s' % (vprojectDir, cdMaterials) |
|
if not os.access( materialsrcDir, os.F_OK ) and os.system( 'md \"%s\"' % materialsrcDir ) != 0: |
|
print 'Can\'t create or access directory %s.' % materialsrcDir |
|
|
|
materialsDir = '%s\\materials\\%s' % (vprojectDir, cdMaterials) |
|
if not os.access( materialsDir, os.F_OK ) and os.system( 'md \"%s\"' % materialsDir ) != 0: |
|
print 'Can\'t create or access directory %s.' % materialsDir |
|
|
|
baseTGAFilename = filename[0:-4] + '.tga' |
|
generatedFilename = vprojectDir + '\\materialsrc\\' + baseTGAFilename |
|
cmd = 'move \"%s\" \"%s\"' % (generatedFilename, materialsrcDir) |
|
if os.system( cmd ) != 0: |
|
print 'system( %s ) failed.' % cmd |
|
|
|
# |
|
# Lastly, run vtex on it. |
|
# |
|
cmd = '%s -shader VertexLitGeneric -quiet \"%s\\%s\"' % (vtexFilename, materialsrcDir, baseTGAFilename) |
|
if os.system( cmd ) != 0: |
|
sys.exit( 1 ) |
|
|
|
|
|
VisitFiles.VisitFiles( modelSourceDir, WildcardSearch.GetRegExForDOSWildcard( '*.bmp' ), BMPFileCallback, None ) |
|
|
|
|
|
|
|
|
|
|