/* 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