+++ /dev/null
-/*
-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_BRUSHXML_H)
-#define INCLUDED_BRUSHXML_H
-
-#include "stream/stringstream.h"
-#include "xml/xmlelement.h"
-
-#include "brush.h"
-
-inline void FaceTexdef_BP_importXML(FaceTexdef& texdef, const char* xmlContent)
-{
- StringTokeniser content(xmlContent);
-
- texdef.m_projection.m_brushprimit_texdef.coords[0][0] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_brushprimit_texdef.coords[0][1] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_brushprimit_texdef.coords[0][2] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_brushprimit_texdef.coords[1][0] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_brushprimit_texdef.coords[1][1] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_brushprimit_texdef.coords[1][2] = static_cast<float>(atof(content.getToken()));
-}
-inline void FaceTexdef_importXML(FaceTexdef& texdef, const char* xmlContent)
-{
- StringTokeniser content(xmlContent);
-
- texdef.m_projection.m_texdef.shift[0] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_texdef.shift[1] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_texdef.rotate = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_texdef.scale[0] = static_cast<float>(atof(content.getToken()));
- texdef.m_projection.m_texdef.scale[1] = static_cast<float>(atof(content.getToken()));
-
- ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_importXML: bad texdef");
-}
-
-inline void FacePlane_importXML(FacePlane& facePlane, const char* xmlContent)
-{
- StringTokeniser content(xmlContent);
-
- for (int i = 0; i < 3; ++i)
- {
- for (int j = 0; j < 3; ++j)
- {
- facePlane.planePoints()[i][j] = atof(content.getToken());
- }
- }
- facePlane.MakePlane();
-}
-
-
-class FaceXMLImporter
-{
- struct xml_state_t
- {
- enum EState
- {
- eDefault,
- ePlanePts,
- eTexdef,
- eBPMatrix,
- eFlags,
- eShader,
- };
-
- EState m_state;
- StringOutputStream m_content;
-
- xml_state_t(EState state)
- : m_state(state)
- {}
-
- EState state() const
- {
- return m_state;
- }
- const char* content() const
- {
- return m_content.c_str();
- }
- std::size_t write(const char* buffer, std::size_t length)
- {
- return m_content.write(buffer, length);
- }
- };
-
- std::vector<xml_state_t> m_xml_state;
- Face& m_face;
-public:
- FaceXMLImporter(Face& face) : m_face(face)
- {
- m_xml_state.push_back(xml_state_t::eDefault);
- }
- ~FaceXMLImporter()
- {
- m_face.planeChanged();
- }
-
- void pushElement(const XMLElement& element)
- {
- ASSERT_MESSAGE(m_xml_state.back().state() == xml_state_t::eDefault, "parse error");
-
- if(strcmp(element.name(), "planepts") == 0)
- {
- m_xml_state.push_back(xml_state_t::ePlanePts);
- }
- else if(strcmp(element.name(), "texdef") == 0)
- {
- m_xml_state.push_back(xml_state_t::eTexdef);
- }
- else if(strcmp(element.name(), "bpmatrix") == 0)
- {
- m_xml_state.push_back(xml_state_t::eBPMatrix);
- }
- else if(strcmp(element.name(), "flags") == 0)
- {
- m_xml_state.push_back(xml_state_t::eFlags);
- }
- else if(strcmp(element.name(), "shader") == 0)
- {
- m_xml_state.push_back(xml_state_t::eShader);
- }
- }
- void popElement(const char* name)
- {
- ASSERT_MESSAGE(m_xml_state.back().state() != xml_state_t::eDefault, "parse error");
-
- switch(m_xml_state.back().state())
- {
- case xml_state_t::ePlanePts:
- {
- FacePlane_importXML(m_face.getPlane(), m_xml_state.back().content());
- }
- break;
- case xml_state_t::eTexdef:
- {
- FaceTexdef_importXML(m_face.getTexdef(), m_xml_state.back().content());
- }
- break;
- case xml_state_t::eBPMatrix:
- {
- FaceTexdef_BP_importXML(m_face.getTexdef(), m_xml_state.back().content());
- }
- break;
- case xml_state_t::eFlags:
- {
- StringTokeniser content(m_xml_state.back().content());
-
- m_face.getShader().m_flags.m_contentFlags = atoi(content.getToken());
- m_face.getShader().m_flags.m_surfaceFlags = atoi(content.getToken());
- m_face.getShader().m_flags.m_value = atoi(content.getToken());
- }
- break;
- case xml_state_t::eShader:
- {
- m_face.getShader().setShader(m_xml_state.back().content());
- }
- break;
- default:
- break;
- }
-
- m_xml_state.pop_back();
- }
- std::size_t write(const char* data, std::size_t length)
- {
- ASSERT_MESSAGE(!m_xml_state.empty(), "parse error");
- return m_xml_state.back().write(data, length);
- }
-};
-
-
-inline void FaceTexdef_exportXML(const FaceTexdef& texdef, XMLImporter& importer)
-{
- StaticElement element("texdef");
- importer.pushElement(element);
-
- ASSERT_MESSAGE(texdef_sane(texdef.m_projection.m_texdef), "FaceTexdef_exportXML: bad texdef");
-
- importer << texdef.m_projection.m_texdef.shift[0]
- << ' ' << texdef.m_projection.m_texdef.shift[1]
- << ' ' << texdef.m_projection.m_texdef.rotate
- << ' ' << texdef.m_projection.m_texdef.scale[0]
- << ' ' << texdef.m_projection.m_texdef.scale[1];
-
- importer.popElement(element.name());
-}
-inline void FaceTexdef_BP_exportXML(const FaceTexdef& texdef, XMLImporter& importer)
-{
- StaticElement element("texdef");
- importer.pushElement(element);
-
- for(int i = 0; i < 2; ++i)
- {
- for(int j = 0; j < 3; ++j)
- {
- importer << texdef.m_projection.m_brushprimit_texdef.coords[i][j] << ' ';
- }
- }
-
- importer.popElement(element.name());
-}
-inline void FaceShader_ContentsFlagsValue_exportXML(const FaceShader& faceShader, XMLImporter& importer)
-{
- StaticElement element("flags");
- importer.pushElement(element);
-
- {
- importer << faceShader.m_flags.m_contentFlags
- << ' ' << faceShader.m_flags.m_surfaceFlags
- << ' ' << faceShader.m_flags.m_value;
- }
-
- importer.popElement(element.name());
-}
-
-inline void FacePlane_exportXML(const FacePlane& facePlane, XMLImporter& importer)
-{
- StaticElement element("planepts");
- importer.pushElement(element);
-
- {
- // write planepts
- for (int i=0 ; i<3 ; i++)
- {
- for (int j=0 ; j<3 ; j++)
- {
- importer << Face::m_quantise(facePlane.planePoints()[i][j]) << ' ';
- }
- }
- }
-
- importer.popElement(element.name());
-}
-
-inline void FacePolygon_exportXML(const Winding& w, const BasicVector3<double>& normal, XMLImporter& importer)
-{
- DynamicElement element("polygon");
-
- char tmp[32];
-
- sprintf(tmp, "%f", normal.x());
- element.insertAttribute("nx", tmp);
-
- sprintf(tmp, "%f", normal.y());
- element.insertAttribute("ny", tmp);
-
- sprintf(tmp, "%f", normal.z());
- element.insertAttribute("nz", tmp);
-
- importer.pushElement(element);
-
- for(unsigned int i = 0; i < w.numpoints; ++i)
- {
- DynamicElement c("vertex");
-
- sprintf(tmp, "%f", w.points[i].vertex.x());
- c.insertAttribute("x", tmp);
-
- sprintf(tmp, "%f", w.points[i].vertex.y());
- c.insertAttribute("y", tmp);
-
- sprintf(tmp, "%f", w.points[i].vertex.z());
- c.insertAttribute("z", tmp);
-
- sprintf(tmp, "%f", w.points[i].texcoord.x());
- c.insertAttribute("s", tmp);
-
- sprintf(tmp, "%f", w.points[i].texcoord.y());
- c.insertAttribute("t", tmp);
-
- importer.pushElement(c);
- importer.popElement(c.name());
- }
-
- importer.popElement(element.name());
-}
-
-class FaceXMLExporter
-{
- const Face& m_face;
-public:
- FaceXMLExporter(const Face& face) : m_face(face)
- {
- }
- void exportXML(XMLImporter& importer)
- {
- bool bAlternateTexdef = (Face::m_type == eBrushTypeQuake3BP || Face::m_type == eBrushTypeDoom3 || Face::m_type == eBrushTypeQuake4);
-
- // write shader
- {
- StaticElement element("shader");
- importer.pushElement(element);
- importer << m_face.getShader().getShader();
- importer.popElement(element.name());
- }
-
- FacePolygon_exportXML(m_face.getWinding(), m_face.getPlane().plane3().normal(), importer);
- FacePlane_exportXML(m_face.getPlane(), importer);
-
- if(!bAlternateTexdef)
- {
- FaceTexdef_exportXML(m_face.getTexdef(), importer);
- }
- else
- {
- FaceTexdef_BP_exportXML(m_face.getTexdef(), importer);
- }
-
- FaceShader_ContentsFlagsValue_exportXML(m_face.getShader(), importer);
- }
-};
-
-
-class BrushXMLImporter : public XMLImporter
-{
- class xml_state_t
- {
- public:
- enum EState
- {
- eDefault,
- eBrush,
- eFace,
- };
-
- private:
- EState m_state;
-
- public:
- xml_state_t(EState state)
- : m_state(state)
- {
- }
- EState state() const
- {
- return m_state;
- }
- };
-
- std::vector<xml_state_t> m_xml_state;
- char m_faceImporter[sizeof(FaceXMLImporter)];
- Brush& m_brush;
-
- FaceXMLImporter& faceImporter()
- {
- return *reinterpret_cast<FaceXMLImporter*>(m_faceImporter);
- }
-
-public:
- BrushXMLImporter(Brush& brush) : m_brush(brush)
- {
- m_xml_state.push_back(xml_state_t::eDefault);
- }
- void pushElement(const XMLElement& element)
- {
- switch(m_xml_state.back().state())
- {
- case xml_state_t::eDefault:
- ASSERT_MESSAGE(strcmp(element.name(), "brush") == 0, "parse error");
- m_xml_state.push_back(xml_state_t::eBrush);
- break;
- case xml_state_t::eBrush:
- ASSERT_MESSAGE(strcmp(element.name(), "plane") == 0, "parse error");
- m_xml_state.push_back(xml_state_t::eFace);
- m_brush.push_back(FaceSmartPointer(new Face(&m_brush)));
- constructor(faceImporter(), makeReference(*m_brush.back()));
- m_brush.planeChanged();
- m_brush.shaderChanged();
- break;
- case xml_state_t::eFace:
- m_xml_state.push_back(xml_state_t::eFace);
- faceImporter().pushElement(element);
- break;
- }
- }
- void popElement(const char* name)
- {
- ASSERT_MESSAGE(!m_xml_state.empty(), "parse error");
- m_xml_state.pop_back();
-
- switch(m_xml_state.back().state())
- {
- case xml_state_t::eDefault:
- break;
- case xml_state_t::eBrush:
- destructor(faceImporter());
- break;
- case xml_state_t::eFace:
- faceImporter().popElement(name);
- break;
- }
- }
- std::size_t write(const char* data, std::size_t length)
- {
- switch(m_xml_state.back().state())
- {
- case xml_state_t::eFace:
- return faceImporter().write(data, length);
- break;
- default:
- break;
- }
- return length;
- }
-};
-
-class BrushXMLExporter : public XMLExporter
-{
- const Brush& m_brush;
-
-public:
- BrushXMLExporter(const Brush& brush) : m_brush(brush)
- {
- }
- void exportXML(XMLImporter& importer)
- {
- m_brush.evaluateBRep(); // ensure b-rep is up-to-date, so that non-contributing faces can be identified.
- ASSERT_MESSAGE(m_brush.hasContributingFaces(), "exporting an empty brush");
-
- const StaticElement brushElement("brush");
- importer.pushElement(brushElement);
-
- for(Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i)
- {
- if((*i)->contributes())
- {
- const StaticElement element("plane");
- importer.pushElement(element);
- FaceXMLExporter(*(*i)).exportXML(importer);
- importer.popElement(element.name());
- }
- }
-
- importer.popElement(brushElement.name());
- }
-};
-
-
-#endif