diff --git a/tools/quake3/q3map2/autopk3.cpp b/tools/quake3/q3map2/autopk3.cpp index e4e18cd2..01fb5e76 100644 --- a/tools/quake3/q3map2/autopk3.cpp +++ b/tools/quake3/q3map2/autopk3.cpp @@ -107,7 +107,7 @@ static void parseBspFile( const char *bspPath, StrList& outShaders, StrList& out } for ( size_t i = 0; i < bspShaders.size(); ++i ){ - if ( drawsurfSHs[i] && !( bspShaders[i].surfaceFlags & 0x80 /* Q_SURF_NORAW */ ) ){ + if ( drawsurfSHs[i] && !( bspShaders[i].surfaceFlags & GetRequiredSurfaceParm( "nodraw"_Tstring ).surfaceFlags ) ){ // also sort out nodraw patches res2list( pk3Shaders, bspShaders[i].shader ); } } diff --git a/tools/quake3/q3map2/bsp.cpp b/tools/quake3/q3map2/bsp.cpp index 794d67f8..038d43bc 100644 --- a/tools/quake3/q3map2/bsp.cpp +++ b/tools/quake3/q3map2/bsp.cpp @@ -42,16 +42,18 @@ static void autocaulk_write(){ FILE* file = SafeOpenWrite( filename, "wt" ); - int fslime = 16; + int fslime = 0; ApplySurfaceParm( "slime", &fslime, NULL, NULL ); - int flava = 8; + int flava = 0; ApplySurfaceParm( "lava", &flava, NULL, NULL ); for ( const brush_t& b : entities[0].brushes ) { fprintf( file, "%i ", b.brushNum ); const shaderInfo_t* contentShader = b.contentShader; + const bool globalFog = ( contentShader->compileFlags & C_FOG ) + && std::all_of( b.sides.cbegin(), b.sides.cend(), []( const side_t& side ){ return side.visibleHull.empty(); } ); for( const side_t& side : b.sides ){ - if( !side.visibleHull.empty() || ( side.compileFlags & C_NODRAW ) ){ + if( !side.visibleHull.empty() || ( side.compileFlags & C_NODRAW ) || globalFog ){ fprintf( file, "-" ); } else if( contentShader->compileFlags & C_LIQUID ){ diff --git a/tools/quake3/q3map2/convert_map.cpp b/tools/quake3/q3map2/convert_map.cpp index 693edb8f..9a8b143c 100644 --- a/tools/quake3/q3map2/convert_map.cpp +++ b/tools/quake3/q3map2/convert_map.cpp @@ -337,18 +337,20 @@ static void ConvertBrush( FILE *f, int bspBrushNum, const Vector3& origin, bool fprintf( f, "\t{\n" ); } - /* find out if brush is detail */ // note: this also flags structural transparent brushes as detail, e.g. hints + /* find out if brush is detail */ int contentFlag = 0; - for( const auto& leaf : bspLeafs ){ - if( leaf.cluster >= 0 ) - for( auto id = bspLeafBrushes.cbegin() + leaf.firstBSPLeafBrush, end = id + leaf.numBSPLeafBrushes; id != end; ++id ){ - if( *id == bspBrushNum ){ - contentFlag = C_DETAIL; - break; + if( !( bspShaders[bspBrushes[bspBrushNum].shaderNum].contentFlags & GetRequiredSurfaceParm( "structural"_Tstring ).contentFlags ) ){ // sort out structural transparent brushes, e.g. hints + for( const auto& leaf : bspLeafs ){ + if( leaf.cluster >= 0 ) + for( auto id = bspLeafBrushes.cbegin() + leaf.firstBSPLeafBrush, end = id + leaf.numBSPLeafBrushes; id != end; ++id ){ + if( *id == bspBrushNum ){ + contentFlag = C_DETAIL; + break; + } } - } - if( contentFlag == C_DETAIL) - break; + if( contentFlag == C_DETAIL) + break; + } } /* iterate through build brush sides */ diff --git a/tools/quake3/q3map2/map.cpp b/tools/quake3/q3map2/map.cpp index def5dd23..61df0680 100644 --- a/tools/quake3/q3map2/map.cpp +++ b/tools/quake3/q3map2/map.cpp @@ -493,11 +493,10 @@ void SetBrushContents( brush_t& b ){ else if ( s->compileFlags & C_FOG ){ b.contentShader = s->shaderInfo; } - //playerclip - else if ( b.contentShader->contentFlags & 0x10000 ){ + else if ( b.contentShader->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ){ continue; } - else if ( s->contentFlags & 0x10000 ){ + else if ( s->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ){ b.contentShader = s->shaderInfo; } else if (!( b.contentShader->compileFlags & C_SOLID )){ diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index 6ee42e4a..0d0ebf0b 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -1841,6 +1841,22 @@ void TCModScale( tcMod_t& mod, float s, float t ); void TCModRotate( tcMod_t& mod, float euler ); bool ApplySurfaceParm( const char *name, int *contentFlags, int *surfaceFlags, int *compileFlags ); +const surfaceParm_t *GetSurfaceParm( const char *name ); + +// Encode the string as a type +template +using TemplateString = std::integer_sequence; +// Create a user defined literal operator +template +constexpr TemplateString operator""_Tstring() { return { }; } +/// \brief returns statically evaluated \c surfaceParm_t for the given name or emits \c Error +template +const surfaceParm_t &GetRequiredSurfaceParm( const TemplateString ){ + static constexpr char str[sizeof...(chars) + 1] = { chars..., '\0' }; // Recover the character data + static const surfaceParm_t *const sp = GetSurfaceParm( str ); + ENSURE( sp != nullptr ); + return *sp; +} void BeginMapShaderFile( const char *mapFile ); void WriteMapShaderFile( void ); diff --git a/tools/quake3/q3map2/shaders.cpp b/tools/quake3/q3map2/shaders.cpp index 5795e50b..62d170bf 100644 --- a/tools/quake3/q3map2/shaders.cpp +++ b/tools/quake3/q3map2/shaders.cpp @@ -202,65 +202,43 @@ void TCModRotate( tcMod_t& mod, float euler ){ +const surfaceParm_t *GetSurfaceParm( const char *name ){ + /* walk the current game's surfaceparms */ + for( const surfaceParm_t& sp : g_game->surfaceParms ) + if ( striEqual( name, sp.name ) ) + return &sp; + + /* check custom info parms */ + for ( const surfaceParm_t& sp : Span( custSurfaceParms, numCustSurfaceParms ) ) + if ( striEqual( name, sp.name ) ) + return &sp; + + return nullptr; +} + /* ApplySurfaceParm() - ydnar applies a named surfaceparm to the supplied flags */ bool ApplySurfaceParm( const char *name, int *contentFlags, int *surfaceFlags, int *compileFlags ){ - int fake; - - - /* dummy check */ - if ( name == NULL ) { - name = ""; - } - if ( contentFlags == NULL ) { - contentFlags = &fake; - } - if ( surfaceFlags == NULL ) { - surfaceFlags = &fake; - } - if ( compileFlags == NULL ) { - compileFlags = &fake; - } - - /* walk the current game's surfaceparms */ - for( const surfaceParm_t& sp : g_game->surfaceParms ) - { - /* match? */ - if ( striEqual( name, sp.name ) ) { - /* clear and set flags */ - *contentFlags &= ~( sp.contentFlagsClear ); - *contentFlags |= sp.contentFlags; - *surfaceFlags &= ~( sp.surfaceFlagsClear ); - *surfaceFlags |= sp.surfaceFlags; - *compileFlags &= ~( sp.compileFlagsClear ); - *compileFlags |= sp.compileFlags; - - /* return ok */ - return true; + if( const surfaceParm_t *sp = GetSurfaceParm( name ) ){ + /* clear and set flags */ + if( contentFlags != nullptr ){ + *contentFlags &= ~( sp->contentFlagsClear ); + *contentFlags |= sp->contentFlags; } - } - - /* check custom info parms */ - for ( const surfaceParm_t& sp : Span( custSurfaceParms, numCustSurfaceParms ) ) - { - /* match? */ - if ( striEqual( name, sp.name ) ) { - /* clear and set flags */ - *contentFlags &= ~( sp.contentFlagsClear ); - *contentFlags |= sp.contentFlags; - *surfaceFlags &= ~( sp.surfaceFlagsClear ); - *surfaceFlags |= sp.surfaceFlags; - *compileFlags &= ~( sp.compileFlagsClear ); - *compileFlags |= sp.compileFlags; - - /* return ok */ - return true; + if( surfaceFlags != nullptr ){ + *surfaceFlags &= ~( sp->surfaceFlagsClear ); + *surfaceFlags |= sp->surfaceFlags; } + if( compileFlags != nullptr ){ + *compileFlags &= ~( sp->compileFlagsClear ); + *compileFlags |= sp->compileFlags; + } + /* return ok */ + return true; } - /* no matching surfaceparm found */ return false; } @@ -659,7 +637,7 @@ void FinishShader( shaderInfo_t *si ){ } if( noob && !( si->compileFlags & C_OB ) ){ - ApplySurfaceParm( "noob", &si->contentFlags, &si->surfaceFlags, &si->compileFlags ); + ApplySurfaceParm( "noob", nullptr, &si->surfaceFlags, nullptr ); } /* set to finished */ diff --git a/tools/quake3/q3map2/surface.cpp b/tools/quake3/q3map2/surface.cpp index 5c0355f7..cd3b1993 100644 --- a/tools/quake3/q3map2/surface.cpp +++ b/tools/quake3/q3map2/surface.cpp @@ -2196,8 +2196,6 @@ void EmitFlareSurface( mapDrawSurface_t *ds ){ */ void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds ){ - int surfaceFlags, contentFlags; - /* vortex: _patchMeta support */ const bool forcePatchMeta = e->boolForKey( "_patchMeta", "patchMeta" ); @@ -2232,8 +2230,8 @@ void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds ){ } else if ( patchMeta || forcePatchMeta ) { /* patch meta requires that we have nodraw patches for collision */ - surfaceFlags = ds->shaderInfo->surfaceFlags; - contentFlags = ds->shaderInfo->contentFlags; + int surfaceFlags = ds->shaderInfo->surfaceFlags; + int contentFlags = ds->shaderInfo->contentFlags; ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, NULL ); ApplySurfaceParm( "pointlight", &contentFlags, &surfaceFlags, NULL ); diff --git a/tools/quake3/q3map2/surface_meta.cpp b/tools/quake3/q3map2/surface_meta.cpp index 1681ac80..43273ffc 100644 --- a/tools/quake3/q3map2/surface_meta.cpp +++ b/tools/quake3/q3map2/surface_meta.cpp @@ -381,7 +381,7 @@ void TriangulatePatchSurface( entity_t *e, mapDrawSurface_t *ds ){ memcpy( dsNew, ds, sizeof( *ds ) ); /* if the patch is nonsolid, then discard it */ - if ( !( ds->shaderInfo->compileFlags & C_SOLID ) ) { + if ( !( ds->shaderInfo->compileFlags & C_SOLID ) && !( ds->shaderInfo->contentFlags & GetRequiredSurfaceParm( "playerclip"_Tstring ).contentFlags ) ) { ClearSurface( ds ); }