From 32fc6915c02b75014fc79d7b55f759c8703ca8f0 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Sun, 6 Dec 2009 00:17:49 +0000 Subject: [PATCH] Started moving TileSet parsing code into separate class SVN-Revision: 6172 --- src/supertux/tile.cpp | 6 +- src/supertux/tile.hpp | 6 +- src/supertux/tile_set.cpp | 116 ++---------------------------- src/supertux/tile_set.hpp | 2 + src/supertux/tile_set_parser.cpp | 151 +++++++++++++++++++++++++++++++++++++++ src/supertux/tile_set_parser.hpp | 43 +++++++++++ 6 files changed, 207 insertions(+), 117 deletions(-) create mode 100644 src/supertux/tile_set_parser.cpp create mode 100644 src/supertux/tile_set_parser.hpp diff --git a/src/supertux/tile.cpp b/src/supertux/tile.cpp index 8ce0755a6..65a74c5c1 100644 --- a/src/supertux/tile.cpp +++ b/src/supertux/tile.cpp @@ -22,7 +22,7 @@ #include "util/reader.hpp" #include "video/drawing_context.hpp" -Tile::Tile(const TileSet *new_tileset) : +Tile::Tile(const TileSet& new_tileset) : tileset(new_tileset), imagespecs(), images(), @@ -32,7 +32,7 @@ Tile::Tile(const TileSet *new_tileset) : { } -Tile::Tile(const TileSet *new_tileset, std::vector images, Rect rect, +Tile::Tile(const TileSet& new_tileset, std::vector 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::iterator i = imagespecs.begin(); i != diff --git a/src/supertux/tile.hpp b/src/supertux/tile.hpp index 64636316b..2611a8a51 100644 --- a/src/supertux/tile.hpp +++ b/src/supertux/tile.hpp @@ -95,7 +95,7 @@ public: }; private: - const TileSet *tileset; + const TileSet& tileset; std::vector imagespecs; std::vector images; @@ -108,8 +108,8 @@ private: float anim_fps; public: - Tile(const TileSet* tileset); - Tile(const TileSet* tileset, std::vector images, Rect rect, + Tile(const TileSet& tileset); + Tile(const TileSet& tileset, std::vector images, Rect rect, uint32_t attributes, uint32_t data, float animfps); ~Tile(); diff --git a/src/supertux/tile_set.cpp b/src/supertux/tile_set.cpp index c816d36f5..f1a326e2f 100644 --- a/src/supertux/tile_set.cpp +++ b/src/supertux/tile_set.cpp @@ -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(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 ids; - // List of attributes of the tile - std::vector attributes; - // List of data for the tiles - std::vector datas; - //List of frames that the tiles come in - std::vector 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::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(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 diff --git a/src/supertux/tile_set.hpp b/src/supertux/tile_set.hpp index 8c4410e20..54f9b5978 100644 --- a/src/supertux/tile_set.hpp +++ b/src/supertux/tile_set.hpp @@ -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 index 000000000..8a11e52c3 --- /dev/null +++ b/src/supertux/tile_set_parser.cpp @@ -0,0 +1,151 @@ +// SuperTux +// Copyright (C) 2008 Matthias Braun +// Ingo Ruhnke +// +// 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 . + +#include "supertux/tile_set_parser.hpp" + +#include +#include + +#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(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 ids; + // List of attributes of the tile + std::vector attributes; + // List of data for the tiles + std::vector datas; + //List of frames that the tiles come in + std::vector 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::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(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 index 000000000..71c2482be --- /dev/null +++ b/src/supertux/tile_set_parser.hpp @@ -0,0 +1,43 @@ +// SuperTux +// Copyright (C) 2008 Matthias Braun , +// Ingo Ruhnke +// +// 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 . + +#ifndef HEADER_SUPERTUX_SUPERTUX_TILE_SET_PARSER_HPP +#define HEADER_SUPERTUX_SUPERTUX_TILE_SET_PARSER_HPP + +#include + +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 */ -- 2.11.0