755 lines
26 KiB
C++
755 lines
26 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
|
|
*/
|
|
|
|
#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)
|
|
{
|
|
//don't break if they're omitted. Yes, this might mean that it silently accepts quake-format maps where q3 maps were expected.
|
|
if (Tokeniser_nextTokenIsDigit(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_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 FaceTexdef_importTokens(FaceTexdef &texdef, Tokeniser &tokeniser)
|
|
{
|
|
/* //pass it on to halflife parsing if we unexpectedly find it in one of the other formats (blame J.A.C.K.)
|
|
const char* token = tokeniser.getToken();
|
|
if ( token && *token == '[' )
|
|
{
|
|
tokeniser.ungetToken();
|
|
texdef.m_scaleApplied = true;
|
|
return FaceTexdef_HalfLife_importTokens(texdef, tokeniser);
|
|
}
|
|
tokeniser.ungetToken();
|
|
*/
|
|
// 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 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 Quake3ValveFaceTokenImporter {
|
|
Face &m_face;
|
|
public:
|
|
Quake3ValveFaceTokenImporter(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));
|
|
RETURN_FALSE_IF_FAIL(FaceShader_importContentsFlagsValue(m_face.getShader(), tokeniser));
|
|
|
|
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 Quake3ValveFaceTokenExporter {
|
|
const Face &m_face;
|
|
public:
|
|
Quake3ValveFaceTokenExporter(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);
|
|
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 eBrushTypeQuake3Valve: {
|
|
Quake3ValveFaceTokenImporter 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;
|
|
break;
|
|
case eBrushTypeQuake3Valve: {
|
|
Quake3ValveFaceTokenExporter 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
|