Q2 optional brush face flags in BP, 220 mapformats

This commit is contained in:
Garux 2021-08-24 18:55:34 +03:00
parent 3129fd0bce
commit b58408344c
6 changed files with 90 additions and 157 deletions

View File

@ -31,6 +31,8 @@ enum EBrushType
{ {
eBrushTypeQuake, eBrushTypeQuake,
eBrushTypeQuake2, eBrushTypeQuake2,
eBrushTypeQuake2BP,
eBrushTypeQuake2Valve220,
eBrushTypeQuake3, eBrushTypeQuake3,
eBrushTypeQuake3BP, eBrushTypeQuake3BP,
eBrushTypeQuake3Valve220, eBrushTypeQuake3Valve220,

View File

@ -448,12 +448,12 @@ public:
if( !m_formatDetected ){ if( !m_formatDetected ){
EBrushType detectedFormat; EBrushType detectedFormat;
if ( string_equal( primitive, "brushDef" ) ) { if ( string_equal( primitive, "brushDef" ) ) {
detectedFormat = eBrushTypeQuake3BP; detectedFormat = eBrushTypeQuake2BP;
globalWarningStream() << "detectedFormat = eBrushTypeQuake3BP\n"; globalWarningStream() << "detectedFormat = eBrushTypeQuake2BP\n";
} }
else if ( string_equal( primitive, "(" ) && tokeniser.bufferContains( " [ " ) && tokeniser.bufferContains( " ] " ) ) { else if ( string_equal( primitive, "(" ) && tokeniser.bufferContains( " [ " ) && tokeniser.bufferContains( " ] " ) ) {
detectedFormat = eBrushTypeQuake3Valve220; detectedFormat = eBrushTypeQuake2Valve220;
globalWarningStream() << "detectedFormat = eBrushTypeQuake3Valve220\n"; globalWarningStream() << "detectedFormat = eBrushTypeQuake2Valve220\n";
} }
else if ( string_equal( primitive, "(" ) ) { else if ( string_equal( primitive, "(" ) ) {
detectedFormat = eBrushTypeQuake2; detectedFormat = eBrushTypeQuake2;
@ -473,10 +473,10 @@ public:
switch ( GlobalBrushCreator().getFormat() ) switch ( GlobalBrushCreator().getFormat() )
{ {
case eBrushTypeQuake2: case eBrushTypeQuake2:
case eBrushTypeQuake3Valve220: case eBrushTypeQuake2Valve220:
tokeniser.ungetToken(); // ( tokeniser.ungetToken(); // (
// fall through // fall through
case eBrushTypeQuake3BP: case eBrushTypeQuake2BP:
return GlobalBrushCreator().createBrush(); return GlobalBrushCreator().createBrush();
default: default:
break; break;

View File

@ -888,10 +888,12 @@ inline TexdefTypeId BrushType_getTexdefType( EBrushType type ){
switch ( type ) switch ( type )
{ {
case eBrushTypeQuake3BP: case eBrushTypeQuake3BP:
case eBrushTypeQuake2BP:
case eBrushTypeDoom3: case eBrushTypeDoom3:
case eBrushTypeQuake4: case eBrushTypeQuake4:
return TEXDEFTYPEID_BRUSHPRIMITIVES; return TEXDEFTYPEID_BRUSHPRIMITIVES;
case eBrushTypeValve220: case eBrushTypeValve220:
case eBrushTypeQuake2Valve220:
case eBrushTypeQuake3Valve220: case eBrushTypeQuake3Valve220:
return TEXDEFTYPEID_VALVE; return TEXDEFTYPEID_VALVE;
default: default:

View File

@ -58,8 +58,10 @@ const char* BrushType_getName( EBrushType type ){
case eBrushTypeQuake2: case eBrushTypeQuake2:
case eBrushTypeQuake3: case eBrushTypeQuake3:
return "Axial Projection"; return "Axial Projection";
case eBrushTypeQuake2BP:
case eBrushTypeQuake3BP: case eBrushTypeQuake3BP:
return "Brush Primitives"; return "Brush Primitives";
case eBrushTypeQuake2Valve220:
case eBrushTypeQuake3Valve220: case eBrushTypeQuake3Valve220:
case eBrushTypeValve220: case eBrushTypeValve220:
return "Valve 220"; return "Valve 220";
@ -348,8 +350,8 @@ public:
BrushQuake2API(){ BrushQuake2API(){
g_multipleBrushTypes = true; g_multipleBrushTypes = true;
g_brushTypes[0] = eBrushTypeQuake2; g_brushTypes[0] = eBrushTypeQuake2;
g_brushTypes[1] = eBrushTypeQuake3BP; g_brushTypes[1] = eBrushTypeQuake2BP;
g_brushTypes[2] = eBrushTypeQuake3Valve220; g_brushTypes[2] = eBrushTypeQuake2Valve220;
Brush_Construct( eBrushTypeQuake2 ); Brush_Construct( eBrushTypeQuake2 );

View File

@ -196,36 +196,22 @@ public:
} }
}; };
class Quake2FaceTokenImporter class QuakeFaceTokenImporter
{ {
Face& m_face; Face& m_face;
public: public:
Quake2FaceTokenImporter( Face& face ) : m_face( face ){ QuakeFaceTokenImporter( Face& face ) : m_face( face ){
} }
bool importTokens( Tokeniser& tokeniser ){ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
// optional face flags
// Q1: normally not present, try to load to handle 3rd party maps with them or extended format with flags
// Q2: presence determines whether flags are considered as specified (otherwise embedded .wal flags are used)
// Q3: normally present, load optionally to handle 3rd party maps without them
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) {
m_face.getShader().m_flags.m_specified = true; m_face.getShader().m_flags.m_specified = true; // enable for Q2
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Quake3FaceTokenImporter
{
Face& m_face;
public:
Quake3FaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
} }
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
@ -244,6 +230,7 @@ public:
RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
m_face.getShader().m_flags.m_specified = true; // enable for Q2
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
} }
@ -254,53 +241,18 @@ public:
} }
}; };
class QuakeFaceTokenImporter
{
Face& m_face;
public:
QuakeFaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///try to load for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Valve220FaceTokenImporter class Valve220FaceTokenImporter
{ {
Face& m_face; Face& m_face;
public: public:
Valve220FaceTokenImporter( Face& face ) : m_face( face ){ Valve220FaceTokenImporter( Face& face ) : m_face( face ){
} }
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_Valve220_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///try to load for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Quake3Valve220FaceTokenImporter
{
Face& m_face;
public:
Quake3Valve220FaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_Valve220_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_Valve220_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
m_face.getShader().m_flags.m_specified = true; // enable for Q2
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
} }
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
@ -444,53 +396,25 @@ public:
} }
}; };
class Quake2FaceTokenExporter enum class FaceExportFlags{
{ yes,
const Face& m_face; no,
public: optional
Quake2FaceTokenExporter( const Face& face ) : m_face( face ){ };
template<FaceExportFlags exportFlags>
void FaceFlags_exportTokens( const Face& face, TokenWriter& writer ){
if constexpr ( exportFlags == FaceExportFlags::yes ){
FaceShader_ContentsFlagsValue_exportTokens( face.getShader(), writer );
} }
void exportTokens( TokenWriter& writer ) const { else if constexpr ( exportFlags == FaceExportFlags::optional ){
FacePlane_exportTokens( m_face.getPlane(), writer ); if ( face.getShader().m_flags.m_specified || face.isDetail() ) {
FaceShader_exportTokens( m_face.getShader(), writer ); FaceShader_ContentsFlagsValue_exportTokens( face.getShader(), writer );
FaceTexdef_exportTokens( m_face.getTexdef(), writer );
if ( m_face.getShader().m_flags.m_specified || m_face.isDetail() ) {
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
} }
writer.nextLine();
} }
}; }
class Quake3FaceTokenExporter
{
const Face& m_face;
public:
Quake3FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer );
FaceShader_exportTokens( m_face.getShader(), writer );
FaceTexdef_exportTokens( m_face.getTexdef(), writer );
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
writer.nextLine();
}
};
class Quake3BPFaceTokenExporter
{
const Face& m_face;
public:
Quake3BPFaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer );
FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
FaceShader_exportTokens( m_face.getShader(), writer );
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
writer.nextLine();
}
};
template<FaceExportFlags exportFlags>
class QuakeFaceTokenExporter class QuakeFaceTokenExporter
{ {
const Face& m_face; const Face& m_face;
@ -501,10 +425,28 @@ public:
FacePlane_exportTokens( m_face.getPlane(), writer ); FacePlane_exportTokens( m_face.getPlane(), writer );
FaceShader_exportTokens( m_face.getShader(), writer ); FaceShader_exportTokens( m_face.getShader(), writer );
FaceTexdef_exportTokens( m_face.getTexdef(), writer ); FaceTexdef_exportTokens( m_face.getTexdef(), writer );
FaceFlags_exportTokens<exportFlags>( m_face, writer );
writer.nextLine(); writer.nextLine();
} }
}; };
template<FaceExportFlags exportFlags>
class Quake3BPFaceTokenExporter
{
const Face& m_face;
public:
Quake3BPFaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer );
FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
FaceShader_exportTokens( m_face.getShader(), writer );
FaceFlags_exportTokens<exportFlags>( m_face, writer );
writer.nextLine();
}
};
template<FaceExportFlags exportFlags>
class Valve220FaceTokenExporter class Valve220FaceTokenExporter
{ {
const Face& m_face; const Face& m_face;
@ -515,21 +457,7 @@ public:
FacePlane_exportTokens( m_face.getPlane(), writer ); FacePlane_exportTokens( m_face.getPlane(), writer );
FaceShader_exportTokens( m_face.getShader(), writer ); FaceShader_exportTokens( m_face.getShader(), writer );
FaceTexdef_Valve220_exportTokens( m_face.getTexdef(), writer ); FaceTexdef_Valve220_exportTokens( m_face.getTexdef(), writer );
writer.nextLine(); FaceFlags_exportTokens<exportFlags>( m_face, writer );
}
};
class Quake3Valve220FaceTokenExporter
{
const Face& m_face;
public:
Quake3Valve220FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer );
FaceShader_exportTokens( m_face.getShader(), writer );
FaceTexdef_Valve220_exportTokens( m_face.getTexdef(), writer );
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
writer.nextLine(); writer.nextLine();
} }
}; };
@ -543,7 +471,7 @@ public:
BrushTokenImporter( Brush& brush ) : m_brush( brush ){ BrushTokenImporter( Brush& brush ) : m_brush( brush ){
} }
bool importTokens( Tokeniser& tokeniser ){ bool importTokens( Tokeniser& tokeniser ){
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) { if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
tokeniser.nextLine(); tokeniser.nextLine();
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) ); RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
} }
@ -579,46 +507,33 @@ public:
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
case eBrushTypeQuake:
case eBrushTypeQuake2: case eBrushTypeQuake2:
{
Quake2FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake3: case eBrushTypeQuake3:
{ {
Quake3FaceTokenImporter importer( face ); QuakeFaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
case eBrushTypeQuake2BP:
case eBrushTypeQuake3BP: case eBrushTypeQuake3BP:
{ {
Quake3BPFaceTokenImporter importer( face ); Quake3BPFaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
case eBrushTypeQuake:
{
QuakeFaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeValve220: case eBrushTypeValve220:
{ case eBrushTypeQuake2Valve220:
Valve220FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake3Valve220: case eBrushTypeQuake3Valve220:
{ {
Quake3Valve220FaceTokenImporter importer( face ); Valve220FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
} }
face.planeChanged(); face.planeChanged();
} }
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) { if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
tokeniser.nextLine(); tokeniser.nextLine();
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) ); RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
} }
@ -648,7 +563,7 @@ public:
writer.writeToken( "{" ); writer.writeToken( "{" );
writer.nextLine(); writer.nextLine();
if ( Brush::m_type == eBrushTypeQuake3BP ) { if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP ) {
writer.writeToken( "brushDef" ); writer.writeToken( "brushDef" );
writer.nextLine(); writer.nextLine();
writer.writeToken( "{" ); writer.writeToken( "{" );
@ -680,39 +595,51 @@ public:
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeQuake:
{
QuakeFaceTokenExporter<FaceExportFlags::no> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2: case eBrushTypeQuake2:
{ {
Quake2FaceTokenExporter exporter( face ); QuakeFaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeQuake3: case eBrushTypeQuake3:
{ {
Quake3FaceTokenExporter exporter( face ); QuakeFaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2BP:
{
Quake3BPFaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeQuake3BP: case eBrushTypeQuake3BP:
{ {
Quake3BPFaceTokenExporter exporter( face ); Quake3BPFaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake:
{
QuakeFaceTokenExporter exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeValve220: case eBrushTypeValve220:
{ {
Valve220FaceTokenExporter exporter( face ); Valve220FaceTokenExporter<FaceExportFlags::no> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2Valve220:
{
Valve220FaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeQuake3Valve220: case eBrushTypeQuake3Valve220:
{ {
Quake3Valve220FaceTokenExporter exporter( face ); Valve220FaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
@ -720,7 +647,7 @@ public:
} }
} }
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) { if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
writer.writeToken( "}" ); writer.writeToken( "}" );
writer.nextLine(); writer.nextLine();
} }

View File

@ -279,7 +279,7 @@ public:
FaceXMLExporter( const Face& face ) : m_face( face ){ FaceXMLExporter( const Face& face ) : m_face( face ){
} }
void exportXML( XMLImporter& importer ){ void exportXML( XMLImporter& importer ){
bool bAlternateTexdef = ( Face::m_type == eBrushTypeQuake3BP || Face::m_type == eBrushTypeDoom3 || Face::m_type == eBrushTypeQuake4 ); bool bAlternateTexdef = ( Face::m_type == eBrushTypeQuake3BP || Face::m_type == eBrushTypeQuake2BP || Face::m_type == eBrushTypeDoom3 || Face::m_type == eBrushTypeQuake4 );
// write shader // write shader
{ {