From d897de13d50b38a7a89ff2903afdb52025bfe630 Mon Sep 17 00:00:00 2001 From: Garux Date: Thu, 7 Oct 2021 18:58:00 +0300 Subject: [PATCH] refactor scripts parsing --- tools/quake3/common/scriplib.h | 10 + tools/quake3/q3map2/autopk3.cpp | 219 ++++----------- tools/quake3/q3map2/convert_obj.cpp | 23 +- tools/quake3/q3map2/map.cpp | 18 +- tools/quake3/q3map2/shaders.cpp | 380 ++++++++++---------------- tools/quake3/q3map2/shaders.h | 87 ++++++ tools/quake3/q3map2/surface_extra.cpp | 18 +- 7 files changed, 291 insertions(+), 464 deletions(-) create mode 100644 tools/quake3/q3map2/shaders.h diff --git a/tools/quake3/common/scriplib.h b/tools/quake3/common/scriplib.h index 959739c0..b2b6508f 100644 --- a/tools/quake3/common/scriplib.h +++ b/tools/quake3/common/scriplib.h @@ -32,10 +32,20 @@ extern int scriptline; void LoadScriptFile( const char *filename, int index, bool verbose = true ); void ParseFromMemory( char *buffer, int size ); +/// \param[in] crossline true: write next token to \c token or return false on EOF +/// \param[in] crossline false: find next token on the current line or emit \c Error bool GetToken( bool crossline ); + +/// \brief Signals that the current token was not used, and should be reported for the next \c GetToken(). +/// Only may be used once between the \c GetToken() calls. void UnGetToken( void ); + +/// \brief +/// \return true, if there is another token on the line. bool TokenAvailable( void ); +/// \brief Parses next token and emits \c Error, if it's not equal to \p match. +/// Allowed to cross a line. void MatchToken( const char *match ); template diff --git a/tools/quake3/q3map2/autopk3.cpp b/tools/quake3/q3map2/autopk3.cpp index 3e691f7e..e948b142 100644 --- a/tools/quake3/q3map2/autopk3.cpp +++ b/tools/quake3/q3map2/autopk3.cpp @@ -29,6 +29,7 @@ #include "q3map2.h" #include "autopk3.h" +#include "shaders.h" #include @@ -208,17 +209,11 @@ struct Exclusions }; static inline void parseEXblock( StrList& list, const char *exName ){ - if ( !GetToken( true ) || !strEqual( token, "{" ) ) { + if ( !( GetToken( true ) && strEqual( token, "{" ) ) ) { Error( "ReadExclusionsFile: %s, line %d: { not found", exName, scriptline ); } - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } if ( strEqual( token, "{" ) ) { Error( "ReadExclusionsFile: %s, line %d: brace, opening twice in a row.", exName, scriptline ); } @@ -243,13 +238,8 @@ static const Exclusions parseEXfile( const char* filename ){ ParseFromMemory( (char *) buffer, size ); /* tokenize it */ - while ( 1 ) + while ( GetToken( true ) ) /* test for end of file */ { - /* test for end of file */ - if ( !GetToken( true ) ) { - break; - } - /* blocks */ if ( striEqual( token, "textures" ) ){ parseEXblock( ex.textures, filename ); @@ -386,50 +376,31 @@ int pk3BSPMain( Args& args ){ /* load the shader */ const auto scriptFile = stream( g_game->shaderPath, '/', file ); - LoadScriptFile( scriptFile, 0, dbg ); - /* tokenize it */ /* check if shader file has to be excluded */ - while ( !excludedByShader && !excludedByShaderFile ) - { - /* test for end of file */ - if ( !GetToken( true ) ) { - break; - } - - /* does it contain restricted shaders/textures? */ - if( ( excludedByShader = StrList_find( ex.shaders, token ) ) - || ( excludedByShader = StrList_find( ex.pureTextures, token ) ) ){ - break; - } - - /* handle { } section */ - if ( !GetToken( true ) ) { - break; - } - if ( !strEqual( token, "{" ) ) { - Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s", - scriptFile.c_str(), scriptline, token, g_strLoadedFileLocation ); - } - - while ( 1 ) + if( !excludedByShaderFile ){ + /* tokenize it */ + LoadScriptFile( scriptFile, 0, false ); + while ( GetToken( true ) ) { - /* get the next token */ - if ( !GetToken( true ) ) { + /* does it contain restricted shaders/textures? */ + if( ( excludedByShader = StrList_find( ex.shaders, token ) ) + || ( excludedByShader = StrList_find( ex.pureTextures, token ) ) ){ break; } - if ( strEqual( token, "}" ) ) { - break; + + /* handle { } section */ + if ( !( GetToken( true ) && strEqual( token, "{" ) ) ) { + Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s", + scriptFile.c_str(), scriptline, token, g_strLoadedFileLocation ); } - /* parse stage directives */ - if ( strEqual( token, "{" ) ) { - while ( 1 ) - { - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; + + while ( GetToken( true ) && !strEqual( token, "}" ) ) + { + /* parse stage directives */ + if ( strEqual( token, "{" ) ) { + while ( GetToken( true ) && !strEqual( token, "}" ) ) + { } } } @@ -437,13 +408,9 @@ int pk3BSPMain( Args& args ){ } /* tokenize it again */ - LoadScriptFile( scriptFile, 0, false ); - while ( 1 ) + LoadScriptFile( scriptFile, 0, dbg ); + while ( GetToken( true ) ) { - /* test for end of file */ - if ( !GetToken( true ) ) { - break; - } //dump shader names if( dbg ) Sys_Printf( "%s\n", token ); @@ -452,25 +419,14 @@ int pk3BSPMain( Args& args ){ String64 *wantShader = StrList_find( pk3Shaders, token ); /* handle { } section */ - if ( !GetToken( true ) ) { - break; - } - if ( !strEqual( token, "{" ) ) { + if ( !( GetToken( true ) && strEqual( token, "{" ) ) ) { Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s", scriptFile.c_str(), scriptline, token, g_strLoadedFileLocation ); } bool hasmap = false; - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - /* get the next token */ - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } - /* ----------------------------------------------------------------- shader stages (passes) @@ -478,14 +434,8 @@ int pk3BSPMain( Args& args ){ /* parse stage directives */ if ( strEqual( token, "{" ) ) { - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } if ( strEqual( token, "{" ) ) { Sys_FPrintf( SYS_WRN, "WARNING9: %s : line %d : opening brace inside shader stage\n", scriptFile.c_str(), scriptline ); } @@ -543,7 +493,7 @@ int pk3BSPMain( Args& args ){ /* ignore bogus paths */ if ( !strEqual( token, "-" ) && !striEqual( token, "full" ) ) { - char* const skysidestring = token + strcatQ( token, "_@@.tga", sizeof( token ) ) - 6; + char* const skysidestring = token + strcatQ( token, "_@@.tga", std::size( token ) ) - 6; for( const auto side : { "up", "dn", "lf", "rt", "bk", "ft" } ){ memcpy( skysidestring, side, 2 ); tex2list( pk3Textures, ex.textures, NULL ); @@ -842,7 +792,7 @@ int repackBSPMain( Args& args ){ //Parse Shader Files Sys_Printf( "\t\nParsing shaders....\n\n" ); - StringOutputStream shaderText( 4096 ); + ShaderTextCollector text; StringOutputStream allShaders( 1048576 ); for ( const CopiedString& file : pk3Shaderfiles ){ @@ -851,20 +801,12 @@ int repackBSPMain( Args& args ){ LoadScriptFile( scriptFile, 0, dbg ); /* tokenize it */ - while ( 1 ) + while ( text.GetToken( true ) ) /* test for end of file */ { - int line = scriptline; - /* test for end of file */ - if ( !GetToken( true ) ) { - break; - } //dump shader names if( dbg ) Sys_Printf( "%s\n", token ); - shaderText.clear(); - shaderText << token; - if ( strchr( token, '\\') != NULL ){ Sys_FPrintf( SYS_WRN, "WARNING1: %s : %s : shader name with backslash\n", file.c_str(), token ); } @@ -873,49 +815,19 @@ int repackBSPMain( Args& args ){ String64 *wantShader = StrList_find( pk3Shaders, token ); /* handle { } section */ - if ( !GetToken( true ) ) { - break; - } - if ( !strEqual( token, "{" ) ) { + if ( !( text.GetToken( true ) && strEqual( token, "{" ) ) ) { Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s", scriptFile.c_str(), scriptline, token, g_strLoadedFileLocation ); } - shaderText << "\n{"; + bool hasmap = false; - while ( 1 ) + while ( text.GetToken( true ) && !strEqual( token, "}" ) ) { - line = scriptline; - /* get the next token */ - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - shaderText << "\n}\n\n"; - break; - } /* parse stage directives */ if ( strEqual( token, "{" ) ) { - bool tokenready = false; - shaderText << "\n\t{"; - while ( 1 ) + while ( text.GetToken( true ) && !strEqual( token, "}" ) ) { - /* detour of TokenAvailable() '~' */ - if ( tokenready ) - tokenready = false; - else - line = scriptline; - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - shaderText << "\n\t}"; - break; - } - if ( strEqual( token, "{" ) ) { - shaderText << "\n\t{"; - Sys_FPrintf( SYS_WRN, "WARNING9: %s : line %d : opening brace inside shader stage\n", scriptFile.c_str(), scriptline ); - } /* skip the shader */ if ( !wantShader ) continue; @@ -923,7 +835,6 @@ int repackBSPMain( Args& args ){ /* digest any images */ if ( striEqual( token, "map" ) || striEqual( token, "clampMap" ) ) { - shaderText << "\n\t\t" << token; hasmap = true; /* get an image */ @@ -931,27 +842,21 @@ int repackBSPMain( Args& args ){ if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) { tex2list( pk3Textures, ex.textures, &rex.textures ); } - shaderText << " " << token; + text.tokenAppend(); // append token, modified by tex2list() } else if ( striEqual( token, "animMap" ) || striEqual( token, "clampAnimMap" ) ) { - shaderText << "\n\t\t" << token; hasmap = true; - GetToken( false );// skip num - shaderText << " " << token; + text.GetToken( false );// skip num while ( TokenAvailable() ){ - GetToken( false ); tex2list( pk3Textures, ex.textures, &rex.textures ); - shaderText << " " << token; + text.GetToken( false ); // append token, modified by tex2list() } - tokenready = true; } else if ( striEqual( token, "videoMap" ) ){ - shaderText << "\n\t\t" << token; hasmap = true; - GetToken( false ); - shaderText << " " << token; + text.GetToken( false ); FixDOSName( token ); if ( strchr( token, '/' ) == NULL ){ strcpy( token, stream( "video/", token ) ); @@ -964,18 +869,6 @@ int repackBSPMain( Args& args ){ else if ( striEqual( token, "mapComp" ) || striEqual( token, "mapNoComp" ) || striEqual( token, "animmapcomp" ) || striEqual( token, "animmapnocomp" ) ){ Sys_FPrintf( SYS_WRN, "WARNING7: %s : %s shader\n", wantShader->c_str(), token ); hasmap = true; - if ( line == scriptline ){ - shaderText << " " << token; - } - else{ - shaderText << "\n\t\t" << token; - } - } - else if ( line == scriptline ){ - shaderText << " " << token; - } - else{ - shaderText << "\n\t\t" << token; } } } @@ -985,50 +878,28 @@ int repackBSPMain( Args& args ){ /* skyparms */ else if ( striEqual( token, "skyParms" ) ) { - shaderText << "\n\tskyParms "; hasmap = true; /* get image base */ - GetToken( false ); - shaderText << token; + text.GetToken( false ); /* ignore bogus paths */ if ( !strEqual( token, "-" ) && !striEqual( token, "full" ) ) { - char* const skysidestring = token + strcatQ( token, "_@@.tga", sizeof( token ) ) - 6; + char* const skysidestring = token + strcatQ( token, "_@@.tga", std::size( token ) ) - 6; for( const auto side : { "up", "dn", "lf", "rt", "bk", "ft" } ){ memcpy( skysidestring, side, 2 ); tex2list( pk3Textures, ex.textures, &rex.textures ); } } /* skip rest of line */ - GetToken( false ); - shaderText << " " << token; - GetToken( false ); - shaderText << " " << token; + text.GetToken( false ); + text.GetToken( false ); } else if ( striEqualPrefix( token, "implicit" ) ){ Sys_FPrintf( SYS_WRN, "WARNING5: %s : %s shader\n", wantShader->c_str(), token ); hasmap = true; - if ( line == scriptline ){ - shaderText << " " << token; - } - else{ - shaderText << "\n\t" << token; - } } else if ( striEqual( token, "fogparms" ) ){ hasmap = true; - if ( line == scriptline ){ - shaderText << " " << token; - } - else{ - shaderText << "\n\t" << token; - } - } - else if ( line == scriptline ){ - shaderText << " " << token; - } - else{ - shaderText << "\n\t" << token; } } @@ -1045,10 +916,12 @@ int repackBSPMain( Args& args ){ wantShader = nullptr; } if ( wantShader ){ - allShaders << shaderText; + allShaders << text.text << '\n'; wantShader->clear(); } } + /* reset collector */ + text.clear(); } } /* TODO: RTCW's mapComp, mapNoComp, animmapcomp, animmapnocomp; nocompress?; ET's implicitmap, implicitblend, implicitmask */ diff --git a/tools/quake3/q3map2/convert_obj.cpp b/tools/quake3/q3map2/convert_obj.cpp index 5a1bddfc..75d400d5 100644 --- a/tools/quake3/q3map2/convert_obj.cpp +++ b/tools/quake3/q3map2/convert_obj.cpp @@ -220,36 +220,21 @@ void Convert_ReferenceLightmaps( const char* base, std::vector& lmIndices ) sprintf( shaderfile, "%s/q3map2_%s.shader", g_game->shaderPath, base ); LoadScriptFile( shaderfile, 0 ); /* tokenize it */ - while ( 1 ) + while ( GetToken( true ) ) /* test for end of file */ { - /* test for end of file */ - if ( !GetToken( true ) ) - break; - char shadername[256]; strcpy( shadername, token ); /* handle { } section */ - if ( !GetToken( true ) ) - break; - if ( !strEqual( token, "{" ) ) + if ( !( GetToken( true ) && strEqual( token, "{" ) ) ) Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s", shaderfile, scriptline, token, g_strLoadedFileLocation ); - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - /* get the next token */ - if ( !GetToken( true ) ) - break; - if ( strEqual( token, "}" ) ) - break; /* parse stage directives */ if ( strEqual( token, "{" ) ) { - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - if ( !GetToken( true ) ) - break; - if ( strEqual( token, "}" ) ) - break; if ( strEqual( token, "{" ) ) Sys_FPrintf( SYS_WRN, "WARNING9: %s : line %d : opening brace inside shader stage\n", shaderfile, scriptline ); diff --git a/tools/quake3/q3map2/map.cpp b/tools/quake3/q3map2/map.cpp index ab644d1c..6dc0f832 100644 --- a/tools/quake3/q3map2/map.cpp +++ b/tools/quake3/q3map2/map.cpp @@ -967,25 +967,13 @@ static void ParseRawBrush( bool onlyLights ){ } /* parse sides */ - while ( 1 ) + while ( GetToken( true ) && !strEqual( token, "}" ) ) { - if ( !GetToken( true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } - /* ttimo : bp: here we may have to jump over brush epairs (only used in editor) */ if ( g_brushType == EBrushType::Bp ) { - while ( 1 ) + while ( !strEqual( token, "(" ) ) { - if ( !strEqual( token, "(" ) ) { - GetToken( false ); - } - else{ - break; - } + GetToken( false ); GetToken( true ); } } diff --git a/tools/quake3/q3map2/shaders.cpp b/tools/quake3/q3map2/shaders.cpp index d91a7858..3a578247 100644 --- a/tools/quake3/q3map2/shaders.cpp +++ b/tools/quake3/q3map2/shaders.cpp @@ -30,6 +30,7 @@ /* dependencies */ #include "q3map2.h" +#include "shaders.h" @@ -845,111 +846,41 @@ shaderInfo_t *ShaderInfoForShader( const char *shaderName ){ -/* - GetTokenAppend() - ydnar - gets a token and appends its text to the specified buffer - */ +static void Parse1DMatrixAppend( ShaderTextCollector& text, int x, float *m ){ -static int oldScriptLine = 0; -static int tabDepth = 0; - -bool GetTokenAppend( char *buffer, bool crossline ){ - bool r; - int i; - - - /* get the token */ - r = GetToken( crossline ); - if ( !r || buffer == NULL || strEmpty( token ) ) { - return r; - } - - /* pre-tabstops */ - if ( token[ 0 ] == '}' ) { - tabDepth--; - } - - /* append? */ - if ( oldScriptLine != scriptline ) { - strcat( buffer, "\n" ); - for ( i = 0; i < tabDepth; i++ ) - strcat( buffer, "\t" ); - } - else{ - strcat( buffer, " " ); - } - oldScriptLine = scriptline; - strcat( buffer, token ); - - /* post-tabstops */ - if ( token[ 0 ] == '{' ) { - tabDepth++; - } - - /* return */ - return r; -} - - -void Parse1DMatrixAppend( char *buffer, int x, float *m ){ - - if ( !GetTokenAppend( buffer, true ) || !strEqual( token, "(" ) ) { + if ( !text.GetToken( true ) || !strEqual( token, "(" ) ) { Error( "Parse1DMatrixAppend(): line %d: ( not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation ); } for ( int i = 0; i < x; i++ ) { - if ( !GetTokenAppend( buffer, false ) ) { + if ( !text.GetToken( false ) ) { Error( "Parse1DMatrixAppend(): line %d: Number not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation ); } m[ i ] = atof( token ); } - if ( !GetTokenAppend( buffer, true ) || !strEqual( token, ")" ) ) { + if ( !text.GetToken( true ) || !strEqual( token, ")" ) ) { Error( "Parse1DMatrixAppend(): line %d: ) not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation ); } } - /* ParseShaderFile() parses a shader file into discrete shaderInfo_t */ static void ParseShaderFile( const char *filename ){ - int i; - shaderInfo_t *si; - char shaderText[ 8192 ]; /* ydnar: fixme (make this bigger?) */ - - - /* init */ - si = NULL; - strClear( shaderText ); + ShaderTextCollector text; /* load the shader */ LoadScriptFile( filename, 0 ); /* tokenize it */ - while ( 1 ) + while ( GetToken( true ) ) /* test for end of file */ { - /* copy shader text to the shaderinfo */ - if ( si != NULL && !strEmpty( shaderText ) ) { - strcat( shaderText, "\n" ); - si->shaderText = copystring( shaderText ); - //% if( vector3_length( si->vecs[ 0 ] ) ) - //% Sys_Printf( "%s\n", shaderText ); - } - - /* ydnar: clear shader text buffer */ - strClear( shaderText ); - - /* test for end of file */ - if ( !GetToken( true ) ) { - break; - } - /* shader name is initial token */ - si = AllocShaderInfo(); + shaderInfo_t *si = AllocShaderInfo(); /* ignore ":q3map" suffix */ if( striEqualSuffix( token, ":q3map" ) ) @@ -958,31 +889,13 @@ static void ParseShaderFile( const char *filename ){ si->shader << token; /* handle { } section */ - if ( !GetTokenAppend( shaderText, true ) ) { - break; - } - if ( !strEqual( token, "{" ) ) { - if ( si != NULL ) { - Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s\nFile location be: %s\n", - filename, scriptline, token, si->shader.c_str(), g_strLoadedFileLocation ); - } - else{ - Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nFile location be: %s\n", - filename, scriptline, token, g_strLoadedFileLocation ); - } + if ( !( text.GetToken( true ) && strEqual( token, "{" ) ) ) { + Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s\nFile location be: %s\n", + filename, scriptline, token, si->shader.c_str(), g_strLoadedFileLocation ); } - while ( 1 ) + while ( text.GetToken( true ) && !strEqual( token, "}" ) ) { - /* get the next token */ - if ( !GetTokenAppend( shaderText, true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } - - /* ----------------------------------------------------------------- shader stages (passes) ----------------------------------------------------------------- */ @@ -990,15 +903,8 @@ static void ParseShaderFile( const char *filename ){ /* parse stage directives */ if ( strEqual( token, "{" ) ) { si->hasPasses = true; - while ( 1 ) + while ( text.GetToken( true ) && !strEqual( token, "}" ) ) { - if ( !GetTokenAppend( shaderText, true ) ) { - break; - } - if ( strEqual( token, "}" ) ) { - break; - } - /* only care about images if we don't have a editor/light image */ if ( si->editorImagePath.empty() && si->lightImagePath.empty() && si->implicitImagePath.empty() ) { /* digest any images */ @@ -1010,11 +916,11 @@ static void ParseShaderFile( const char *filename ){ striEqual( token, "mapNoComp" ) ) { /* skip one token for animated stages */ if ( striEqual( token, "animMap" ) || striEqual( token, "clampAnimMap" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); } /* get an image */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) { si->lightImagePath( PathExtensionless( token ) ); @@ -1033,7 +939,7 @@ static void ParseShaderFile( const char *filename ){ /* match surfaceparm */ else if ( striEqual( token, "surfaceparm" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !ApplySurfaceParm( token, &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) ) { Sys_Warning( "Unknown surfaceparm: \"%s\"\n", token ); } @@ -1056,13 +962,13 @@ static void ParseShaderFile( const char *filename ){ /* tesssize is used to force liquid surfaces to subdivide */ else if ( striEqual( token, "tessSize" ) || striEqual( token, "q3map_tessSize" ) /* sof2 */ ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->subdivisions = atof( token ); } /* cull none will set twoSided (ydnar: added disable too) */ else if ( striEqual( token, "cull" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( striEqual( token, "none" ) || striEqual( token, "disable" ) || striEqual( token, "twosided" ) ) { si->twoSided = true; } @@ -1072,7 +978,7 @@ static void ParseShaderFile( const char *filename ){ we catch this so autosprited surfaces become point lights instead of area lights */ else if ( striEqual( token, "deformVertexes" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); /* deformVertexes autosprite(2) */ if ( striEqualPrefix( token, "autosprite" ) ) { @@ -1092,16 +998,16 @@ static void ParseShaderFile( const char *filename ){ /* get move amount */ - GetTokenAppend( shaderText, false ); amt[ 0 ] = atof( token ); - GetTokenAppend( shaderText, false ); amt[ 1 ] = atof( token ); - GetTokenAppend( shaderText, false ); amt[ 2 ] = atof( token ); + text.GetToken( false ); amt[ 0 ] = atof( token ); + text.GetToken( false ); amt[ 1 ] = atof( token ); + text.GetToken( false ); amt[ 2 ] = atof( token ); /* skip func */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); /* get base and amplitude */ - GetTokenAppend( shaderText, false ); base = atof( token ); - GetTokenAppend( shaderText, false ); amp = atof( token ); + text.GetToken( false ); base = atof( token ); + text.GetToken( false ); amp = atof( token ); /* calculate */ si->minmax.mins = amt * base; @@ -1111,23 +1017,23 @@ static void ParseShaderFile( const char *filename ){ /* light (old-style flare specification) */ else if ( striEqual( token, "light" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->flareShader = g_game->flareShader; } /* ydnar: damageShader (sof2 mods) */ else if ( striEqual( token, "damageShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->damageShader = copystring( token ); } - GetTokenAppend( shaderText, false ); /* don't do anything with health */ + text.GetToken( false ); /* don't do anything with health */ } /* ydnar: enemy territory implicit shaders */ else if ( striEqual( token, "implicitMap" ) ) { si->implicitMap = EImplicitMap::Opaque; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( strEqual( token, "-" ) ) { si->implicitImagePath = si->shader; } @@ -1138,7 +1044,7 @@ static void ParseShaderFile( const char *filename ){ else if ( striEqual( token, "implicitMask" ) ) { si->implicitMap = EImplicitMap::Masked; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( strEqual( token, "-" ) ) { si->implicitImagePath = si->shader; } @@ -1149,7 +1055,7 @@ static void ParseShaderFile( const char *filename ){ else if ( striEqual( token, "implicitBlend" ) ) { si->implicitMap = EImplicitMap::Blend; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( strEqual( token, "-" ) ) { si->implicitImagePath = si->shader; } @@ -1165,26 +1071,26 @@ static void ParseShaderFile( const char *filename ){ /* qer_editorimage */ else if ( striEqual( token, "qer_editorImage" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->editorImagePath( PathExtensionless( token ) ); } /* ydnar: q3map_normalimage (bumpmapping normal map) */ else if ( striEqual( token, "q3map_normalImage" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->normalImagePath( PathExtensionless( token ) ); } /* q3map_lightimage */ else if ( striEqual( token, "q3map_lightImage" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightImagePath( PathExtensionless( token ) ); } /* ydnar: skyparms */ else if ( striEqual( token, "skyParms" ) ) { /* get image base */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); /* ignore bogus paths */ if ( !strEqual( token, "-" ) && !striEqual( token, "full" ) ) { @@ -1197,8 +1103,8 @@ static void ParseShaderFile( const char *filename ){ } /* skip rest of line */ - GetTokenAppend( shaderText, false ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); + text.GetToken( false ); } /* ----------------------------------------------------------------- @@ -1222,11 +1128,11 @@ static void ParseShaderFile( const char *filename ){ sun->style = si->lightStyle; /* get color */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->color[ 0 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->color[ 1 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->color[ 2 ] = atof( token ); if ( colorsRGB ) { @@ -1239,14 +1145,14 @@ static void ParseShaderFile( const char *filename ){ ColorNormalize( sun->color ); /* scale color by brightness */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->photons = atof( token ); /* get sun angle/elevation */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); const double a = degrees_to_radians( atof( token ) ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); const double b = degrees_to_radians( atof( token ) ); sun->direction = vector3_for_spherical( a, b ); @@ -1256,10 +1162,10 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: get sun angular deviance/samples */ if ( ext && TokenAvailable() ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->deviance = degrees_to_radians( atof( token ) ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); sun->numSamples = atoi( token ); } @@ -1283,7 +1189,7 @@ static void ParseShaderFile( const char *filename ){ /* get shader */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); //% Sys_FPrintf( SYS_VRB, "Shader %s has base shader %s\n", si->shader, token ); oldWarnImage = warnImage; warnImage = false; @@ -1312,25 +1218,25 @@ static void ParseShaderFile( const char *filename ){ surfaceModel_t& model = si->surfaceModels.emplace_back(); /* get parameters */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.model = token; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.density = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.odds = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.minScale = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.maxScale = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.minAngle = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.maxAngle = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); model.oriented = ( token[ 0 ] == '1' ); } @@ -1340,30 +1246,30 @@ static void ParseShaderFile( const char *filename ){ foliage_t& foliage = si->foliage.emplace_back(); /* get parameters */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); foliage.model = token; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); foliage.scale = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); foliage.density = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); foliage.odds = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); foliage.inverseAlpha = atoi( token ); } /* ydnar: q3map_bounce (fraction of light to re-emit during radiosity passes) */ else if ( striEqual( token, "q3map_bounce" ) || striEqual( token, "q3map_bounceScale" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->bounceScale = atof( token ); } /* ydnar/splashdamage: q3map_skyLight */ else if ( striEqual( token, "q3map_skyLight" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->skyLightValue = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->skyLightIterations = atoi( token ); /* clamp */ @@ -1373,24 +1279,24 @@ static void ParseShaderFile( const char *filename ){ /* q3map_surfacelight */ else if ( striEqual( token, "q3map_surfacelight" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->value = atof( token ); } /* q3map_lightStyle (sof2/jk2 lightstyle) */ else if ( striEqual( token, "q3map_lightStyle" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightStyle = std::clamp( atoi( token ), 0, LS_NONE ); } /* wolf: q3map_lightRGB */ else if ( striEqual( token, "q3map_lightRGB" ) ) { si->color.set( 0 ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->color[ 0 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->color[ 1 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->color[ 2 ] = atof( token ); if ( colorsRGB ) { si->color[0] = Image_LinearFloatFromsRGBFloat( si->color[0] ); @@ -1402,32 +1308,32 @@ static void ParseShaderFile( const char *filename ){ /* q3map_lightSubdivide */ else if ( striEqual( token, "q3map_lightSubdivide" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightSubdivide = atoi( token ); } /* q3map_backsplash */ else if ( striEqual( token, "q3map_backsplash" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->backsplashFraction = atof( token ) * 0.01f; - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->backsplashDistance = atof( token ); } /* q3map_floodLight */ else if ( striEqual( token, "q3map_floodLight" ) ) { /* get color */ - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightRGB[ 0 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightRGB[ 1 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightRGB[ 2 ] = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightDistance = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightIntensity = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->floodlightDirectionScale = atof( token ); if ( colorsRGB ) { si->floodlightRGB[0] = Image_LinearFloatFromsRGBFloat( si->floodlightRGB[0] ); @@ -1444,27 +1350,27 @@ static void ParseShaderFile( const char *filename ){ /* q3map_lightmapSampleSize */ else if ( striEqual( token, "q3map_lightmapSampleSize" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightmapSampleSize = atoi( token ); } /* q3map_lightmapSampleOffset */ else if ( striEqual( token, "q3map_lightmapSampleOffset" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightmapSampleOffset = atof( token ); } /* ydnar: q3map_lightmapFilterRadius */ else if ( striEqual( token, "q3map_lightmapFilterRadius" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lmFilterRadius = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lightFilterRadius = atof( token ); } /* ydnar: q3map_lightmapAxis [xyz] */ else if ( striEqual( token, "q3map_lightmapAxis" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( striEqual( token, "x" ) ) { si->lightmapAxis = g_vector3_axis_x; } @@ -1483,9 +1389,9 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: q3map_lightmapSize (for autogenerated shaders + external tga lightmaps) */ else if ( striEqual( token, "q3map_lightmapSize" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lmCustomWidth = atoi( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lmCustomHeight = atoi( token ); /* must be a power of 2 */ @@ -1500,7 +1406,7 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: q3map_lightmapBrightness N (for autogenerated shaders + external tga lightmaps) */ else if ( striEqual( token, "q3map_lightmapBrightness" ) || striEqual( token, "q3map_lightmapGamma" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->lmBrightness *= atof( token ); if ( si->lmBrightness < 0 ) { si->lmBrightness = 1.0; @@ -1509,7 +1415,7 @@ static void ParseShaderFile( const char *filename ){ /* q3map_vertexScale (scale vertex lighting by this fraction) */ else if ( striEqual( token, "q3map_vertexScale" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->vertexScale *= atof( token ); } @@ -1520,7 +1426,7 @@ static void ParseShaderFile( const char *filename ){ /* q3map_flare[Shader] */ else if ( striEqual( token, "q3map_flare" ) || striEqual( token, "q3map_flareShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->flareShader = copystring( token ); } @@ -1528,7 +1434,7 @@ static void ParseShaderFile( const char *filename ){ /* q3map_backShader */ else if ( striEqual( token, "q3map_backShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->backShader = copystring( token ); } @@ -1536,7 +1442,7 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: q3map_cloneShader */ else if ( striEqual( token, "q3map_cloneShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->cloneShader = copystring( token ); } @@ -1544,7 +1450,7 @@ static void ParseShaderFile( const char *filename ){ /* q3map_remapShader */ else if ( striEqual( token, "q3map_remapShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->remapShader = copystring( token ); } @@ -1552,7 +1458,7 @@ static void ParseShaderFile( const char *filename ){ /* q3map_deprecateShader */ else if ( striEqual( token, "q3map_deprecateShader" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); if ( !strEmpty( token ) ) { si->deprecateShader = copystring( token ); } @@ -1560,17 +1466,17 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: q3map_offset */ else if ( striEqual( token, "q3map_offset" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->offset = atof( token ); } /* ydnar: q3map_fur */ else if ( striEqual( token, "q3map_fur" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->furNumLayers = atoi( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->furOffset = atof( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->furFade = atof( token ); } @@ -1595,34 +1501,34 @@ static void ParseShaderFile( const char *filename ){ /* ydnar: gs mods: q3map_shadeAngle */ else if ( striEqual( token, "q3map_shadeAngle" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->shadeAngleDegrees = atof( token ); } /* ydnar: q3map_textureSize (substitute for q3map_lightimage derivation for terrain) */ else if ( striEqual( token, "q3map_textureSize" ) ) { - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->shaderWidth = atoi( token ); - GetTokenAppend( shaderText, false ); + text.GetToken( false ); si->shaderHeight = atoi( token ); } /* ydnar: gs mods: q3map_tcGen