Started moving TileSet parsing code into separate class
authorIngo Ruhnke <grumbel@gmx.de>
Sun, 6 Dec 2009 00:17:49 +0000 (00:17 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Sun, 6 Dec 2009 00:17:49 +0000 (00:17 +0000)
SVN-Revision: 6172

src/supertux/tile.cpp
src/supertux/tile.hpp
src/supertux/tile_set.cpp
src/supertux/tile_set.hpp
src/supertux/tile_set_parser.cpp [new file with mode: 0644]
src/supertux/tile_set_parser.hpp [new file with mode: 0644]

index 8ce0755..65a74c5 100644 (file)
@@ -22,7 +22,7 @@
 #include "util/reader.hpp"
 #include "video/drawing_context.hpp"
 
-Tile::Tile(const TileSet *new_tileset) :
+Tile::Tile(const TileSetnew_tileset) :
   tileset(new_tileset), 
   imagespecs(),
   images(),
@@ -32,7 +32,7 @@ Tile::Tile(const TileSet *new_tileset) :
 {
 }
 
-Tile::Tile(const TileSet *new_tileset, std::vector<std::string> images, Rect rect, 
+Tile::Tile(const TileSetnew_tileset, std::vector<std::string> images, Rect rect, 
            uint32_t attributes, uint32_t data, float animfps) :
   tileset(new_tileset),
   imagespecs(),
@@ -158,7 +158,7 @@ Tile::load_images()
 {
   if(images.size() == 0 && imagespecs.size() != 0)
   {
-    const std::string& tiles_path = tileset->tiles_path;
+    const std::string& tiles_path = tileset.tiles_path;
 
     assert(images.size() == 0);
     for(std::vector<ImageSpec>::iterator i = imagespecs.begin(); i !=
index 6463631..2611a8a 100644 (file)
@@ -95,7 +95,7 @@ public:
   };
 
 private:
-  const TileSet         *tileset;
+  const TileSet&         tileset;
   std::vector<ImageSpec> imagespecs;
   std::vector<Surface*>  images;
 
@@ -108,8 +108,8 @@ private:
   float anim_fps;
 
 public:
-  Tile(const TileSet* tileset);
-  Tile(const TileSet* tileset, std::vector<std::string> images, Rect rect,
+  Tile(const TileSet& tileset);
+  Tile(const TileSet& tileset, std::vector<std::string> images, Rect rect,
        uint32_t attributes, uint32_t data, float animfps);
   ~Tile();
 
index c816d36..f1a326e 100644 (file)
@@ -23,6 +23,7 @@
 #include "lisp/list_iterator.hpp"
 #include "lisp/parser.hpp"
 #include "util/file_system.hpp"
+#include "supertux/tile_set_parser.hpp"
 
 TileSet::TileSet() :
   tiles(),
@@ -30,7 +31,7 @@ TileSet::TileSet() :
   tiles_loaded(false)
 {
   tiles.resize(1, 0);
-  tiles[0] = new Tile(this);
+  tiles[0] = new Tile(*this);
 }
 
 TileSet::TileSet(const std::string& filename) :
@@ -38,117 +39,9 @@ TileSet::TileSet(const std::string& filename) :
   tiles_path(), 
   tiles_loaded(true)
 {
-  tiles_path = FileSystem::dirname(filename);
+  TileSetParser parser(*this, filename);
+  parser.parse();
 
-  tiles.resize(1, 0);
-  tiles[0] = new Tile(this);
-
-  lisp::Parser parser;
-  const lisp::Lisp* root = parser.parse(filename);
-
-  const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles");
-  if(!tiles_lisp)
-    throw std::runtime_error("file is not a supertux tiles file.");
-
-  lisp::ListIterator iter(tiles_lisp);
-  while(iter.next()) {
-    if(iter.item() == "tile") {
-      std::auto_ptr<Tile> tile(new Tile(this));
-      uint32_t id = tile->parse(*(iter.lisp()));
-
-      if(id >= tiles.size())
-        tiles.resize(id+1, 0);
-
-      if(tiles[id] != 0) {
-        log_warning << "Tile with ID " << id << " redefined" << std::endl;
-      } else {
-        tiles[id] = tile.release();
-      }
-    } else if(iter.item() == "tilegroup") {
-      /* tilegroups are only interesting for the editor */
-    } else if (iter.item() == "tiles") {
-      // List of ids (use 0 if the tile should be ignored)
-      std::vector<uint32_t> ids;
-      // List of attributes of the tile
-      std::vector<uint32_t> attributes;
-      // List of data for the tiles
-      std::vector<uint32_t> datas;
-      //List of frames that the tiles come in
-      std::vector<std::string> images;
-
-      // width and height of the image in tile units, this is used for two
-      // purposes:
-      //  a) so we don't have to load the image here to know its dimensions
-      //  b) so that the resulting 'tiles' entry is more robust,
-      //  ie. enlarging the image won't break the tile id mapping
-      // FIXME: height is actually not used, since width might be enough for
-      // all purposes, still feels somewhat more natural this way
-      unsigned int width  = 0;
-      unsigned int height = 0;
-
-      iter.lisp()->get("ids",        ids);
-      bool has_attributes = iter.lisp()->get("attributes", attributes);
-      bool has_datas = iter.lisp()->get("datas", datas);
-
-      if(!iter.lisp()->get("image",      images))
-        iter.lisp()->get( "images",      images);
-
-      iter.lisp()->get("width",      width);
-      iter.lisp()->get("height",     height);
-
-      float animfps = 10;
-      iter.lisp()->get("anim-fps",     animfps);
-
-      if(images.size() <= 0) {
-        throw std::runtime_error("No images in tile.");
-      }
-      if(animfps < 0) {
-        throw std::runtime_error("Negative fps.");
-      }
-      if (ids.size() != width*height) {
-        std::ostringstream err;
-        err << "Number of ids (" << ids.size() <<  ") and size of image (" << width*height
-            << ") mismatch for image '" << images[0] << "', but must be equal";
-        throw std::runtime_error(err.str());
-      }
-
-      if (has_attributes && ids.size() != attributes.size()) {
-        std::ostringstream err;
-        err << "Number of ids (" << ids.size() <<  ") and attributes (" << attributes.size()
-            << ") mismatch for image '" << images[0] << "', but must be equal";
-        throw std::runtime_error(err.str());
-      }
-
-      if (has_datas && ids.size() != datas.size()) {
-        std::ostringstream err;
-        err << "Number of ids (" << ids.size() <<  ") and datas (" << datas.size()
-            << ") mismatch for image '" << images[0] << "', but must be equal";
-        throw std::runtime_error(err.str());
-      }
-
-      for(std::vector<uint32_t>::size_type i = 0; i < ids.size() && i < width*height; ++i) {
-        if (ids[i] == 0)
-          continue;
-
-        if(ids[i] >= tiles.size())
-          tiles.resize(ids[i]+1, 0);
-
-        int x = 32*(i % width);
-        int y = 32*(i / width);
-        std::auto_ptr<Tile> tile(new Tile(this, images, Rect(x, y, x + 32, y + 32),
-                                          (has_attributes ? attributes[i] : 0), (has_datas ? datas[i] : 0), animfps));
-        if (tiles[ids[i]] == 0) {
-          tiles[ids[i]] = tile.release();
-        } else {
-          log_warning << "Tile with ID " << ids[i] << " redefined" << std::endl;
-        }
-      }
-    } else if(iter.item() == "properties") {
-      // deprecated
-    } else {
-      log_warning << "Unknown symbol '" << iter.item() << "' in tileset file" << std::endl;
-    }
-  }
   if (0)
   { // enable this if you want to see a list of free tiles
     log_info << "Last Tile ID is " << tiles.size()-1 << std::endl;
@@ -166,6 +59,7 @@ TileSet::TileSet(const std::string& filename) :
       }
     }
   }
+
   if (0)
   { // enable this to dump the (large) list of tiles to log_debug
     // Two dumps are identical iff the tilesets specify identical tiles
index 8c4410e..54f9b59 100644 (file)
@@ -33,6 +33,8 @@ private:
 
   friend class TileManager;
   friend class Tile;
+  friend class TileSetParser;
+
   TileSet(const std::string& filename);
 
 public:
diff --git a/src/supertux/tile_set_parser.cpp b/src/supertux/tile_set_parser.cpp
new file mode 100644 (file)
index 0000000..8a11e52
--- /dev/null
@@ -0,0 +1,151 @@
+//  SuperTux
+//  Copyright (C) 2008 Matthias Braun <matze@braunis.de>
+//                     Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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, see <http://www.gnu.org/licenses/>.
+
+#include "supertux/tile_set_parser.hpp"
+
+#include <stdexcept>
+#include <sstream>
+
+#include "lisp/parser.hpp"
+#include "lisp/list_iterator.hpp"
+#include "supertux/tile_set.hpp"
+#include "util/file_system.hpp"
+#include "util/reader.hpp"
+
+TileSetParser::TileSetParser(TileSet& tileset, const std::string& filename) :
+  m_tileset(tileset),
+  m_filename(filename)
+{  
+}
+
+void
+TileSetParser::parse()
+{
+  m_tileset.tiles_path = FileSystem::dirname(m_filename);
+
+  m_tileset.tiles.resize(1, 0);
+  m_tileset.tiles[0] = new Tile(m_tileset);
+
+  lisp::Parser parser;
+  const lisp::Lisp* root = parser.parse(m_filename);
+
+  const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles");
+  if(!tiles_lisp)
+    throw std::runtime_error("file is not a supertux tiles file.");
+
+  lisp::ListIterator iter(tiles_lisp);
+  while(iter.next()) {
+    if(iter.item() == "tile") {
+      std::auto_ptr<Tile> tile(new Tile(m_tileset));
+      uint32_t id = tile->parse(*(iter.lisp()));
+
+      if(id >= m_tileset.tiles.size())
+        m_tileset.tiles.resize(id+1, 0);
+
+      if(m_tileset.tiles[id] != 0) {
+        log_warning << "Tile with ID " << id << " redefined" << std::endl;
+      } else {
+        m_tileset.tiles[id] = tile.release();
+      }
+    } else if(iter.item() == "tilegroup") {
+      /* tilegroups are only interesting for the editor */
+    } else if (iter.item() == "tiles") {
+      // List of ids (use 0 if the tile should be ignored)
+      std::vector<uint32_t> ids;
+      // List of attributes of the tile
+      std::vector<uint32_t> attributes;
+      // List of data for the tiles
+      std::vector<uint32_t> datas;
+      //List of frames that the tiles come in
+      std::vector<std::string> images;
+
+      // width and height of the image in tile units, this is used for two
+      // purposes:
+      //  a) so we don't have to load the image here to know its dimensions
+      //  b) so that the resulting 'tiles' entry is more robust,
+      //  ie. enlarging the image won't break the tile id mapping
+      // FIXME: height is actually not used, since width might be enough for
+      // all purposes, still feels somewhat more natural this way
+      unsigned int width  = 0;
+      unsigned int height = 0;
+
+      iter.lisp()->get("ids",        ids);
+      bool has_attributes = iter.lisp()->get("attributes", attributes);
+      bool has_datas = iter.lisp()->get("datas", datas);
+
+      if(!iter.lisp()->get("image",      images))
+        iter.lisp()->get( "images",      images);
+
+      iter.lisp()->get("width",      width);
+      iter.lisp()->get("height",     height);
+
+      float animfps = 10;
+      iter.lisp()->get("anim-fps",     animfps);
+
+      if(images.size() <= 0) {
+        throw std::runtime_error("No images in tile.");
+      }
+      if(animfps < 0) {
+        throw std::runtime_error("Negative fps.");
+      }
+      if (ids.size() != width*height) {
+        std::ostringstream err;
+        err << "Number of ids (" << ids.size() <<  ") and size of image (" << width*height
+            << ") mismatch for image '" << images[0] << "', but must be equal";
+        throw std::runtime_error(err.str());
+      }
+
+      if (has_attributes && ids.size() != attributes.size()) {
+        std::ostringstream err;
+        err << "Number of ids (" << ids.size() <<  ") and attributes (" << attributes.size()
+            << ") mismatch for image '" << images[0] << "', but must be equal";
+        throw std::runtime_error(err.str());
+      }
+
+      if (has_datas && ids.size() != datas.size()) {
+        std::ostringstream err;
+        err << "Number of ids (" << ids.size() <<  ") and datas (" << datas.size()
+            << ") mismatch for image '" << images[0] << "', but must be equal";
+        throw std::runtime_error(err.str());
+      }
+
+      for(std::vector<uint32_t>::size_type i = 0; i < ids.size() && i < width*height; ++i) {
+        if (ids[i] == 0)
+          continue;
+
+        if(ids[i] >= m_tileset.tiles.size())
+          m_tileset.tiles.resize(ids[i]+1, 0);
+
+        int x = 32*(i % width);
+        int y = 32*(i / width);
+        std::auto_ptr<Tile> tile(new Tile(m_tileset, images, Rect(x, y, x + 32, y + 32),
+                                          (has_attributes ? attributes[i] : 0), (has_datas ? datas[i] : 0), animfps));
+        if (m_tileset.tiles[ids[i]] == 0) {
+          m_tileset.tiles[ids[i]] = tile.release();
+        } else {
+          log_warning << "Tile with ID " << ids[i] << " redefined" << std::endl;
+        }
+      }
+    } else if(iter.item() == "properties") {
+      // deprecated
+    } else {
+      log_warning << "Unknown symbol '" << iter.item() << "' in tileset file" << std::endl;
+    }
+  }
+}
+
+/* EOF */
diff --git a/src/supertux/tile_set_parser.hpp b/src/supertux/tile_set_parser.hpp
new file mode 100644 (file)
index 0000000..71c2482
--- /dev/null
@@ -0,0 +1,43 @@
+//  SuperTux
+//  Copyright (C) 2008 Matthias Braun <matze@braunis.de>,
+//                     Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_SUPERTUX_TILE_SET_PARSER_HPP
+#define HEADER_SUPERTUX_SUPERTUX_TILE_SET_PARSER_HPP
+
+#include <string>
+
+class TileSet;
+
+class TileSetParser
+{
+private:
+  TileSet&    m_tileset;
+  std::string m_filename;
+  
+public:
+  TileSetParser(TileSet& tileset, const std::string& filename);
+  
+  void parse();
+
+private:
+  TileSetParser(const TileSetParser&);
+  TileSetParser& operator=(const TileSetParser&);
+};
+
+#endif
+
+/* EOF */