1) Added support for nested tags to XMLNode.

2) Made all xml files well formed.
3) Minor code cleanups.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3324 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-03-31 02:52:01 +00:00
parent 3f4e171872
commit f860816241
13 changed files with 157 additions and 209 deletions

View File

@ -93,8 +93,6 @@ supertuxkart_SOURCES = \
io/file_manager.hpp \ io/file_manager.hpp \
io/xml_node.cpp \ io/xml_node.cpp \
io/xml_node.hpp \ io/xml_node.hpp \
io/xml_reader.cpp \
io/xml_reader.hpp\
items/attachment.cpp \ items/attachment.cpp \
items/attachment.hpp \ items/attachment.hpp \
items/attachment_manager.cpp \ items/attachment_manager.cpp \

View File

@ -17,8 +17,8 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef MOVING_TEXTURE_H #ifndef MOVING_TEXTURE_HPP
#define MOVING_TEXTURE_H #define MOVING_TEXTURE_HPP
#include <string> #include <string>
#define _WINSOCKAPI_ #define _WINSOCKAPI_

View File

@ -668,10 +668,6 @@
RelativePath="..\..\io\xml_node.cpp" RelativePath="..\..\io\xml_node.cpp"
> >
</File> </File>
<File
RelativePath="..\..\io\xml_reader.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="input" Name="input"
@ -1278,10 +1274,6 @@
RelativePath="..\..\io\xml_node.hpp" RelativePath="..\..\io\xml_node.hpp"
> >
</File> </File>
<File
RelativePath="..\..\io\xml_reader.hpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="input" Name="input"

View File

@ -6,7 +6,6 @@
#include "input/input.hpp" #include "input/input.hpp"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "io/xml_reader.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
enum DeviceType enum DeviceType

View File

