netradiant-custom/radiant/brushtokens.h
Garux df02774ff5 tweak StringOutputStream use
auto str = StringOutputStream()(bla) use form was not doing copy elision or move, but copy
2024-01-29 16:54:08 +06:00

656 lines
22 KiB
C++

/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "stringio.h"
#include "stream/stringstream.h"
#include "brush.h"
inline bool FaceShader_importContentsFlagsValue( FaceShader& faceShader, Tokeniser& tokeniser ){
// parse the optional contents/flags/value
RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_contentFlags ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_surfaceFlags ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_value ) );
return true;
}
inline bool FaceTexdef_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
// parse texdef
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[1] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.rotate ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[1] ) );
if( !texdef_sane( texdef.m_projection.m_texdef ) )
globalWarningStream() << "FaceTexdef_importTokens: bad texdef\n";
return true;
}
inline bool FaceTexdef_BP_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
// parse alternate texdef
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
{
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][1] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][2] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
}
{
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][1] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][2] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
}
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
return true;
}
inline bool FaceTexdef_Valve220_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
// parse texdef
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.x() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.y() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.z() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "]" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.x() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.y() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.z() ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[1] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "]" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.rotate ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[0] ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[1] ) );
texdef.m_projection.m_texdef.rotate = -texdef.m_projection.m_texdef.rotate;
if( !texdef_sane( texdef.m_projection.m_texdef ) )
globalWarningStream() << "FaceTexdef_Valve220_importTokens: bad texdef\n";
return true;
}
inline bool FacePlane_importTokens( FacePlane& facePlane, Tokeniser& tokeniser ){
// parse planepts
for ( std::size_t i = 0; i < 3; i++ )
{
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
for ( std::size_t j = 0; j < 3; ++j )
{
RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, facePlane.planePoints()[i][j] ) );
}
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
}
facePlane.MakePlane();
return true;
}
inline bool FacePlane_Doom3_importTokens( FacePlane& facePlane, Tokeniser& tokeniser ){
Plane3 plane;
// parse plane equation
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.a ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.b ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.c ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.d ) );
plane.d = -plane.d;
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
facePlane.setDoom3Plane( plane );
return true;
}
inline bool FaceShader_Doom3_importTokens( FaceShader& faceShader, Tokeniser& tokeniser ){
const char *shader = tokeniser.getToken();
if ( shader == 0 ) {
Tokeniser_unexpectedError( tokeniser, shader, "#shader-name" );
return false;
}
if ( string_equal( shader, "_emptyname" ) ) {
shader = texdef_name_default();
}
faceShader.setShader( shader );
return true;
}
inline bool FaceShader_importTokens( FaceShader& faceShader, Tokeniser& tokeniser ){
const char* texture = tokeniser.getToken();
if ( texture == 0 ) {
Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" );
return false;
}
if ( string_equal( texture, "NULL" ) ) {
faceShader.setShader( texdef_name_default() );
}
else
{
faceShader.setShader( StringStream<64>( GlobalTexturePrefix_get(), texture ) );
}
return true;
}
class Doom3FaceTokenImporter
{
Face& m_face;
public:
Doom3FaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_Doom3_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_Doom3_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
m_face.getTexdef().m_projectionInitialised = true;
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Quake4FaceTokenImporter
{
Face& m_face;
public:
Quake4FaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_Doom3_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_Doom3_importTokens( m_face.getShader(), tokeniser ) );
m_face.getTexdef().m_projectionInitialised = true;
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
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 ) );
// 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 ) ) {
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 Quake3BPFaceTokenImporter
{
Face& m_face;
public:
Quake3BPFaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
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 ) );
}
m_face.getTexdef().m_projectionInitialised = true;
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Valve220FaceTokenImporter
{
Face& m_face;
public:
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 ) ) { ///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 ) );
}
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
inline void FacePlane_Doom3_exportTokens( const FacePlane& facePlane, TokenWriter& writer ){
// write plane equation
writer.writeToken( "(" );
writer.writeFloat( facePlane.getDoom3Plane().a );
writer.writeFloat( facePlane.getDoom3Plane().b );
writer.writeFloat( facePlane.getDoom3Plane().c );
writer.writeFloat( -facePlane.getDoom3Plane().d );
writer.writeToken( ")" );
}
inline void FacePlane_exportTokens( const FacePlane& facePlane, TokenWriter& writer ){
// write planepts
for ( std::size_t i = 0; i < 3; i++ )
{
writer.writeToken( "(" );
for ( std::size_t j = 0; j < 3; j++ )
{
writer.writeFloat( Face::m_quantise( facePlane.planePoints()[i][j] ) );
}
writer.writeToken( ")" );
}
}
inline void FaceTexdef_BP_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
// write alternate texdef
writer.writeToken( "(" );
{
writer.writeToken( "(" );
for ( std::size_t i = 0; i < 3; i++ )
{
writer.writeFloat( faceTexdef.m_projection.m_brushprimit_texdef.coords[0][i] );
}
writer.writeToken( ")" );
}
{
writer.writeToken( "(" );
for ( std::size_t i = 0; i < 3; i++ )
{
writer.writeFloat( faceTexdef.m_projection.m_brushprimit_texdef.coords[1][i] );
}
writer.writeToken( ")" );
}
writer.writeToken( ")" );
}
inline void FaceTexdef_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
if( !texdef_sane( faceTexdef.m_projection.m_texdef ) )
globalWarningStream() << "FaceTexdef_exportTokens: bad texdef\n";
// write texdef
writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[0] );
writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[1] );
writer.writeFloat( faceTexdef.m_projection.m_texdef.rotate );
writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[0] );
writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[1] );
}
inline void FaceTexdef_Valve220_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
if( !texdef_sane( faceTexdef.m_projection.m_texdef ) )
globalWarningStream() << "FaceTexdef_Valve220_exportTokens: bad texdef\n";
// write texdef
writer.writeToken( "[" );
writer.writeFloat( faceTexdef.m_projection.m_basis_s.x() );
writer.writeFloat( faceTexdef.m_projection.m_basis_s.y() );
writer.writeFloat( faceTexdef.m_projection.m_basis_s.z() );
writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[0] );
writer.writeToken( "]" );
writer.writeToken( "[" );
writer.writeFloat( faceTexdef.m_projection.m_basis_t.x() );
writer.writeFloat( faceTexdef.m_projection.m_basis_t.y() );
writer.writeFloat( faceTexdef.m_projection.m_basis_t.z() );
writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[1] );
writer.writeToken( "]" );
writer.writeFloat( -faceTexdef.m_projection.m_texdef.rotate );
writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[0] );
writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[1] );
}
inline void FaceShader_ContentsFlagsValue_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
// write surface flags
writer.writeInteger( faceShader.m_flags.m_contentFlags );
writer.writeInteger( faceShader.m_flags.m_surfaceFlags );
writer.writeInteger( faceShader.m_flags.m_value );
}
inline void FaceShader_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
// write shader name
if ( string_empty( shader_get_textureName( faceShader.getShader() ) ) ) {
writer.writeToken( "NULL" );
}
else
{
writer.writeToken( shader_get_textureName( faceShader.getShader() ) );
}
}
inline void FaceShader_Doom3_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
// write shader name
if ( string_empty( shader_get_textureName( faceShader.getShader() ) ) ) {
writer.writeString( "_emptyname" );
}
else
{
writer.writeString( faceShader.getShader() );
}
}
class Doom3FaceTokenExporter
{
const Face& m_face;
public:
Doom3FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_Doom3_exportTokens( m_face.getPlane(), writer );
FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
FaceShader_Doom3_exportTokens( m_face.getShader(), writer );
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
writer.nextLine();
}
};
class Quake4FaceTokenExporter
{
const Face& m_face;
public:
Quake4FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_Doom3_exportTokens( m_face.getPlane(), writer );
FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
FaceShader_Doom3_exportTokens( m_face.getShader(), writer );
writer.nextLine();
}
};
enum class FaceExportFlags{
yes,
no,
optional
};
template<FaceExportFlags exportFlags>
void FaceFlags_exportTokens( const Face& face, TokenWriter& writer ){
if constexpr ( exportFlags == FaceExportFlags::yes ){
FaceShader_ContentsFlagsValue_exportTokens( face.getShader(), writer );
}
else if constexpr ( exportFlags == FaceExportFlags::optional ){
if ( face.getShader().m_flags.m_specified || face.isDetail() ) {
FaceShader_ContentsFlagsValue_exportTokens( face.getShader(), writer );
}
}
}
template<FaceExportFlags exportFlags>
class QuakeFaceTokenExporter
{
const Face& m_face;
public:
QuakeFaceTokenExporter( 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 );
FaceFlags_exportTokens<exportFlags>( m_face, writer );
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
{
const Face& m_face;
public:
Valve220FaceTokenExporter( 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 );
FaceFlags_exportTokens<exportFlags>( m_face, writer );
writer.nextLine();
}
};
class BrushTokenImporter : public MapImporter
{
Brush& m_brush;
public:
BrushTokenImporter( Brush& brush ) : m_brush( brush ){
}
bool importTokens( Tokeniser& tokeniser ){
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
tokeniser.nextLine();
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
}
while ( 1 )
{
// check for end of brush
tokeniser.nextLine();
const char* token = tokeniser.getToken();
if ( string_equal( token, "}" ) ) {
break;
}
tokeniser.ungetToken();
m_brush.push_back( FaceSmartPointer( new Face( &m_brush ) ) );
//!todo BP support
tokeniser.nextLine();
Face& face = *m_brush.back();
switch ( Brush::m_type )
{
case eBrushTypeDoom3:
{
Doom3FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake4:
{
Quake4FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake:
case eBrushTypeQuake2:
case eBrushTypeQuake3:
{
QuakeFaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake2BP:
case eBrushTypeQuake3BP:
{
Quake3BPFaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeValve220:
case eBrushTypeQuake2Valve220:
case eBrushTypeQuake3Valve220:
{
Valve220FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
}
face.planeChanged();
}
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
tokeniser.nextLine();
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
}
m_brush.planeChanged();
m_brush.shaderChanged();
return true;
}
};
class BrushTokenExporter : public MapExporter
{
const Brush& m_brush;
public:
BrushTokenExporter( const Brush& brush ) : m_brush( brush ){
}
void exportTokens( TokenWriter& writer ) const {
m_brush.evaluateBRep(); // ensure b-rep is up-to-date, so that non-contributing faces can be identified.
if ( !m_brush.hasContributingFaces() ) {
return;
}
writer.writeToken( "{" );
writer.nextLine();
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP ) {
writer.writeToken( "brushDef" );
writer.nextLine();
writer.writeToken( "{" );
writer.nextLine();
}
else if ( Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
writer.writeToken( "brushDef3" );
writer.nextLine();
writer.writeToken( "{" );
writer.nextLine();
}
for ( Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i )
{
const Face& face = *( *i );
if ( face.contributes() ) {
switch ( Brush::m_type )
{
case eBrushTypeDoom3:
{
Doom3FaceTokenExporter exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake4:
{
Quake4FaceTokenExporter exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake:
{
QuakeFaceTokenExporter<FaceExportFlags::no> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2:
{
QuakeFaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake3:
{
QuakeFaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2BP:
{
Quake3BPFaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake3BP:
{
Quake3BPFaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeValve220:
{
Valve220FaceTokenExporter<FaceExportFlags::no> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake2Valve220:
{
Valve220FaceTokenExporter<FaceExportFlags::optional> exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake3Valve220:
{
Valve220FaceTokenExporter<FaceExportFlags::yes> exporter( face );
exporter.exportTokens( writer );
}
break;
}
}
}
if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeQuake2BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
writer.writeToken( "}" );
writer.nextLine();
}
writer.writeToken( "}" );
writer.nextLine();
}
};