/* 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 */ #if !defined( INCLUDED_BRUSHTOKENS_H ) #define INCLUDED_BRUSHTOKENS_H #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] ) ); ASSERT_MESSAGE( texdef_sane( texdef.m_projection.m_texdef ), "FaceTexdef_importTokens: bad texdef" ); 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_HalfLife_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; ASSERT_MESSAGE( texdef_sane( texdef.m_projection.m_texdef ), "FaceTexdef_importTokens: bad texdef" ); 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 { StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) ); shader << GlobalTexturePrefix_get() << texture; faceShader.setShader( shader.c_str() ); } 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 Quake2FaceTokenImporter { Face& m_face; public: Quake2FaceTokenImporter( 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 ) ) { m_face.getShader().m_flags.m_specified = true; 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 ) ); 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 ) ); 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 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 ) ); m_face.getTexdef().m_scaleApplied = true; return true; } }; class HalfLifeFaceTokenImporter { Face& m_face; public: HalfLifeFaceTokenImporter( 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_HalfLife_importTokens( m_face.getTexdef(), 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 ){ ASSERT_MESSAGE( texdef_sane( faceTexdef.m_projection.m_texdef ), "FaceTexdef_exportTokens: bad texdef" ); // 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_HalfLife_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){ ASSERT_MESSAGE( texdef_sane( faceTexdef.m_projection.m_texdef ), "FaceTexdef_exportTokens: bad texdef" ); // 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(); } }; class Quake2FaceTokenExporter { const Face& m_face; public: Quake2FaceTokenExporter( 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 ); 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(); } }; 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 ); writer.nextLine(); } }; class HalfLifeFaceTokenExporter { const Face& m_face; public: HalfLifeFaceTokenExporter( const Face& face ) : m_face( face ){ } void exportTokens( TokenWriter& writer ) const { FacePlane_exportTokens( m_face.getPlane(), writer ); FaceShader_exportTokens( m_face.getShader(), writer ); FaceTexdef_HalfLife_exportTokens( m_face.getTexdef(), 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 == 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 eBrushTypeQuake2: { Quake2FaceTokenImporter importer( face ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); } break; case eBrushTypeQuake3: { Quake3FaceTokenImporter importer( face ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); } break; case eBrushTypeQuake3BP: { Quake3BPFaceTokenImporter importer( face ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); } break; case eBrushTypeQuake: { QuakeFaceTokenImporter importer( face ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); } break; case eBrushTypeHalfLife: { HalfLifeFaceTokenImporter importer( face ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); } break; } face.planeChanged(); } if ( Brush::m_type == eBrushTypeQuake3BP || 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 ) { writer.writeToken( "brushDef" ); writer.nextLine(); writer.writeToken( "{" ); writer.nextLine(); } 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 eBrushTypeQuake2: { Quake2FaceTokenExporter exporter( face ); exporter.exportTokens( writer ); } break; case eBrushTypeQuake3: { Quake3FaceTokenExporter exporter( face ); exporter.exportTokens( writer ); } break; case eBrushTypeQuake3BP: { Quake3BPFaceTokenExporter exporter( face ); exporter.exportTokens( writer ); } break; case eBrushTypeQuake: { QuakeFaceTokenExporter exporter( face ); exporter.exportTokens( writer ); } break; case eBrushTypeHalfLife: { HalfLifeFaceTokenExporter exporter( face ); exporter.exportTokens( writer ); } break; } } } if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) { writer.writeToken( "}" ); writer.nextLine(); } writer.writeToken( "}" ); writer.nextLine(); } }; #endif