@ -209,12 +209,20 @@ FileManager::~FileManager()
} // ~FileManager } // ~FileManager
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
XMLReader *FileManager::getXMLReader(const std::string &f) io::IXMLReader *FileManager::getXMLReader(const std::string &filename)
{ {
io::IXMLReader *r = m_file_system->createXMLReader(f.c_str()); return m_file_system->createXMLReader(filename.c_str());
if(!r) return NULL;
return new XMLReader(r);
} // getXMLReader } // getXMLReader
//-----------------------------------------------------------------------------
/** Reads in a XML file and converts it into a XMLNode tree.
* \param filename Name of the XML file to read.
*/
XMLNode *FileManager::getXMLTree(const std::string &filename)
{
io::IXMLReader *xml_reader = getXMLReader(filename);
if(!xml_reader) return NULL;
return new XMLNode(xml_reader);
} // getXMLTree
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FileManager::pushModelSearchPath(const std::string& path) void FileManager::pushModelSearchPath(const std::string& path)

View File

@ -19,13 +19,15 @@
#ifndef HEADER_FILE_MANAGER_HPP #ifndef HEADER_FILE_MANAGER_HPP
#define HEADER_FILE_MANAGER_HPP #define HEADER_FILE_MANAGER_HPP
#include <string> #include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include "irrlicht.h" #include "irrlicht.h"
using namespace irr; using namespace irr;
#include "io/xml_reader.hpp"
#include "io/xml_node.hpp"
class FileManager class FileManager
{ {
@ -54,7 +56,8 @@ public:
~FileManager(); ~FileManager();
void setDevice(IrrlichtDevice *device); void setDevice(IrrlichtDevice *device);
void dropFileSystem(); void dropFileSystem();
XMLReader *getXMLReader(const std::string &f); io::IXMLReader *getXMLReader(const std::string &filename);
XMLNode *getXMLTree(const std::string &filename);
std::string getHomeDir () const; std::string getHomeDir () const;
std::string getTrackDir () const; std::string getTrackDir () const;

View File

@ -1,4 +1,4 @@
// $Id: xml_reader.hpp 694 2006-08-29 07:42:36Z hiker $ // $Id: xml_node.hpp 694 2006-08-29 07:42:36Z hiker $
// //
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs // Copyright (C) 2009 Joerg Henrichs
@ -16,46 +16,110 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_IRRLICHT
#include "io/file_manager.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
XMLNode::XMLNode(const std::string &name, io::IXMLReader *xml) XMLNode::XMLNode(io::IXMLReader *xml)
{ {
m_name = name; while(xml->getNodeType()!=io::EXN_ELEMENT && xml->read());
readXML(xml);
} // XMLNode
// ----------------------------------------------------------------------------
/** Reads a XML file and convert it intoa XMLNode tree.
* \param filename Name of the XML file to read.
*/
XMLNode::XMLNode(const std::string &filename)
{
io::IXMLReader *xml = file_manager->getXMLReader(filename);
bool is_first_element = true;
while(xml->read())
{
switch (xml->getNodeType())
{
case io::EXN_ELEMENT:
{
if(!is_first_element)
{
fprintf(stderr,
"More than one root element in '%s' - ignored.\n",
filename.c_str());
}
readXML(xml);
is_first_element = false;
break;
}
case io::EXN_ELEMENT_END: break; // Ignore all other types
case io::EXN_UNKNOWN: break;
case io::EXN_COMMENT: break;
case io::EXN_TEXT: break;
default: break;
} // switch
} // while
} // XMLNode
// ----------------------------------------------------------------------------
/** Stores all attributes, and reads in all children.
* \param xml The XML reader.
*/
void XMLNode::readXML(io::IXMLReader *xml)
{
m_name = std::string(core::stringc(xml->getNodeName()).c_str());
for(unsigned int i=0; i<xml->getAttributeCount(); i++) for(unsigned int i=0; i<xml->getAttributeCount(); i++)
{ {
std::string name = core::stringc(xml->getAttributeName(i)).c_str(); std::string name = core::stringc(xml->getAttributeName(i)).c_str();
core::stringw value = xml->getAttributeValue(i); core::stringw value = xml->getAttributeValue(i);
m_attributes[name] = value; m_attributes[name] = value;
} // for i } // for i
#ifdef TEST_ONLY
// If no children, we are done
if(xml->isEmptyElement())
return;
/** Read all children elements. */
while(xml->read()) while(xml->read())
{ {
switch (xml->getNodeType()) switch (xml->getNodeType())
{ {
case io::EXN_ELEMENT: break; case io::EXN_ELEMENT:
case io::EXN_ELEMENT_END: m_nodes.push_back(new XMLNode(xml));
printf("found end\n");
break;// Ignore all other types
case io::EXN_UNKNOWN:
printf("found end\n");
break; break;
case io::EXN_COMMENT: case io::EXN_ELEMENT_END:
printf("found end\n"); // End of this element found.
break; return;
case io::EXN_TEXT:
printf("found end\n");
break;
default:
printf("found end\n");
break; break;
case io::EXN_UNKNOWN: break;
case io::EXN_COMMENT: break;
case io::EXN_TEXT: break;
default: break;
} // switch } // switch
} // while } // while
#endif } // readXML
} // XMLNode
// ----------------------------------------------------------------------------
/** Returns the i.th node.
* \param i Number of node to return.
*/
XMLNode *XMLNode::getNode(unsigned int i)
{
return m_nodes[i];
} // getNode
// ----------------------------------------------------------------------------
/** Returns the node with the given name.
* \param s Name of the node to return.
*/
XMLNode *XMLNode::getNode(const std::string &s)
{
for(unsigned int i=0; i<m_nodes.size(); i++)
{
if(m_nodes[i]->getName()==s) return m_nodes[i];
}
return NULL;
} // getNode
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** If 'attribute' was defined, set 'value' to the value of the /** If 'attribute' was defined, set 'value' to the value of the
@ -302,4 +366,3 @@ int XMLNode::getHPR(Vec3 *value) const
} // getHPR Vec3 } // getHPR Vec3
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#endif

View File

@ -1,4 +1,4 @@
// $Id: xml_reader.hpp 694 2006-08-29 07:42:36Z hiker $ // $Id: xml_node.hpp 694 2006-08-29 07:42:36Z hiker $
// //
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs // Copyright (C) 2009 Joerg Henrichs
@ -17,7 +17,6 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_IRRLICHT
#ifndef HEADER_XML_NODE_HPP #ifndef HEADER_XML_NODE_HPP
#define HEADER_XML_NODE_HPP #define HEADER_XML_NODE_HPP
@ -38,10 +37,14 @@ private:
std::map<std::string, core::stringw> m_attributes; std::map<std::string, core::stringw> m_attributes;
/** List of all sub nodes. */ /** List of all sub nodes. */
std::vector<XMLNode *> m_nodes; std::vector<XMLNode *> m_nodes;
void readXML(io::IXMLReader *xml);
public: public:
XMLNode(const std::string &name, io::IXMLReader *xml); XMLNode(io::IXMLReader *xml);
XMLNode(const std::string &filename);
const std::string &getName() const {return m_name; } const std::string &getName() const {return m_name; }
XMLNode *getNode(const std::string &name); XMLNode *getNode(const std::string &name);
XMLNode *getNode(unsigned int i);
unsigned int getNumNodes() {return m_nodes.size(); }
int get(const std::string &attribute, std::string *value) const; int get(const std::string &attribute, std::string *value) const;
int get(const std::string &attribute, int *value) const; int get(const std::string &attribute, int *value) const;
int get(const std::string &attribute, float *value) const; int get(const std::string &attribute, float *value) const;
@ -54,7 +57,7 @@ public:
int get(const std::string &attribute, std::vector<int> *value) const; int get(const std::string &attribute, std::vector<int> *value) const;
int get(core::vector3df *value) const; int get(core::vector3df *value) const;
int getXYZ(core::vector3df *value) const; int getXYZ(core::vector3df *value) const;
int getXYZ(Vec3 *value) const; int getXYZ(Vec3 *vaslue) const;
int getHPR(core::vector3df *value) const; int getHPR(core::vector3df *value) const;
int getHPR(Vec3 *value) const; int getHPR(Vec3 *value) const;
/** Handy functions to test the bit pattern returned by get(vector3df*).*/ /** Handy functions to test the bit pattern returned by get(vector3df*).*/
@ -67,4 +70,3 @@ public:
}; // XMLNode }; // XMLNode
#endif #endif
#endif

View File

@ -1,70 +0,0 @@
// $Id: xml_reader.hpp 694 2006-08-29 07:42:36Z hiker $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
//
// This program 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 3
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_IRRLICHT
#include "io/xml_reader.hpp"
#include "io/xml_node.hpp"
XMLReader::XMLReader(io::IXMLReader *xml)
{
while(xml->read())
{
switch (xml->getNodeType())
{
case io::EXN_ELEMENT:
{
// FIXME: is there an easier way to convert
// stringw to std::string?
std::string s = core::stringc(xml->getNodeName()).c_str();
const XMLNode *node = new XMLNode(s, xml);
m_all_nodes.push_back(node);
break;
}
case io::EXN_ELEMENT_END: // Ignore all other types
case io::EXN_UNKNOWN:
case io::EXN_COMMENT:
case io::EXN_TEXT:
default: break;
} // switch
} // while
} // XMLReader
// ----------------------------------------------------------------------------
unsigned int XMLReader::getNumNodes() const
{
return m_all_nodes.size();
} // getNumNodes
// ----------------------------------------------------------------------------
const XMLNode *XMLReader::getNode(unsigned int n) const
{
return m_all_nodes[n];
} // getNode
// ----------------------------------------------------------------------------
const XMLNode *XMLReader::getNode(const std::string &node_name) const
{
for(unsigned int i=0; i<m_all_nodes.size(); i++)
{
if(m_all_nodes[i]->getName()==node_name) return m_all_nodes[i];
}
return NULL;
} // getNode
#endif

View File

@ -1,45 +0,0 @@
// $Id: xml_reader.hpp 694 2006-08-29 07:42:36Z hiker $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
//
// This program 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 3
// of the License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_IRRLICHT
#ifndef HEADER_XML_READER_HPP
#define HEADER_XML_READER_HPP
#include <string>
#include <vector>
#include "irrlicht.h"
using namespace irr;
class XMLNode;
class XMLReader
{
private:
io::IXMLReader *m_reader;
std::vector<const XMLNode *> m_all_nodes;
public:
XMLReader(io::IXMLReader *r);
unsigned int getNumNodes() const;
const XMLNode *getNode(const std::string &node_name) const;
const XMLNode *getNode(unsigned int n) const;
}; // XMLReader
#endif
#endif

View File

@ -17,9 +17,6 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "io/xml_node.hpp"
#include "io/xml_reader.hpp"
#include "material.hpp" #include "material.hpp"
#include <stdexcept> #include <stdexcept>
@ -27,6 +24,7 @@
#include "stk_config.hpp" #include "stk_config.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"

View File

@ -113,11 +113,11 @@ void MaterialManager::addSharedMaterial(const std::string& filename)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool MaterialManager::pushTempMaterial(const std::string& filename) bool MaterialManager::pushTempMaterial(const std::string& filename)
{ {
XMLReader *xml = file_manager->getXMLReader(filename); XMLNode *root = file_manager->getXMLTree(filename);
if(!xml) return true; if(!root || root->getName()!="materials") return true;
for(unsigned int i=0; i<xml->getNumNodes(); i++) for(unsigned int i=0; i<root->getNumNodes(); i++)
{ {
const XMLNode *node = xml->getNode(i); const XMLNode *node = root->getNode(i);
if(!node) if(!node)
{ {
// We don't have access to the filename at this stage anymore :( // We don't have access to the filename at this stage anymore :(

View File

@ -863,54 +863,54 @@ void Track::loadTrack(const std::string &filename)
m_ambient_color = video::SColorf(0.5f, 0.5f, 0.5f, 1.0f); m_ambient_color = video::SColorf(0.5f, 0.5f, 0.5f, 1.0f);
m_specular_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); m_specular_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
m_diffuse_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); m_diffuse_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
XMLReader *xml = file_manager->getXMLReader(m_filename); XMLNode *root = file_manager->getXMLTree(m_filename);
const XMLNode *node = xml->getNode("track");
if(!node) if(!root || root->getName()!="track")
{ {
std::ostringstream o; std::ostringstream o;
o<<"Can't load track '"<<filename<<"', no track element."; o<<"Can't load track '"<<filename<<"', no track element.";
throw std::runtime_error(o.str()); throw std::runtime_error(o.str());
} }
node->get("name", &m_name); root->get("name", &m_name);
node->get("description", &m_description); root->get("description", &m_description);
node->get("designer", &m_designer); root->get("designer", &m_designer);
node->get("version", &m_version); root->get("version", &m_version);
std::vector<std::string> filenames; std::vector<std::string> filenames;
node->get("music", &filenames); root->get("music", &filenames);
getMusicInformation(filenames, m_music); getMusicInformation(filenames, m_music);
node->get("item", &m_item_style); root->get("item", &m_item_style);
node->get("screenshot", &m_screenshot); root->get("screenshot", &m_screenshot);
node->get("item", &m_item_style); root->get("item", &m_item_style);
node->get("screenshot", &m_screenshot); root->get("screenshot", &m_screenshot);
node->get("sky-color", &m_sky_color); root->get("sky-color", &m_sky_color);
node->get("start-x", &m_start_x); root->get("start-x", &m_start_x);
node->get("start-y", &m_start_y); root->get("start-y", &m_start_y);
node->get("start-z", &m_start_z); root->get("start-z", &m_start_z);
node->get("start-heading", &m_start_heading); root->get("start-heading", &m_start_heading);
node->get("use-fog", &m_use_fog); root->get("use-fog", &m_use_fog);
node->get("fog-color", &m_fog_color); root->get("fog-color", &m_fog_color);
node->get("fog-density", &m_fog_density); root->get("fog-density", &m_fog_density);
node->get("fog-start", &m_fog_start); root->get("fog-start", &m_fog_start);
node->get("fog-end", &m_fog_end); root->get("fog-end", &m_fog_end);
node->get("sun-position", &m_sun_position); root->get("sun-position", &m_sun_position);
node->get("sun-ambient", &m_ambient_color); root->get("sun-ambient", &m_ambient_color);
node->get("sun-specular", &m_specular_color); root->get("sun-specular", &m_specular_color);
node->get("sun-diffuse", &m_diffuse_color); root->get("sun-diffuse", &m_diffuse_color);
node->get("gravity", &m_gravity); root->get("gravity", &m_gravity);
node->get("arena", &m_is_arena); root->get("arena", &m_is_arena);
node->get("groups", &m_groups); root->get("groups", &m_groups);
if(m_groups.size()==0) if(m_groups.size()==0)
m_groups.push_back("standard"); m_groups.push_back("standard");
// if both camera position and rotation are defined, // if both camera position and rotation are defined,
// set the flag that the track has final camera position // set the flag that the track has final camera position
m_has_final_camera = node->get("camera-final-position", m_has_final_camera = root->get("camera-final-position",
&m_camera_final_position)!=1; &m_camera_final_position)!=1;
m_has_final_camera &= node->get("camera-final-hpr", m_has_final_camera &= root->get("camera-final-hpr",
&m_camera_final_hpr) !=1; &m_camera_final_hpr) !=1;
m_camera_final_hpr.degreeToRad(); m_camera_final_hpr.degreeToRad();
m_sky_type = SKY_NONE; m_sky_type = SKY_NONE;
node = xml->getNode("sky-dome"); XMLNode *node = root->getNode("sky-dome");
if(node) if(node)
{ {
m_sky_type = SKY_DOME; m_sky_type = SKY_DOME;
@ -919,7 +919,7 @@ void Track::loadTrack(const std::string &filename)
m_sky_sphere_percent = 1.0f; m_sky_sphere_percent = 1.0f;
m_sky_texture_percent = 1.0f; m_sky_texture_percent = 1.0f;
std::string s; std::string s;
node->get("texture", &s ); node->get("texture", &s );
m_sky_textures.push_back(s); m_sky_textures.push_back(s);
node->get("vertical", &m_sky_vert_segments ); node->get("vertical", &m_sky_vert_segments );
node->get("horizontal", &m_sky_hori_segments ); node->get("horizontal", &m_sky_hori_segments );
@ -927,7 +927,7 @@ void Track::loadTrack(const std::string &filename)
node->get("texture-percent", &m_sky_texture_percent); node->get("texture-percent", &m_sky_texture_percent);
} // if sky-dome } // if sky-dome
node = xml->getNode("sky-box"); node = root->getNode("sky-box");
if(node) if(node)
{ {
std::string s; std::string s;
@ -1300,22 +1300,22 @@ void Track::loadTrackModel()
// Start building the scene graph // Start building the scene graph
#ifdef HAVE_IRRLICHT #ifdef HAVE_IRRLICHT
std::string path = file_manager->getTrackFile(getIdent()+".scene"); std::string path = file_manager->getTrackFile(getIdent()+".scene");
XMLReader *xml = file_manager->getXMLReader(path); XMLNode *root = file_manager->getXMLTree(path);
// Make sure that we have a track (which is used for raycasts to // Make sure that we have a track (which is used for raycasts to
// place other objects). // place other objects).
const XMLNode *node = xml->getNode("track"); if(!root || root->getName()!="scene")
if(!node)
{ {
std::ostringstream msg; std::ostringstream msg;
msg<< "No track model defined in '"<<path msg<< "No track model defined in '"<<path
<<"', aborting."; <<"', aborting.";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
XMLNode *node = root->getNode("track");
loadMainTrack(*node); loadMainTrack(*node);
for(unsigned int i=0; i<xml->getNumNodes(); i++) for(unsigned int i=0; i<root->getNumNodes(); i++)
{ {
const XMLNode *node = xml->getNode(i); const XMLNode *node = root->getNode(i);
const std::string name = node->getName(); const std::string name = node->getName();
// The track object was already converted before the loop // The track object was already converted before the loop
if(name=="track") continue; if(name=="track") continue;