#include <tile_set_parser.hpp>
Public Member Functions | |
TileSetParser (TileSet &tileset, const std::string &filename) | |
void | parse () |
Private Member Functions | |
void | parse_tile (const Reader &reader) |
void | parse_tiles (const Reader &reader) |
std::vector< Tile::ImageSpec > | parse_tile_images (const Reader &cur) |
TileSetParser (const TileSetParser &) | |
TileSetParser & | operator= (const TileSetParser &) |
Private Attributes | |
TileSet & | m_tileset |
std::string | m_filename |
std::string | m_tiles_path |
Definition at line 31 of file tile_set_parser.hpp.
TileSetParser::TileSetParser | ( | TileSet & | tileset, | |
const std::string & | filename | |||
) |
Definition at line 28 of file tile_set_parser.cpp.
00028 : 00029 m_tileset(tileset), 00030 m_filename(filename), 00031 m_tiles_path() 00032 { 00033 }
TileSetParser::TileSetParser | ( | const TileSetParser & | ) | [private] |
void TileSetParser::parse | ( | ) |
Definition at line 36 of file tile_set_parser.cpp.
References FileSystem::dirname(), lisp::Lisp::get_lisp(), lisp::ListIterator::item(), lisp::ListIterator::lisp(), log_warning, m_filename, m_tiles_path, m_tileset, lisp::ListIterator::next(), lisp::Parser::parse(), parse_tile(), parse_tiles(), and TileSet::tiles.
Referenced by TileSet::TileSet().
00037 { 00038 m_tiles_path = FileSystem::dirname(m_filename); 00039 00040 m_tileset.tiles.resize(1, 0); 00041 m_tileset.tiles[0] = new Tile(); 00042 00043 lisp::Parser parser; 00044 const lisp::Lisp* root = parser.parse(m_filename); 00045 00046 const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles"); 00047 if(!tiles_lisp) 00048 throw std::runtime_error("file is not a supertux tiles file."); 00049 00050 lisp::ListIterator iter(tiles_lisp); 00051 while(iter.next()) 00052 { 00053 if (iter.item() == "tile") 00054 { 00055 parse_tile(*iter.lisp()); 00056 } 00057 else if (iter.item() == "tilegroup") 00058 { 00059 /* tilegroups are only interesting for the editor */ 00060 } 00061 else if (iter.item() == "tiles") 00062 { 00063 parse_tiles(*iter.lisp()); 00064 } 00065 else 00066 { 00067 log_warning << "Unknown symbol '" << iter.item() << "' in tileset file" << std::endl; 00068 } 00069 } 00070 }
void TileSetParser::parse_tile | ( | const Reader & | reader | ) | [private] |
Definition at line 73 of file tile_set_parser.cpp.
References Tile::BRICK, Tile::COIN, Tile::FIRE, Tile::FULLBOX, lisp::Lisp::get(), lisp::Lisp::get_lisp(), Tile::GOAL, Tile::HURTS, Tile::ICE, log_warning, m_tileset, parse_tile_images(), Tile::SLOPE, Tile::SOLID, TileSet::tiles, Tile::UNISOLID, Tile::WATER, Tile::WORLDMAP_EAST, Tile::WORLDMAP_NORTH, Tile::WORLDMAP_SOUTH, Tile::WORLDMAP_STOP, and Tile::WORLDMAP_WEST.
Referenced by parse().
00074 { 00075 uint32_t id; 00076 if (!reader.get("id", id)) 00077 { 00078 throw std::runtime_error("Missing tile-id."); 00079 } 00080 00081 uint32_t attributes = 0; 00082 00083 bool value = false; 00084 if(reader.get("solid", value) && value) 00085 attributes |= Tile::SOLID; 00086 if(reader.get("unisolid", value) && value) 00087 attributes |= Tile::UNISOLID | Tile::SOLID; 00088 if(reader.get("brick", value) && value) 00089 attributes |= Tile::BRICK; 00090 if(reader.get("ice", value) && value) 00091 attributes |= Tile::ICE; 00092 if(reader.get("water", value) && value) 00093 attributes |= Tile::WATER; 00094 if(reader.get("hurts", value) && value) 00095 attributes |= Tile::HURTS; 00096 if(reader.get("fire", value) && value) 00097 attributes |= Tile::FIRE; 00098 if(reader.get("fullbox", value) && value) 00099 attributes |= Tile::FULLBOX; 00100 if(reader.get("coin", value) && value) 00101 attributes |= Tile::COIN; 00102 if(reader.get("goal", value) && value) 00103 attributes |= Tile::GOAL; 00104 00105 uint32_t data = 0; 00106 00107 if(reader.get("north", value) && value) 00108 data |= Tile::WORLDMAP_NORTH; 00109 if(reader.get("south", value) && value) 00110 data |= Tile::WORLDMAP_SOUTH; 00111 if(reader.get("west", value) && value) 00112 data |= Tile::WORLDMAP_WEST; 00113 if(reader.get("east", value) && value) 00114 data |= Tile::WORLDMAP_EAST; 00115 if(reader.get("stop", value) && value) 00116 data |= Tile::WORLDMAP_STOP; 00117 00118 reader.get("data", data); 00119 00120 float fps = 10; 00121 reader.get("fps", fps); 00122 00123 if(reader.get("slope-type", data)) 00124 { 00125 attributes |= Tile::SOLID | Tile::SLOPE; 00126 } 00127 00128 std::vector<Tile::ImageSpec> editor_imagespecs; 00129 const lisp::Lisp* editor_images; 00130 editor_images = reader.get_lisp("editor-images"); 00131 if(editor_images) 00132 editor_imagespecs = parse_tile_images(*editor_images); 00133 00134 std::vector<Tile::ImageSpec> imagespecs; 00135 const lisp::Lisp* images; 00136 images = reader.get_lisp("images"); 00137 if(images) 00138 imagespecs = parse_tile_images(*images); 00139 00140 std::auto_ptr<Tile> tile(new Tile(imagespecs, editor_imagespecs, attributes, data, fps)); 00141 00142 if (id >= m_tileset.tiles.size()) 00143 m_tileset.tiles.resize(id+1, 0); 00144 00145 if (m_tileset.tiles[id] != 0) 00146 { 00147 log_warning << "Tile with ID " << id << " redefined" << std::endl; 00148 } 00149 else 00150 { 00151 m_tileset.tiles[id] = tile.release(); 00152 } 00153 }
void TileSetParser::parse_tiles | ( | const Reader & | reader | ) | [private] |
Definition at line 201 of file tile_set_parser.cpp.
References lisp::Lisp::get(), log_warning, m_tiles_path, m_tileset, and TileSet::tiles.
Referenced by parse().
00202 { 00203 // List of ids (use 0 if the tile should be ignored) 00204 std::vector<uint32_t> ids; 00205 // List of attributes of the tile 00206 std::vector<uint32_t> attributes; 00207 // List of data for the tiles 00208 std::vector<uint32_t> datas; 00209 //List of frames that the tiles come in 00210 std::vector<std::string> images; 00211 //List of frames that the editor tiles come in 00212 std::vector<std::string> editor_images; 00213 // Name used to report errors. 00214 std::string image_name; 00215 00216 // width and height of the image in tile units, this is used for two 00217 // purposes: 00218 // a) so we don't have to load the image here to know its dimensions 00219 // b) so that the resulting 'tiles' entry is more robust, 00220 // ie. enlarging the image won't break the tile id mapping 00221 // FIXME: height is actually not used, since width might be enough for 00222 // all purposes, still feels somewhat more natural this way 00223 unsigned int width = 0; 00224 unsigned int height = 0; 00225 00226 reader.get("ids", ids); 00227 bool has_attributes = reader.get("attributes", attributes); 00228 bool has_datas = reader.get("datas", datas); 00229 00230 reader.get("image", images) || reader.get("images", images); 00231 reader.get("editor-images", editor_images); 00232 00233 if (images.size() > 0) 00234 image_name = images[0]; 00235 else 00236 image_name = "(no image)"; 00237 00238 reader.get("width", width); 00239 reader.get("height", height); 00240 00241 float fps = 10; 00242 reader.get("fps", fps); 00243 00244 if (width <= 0) 00245 { 00246 throw std::runtime_error("Width is zero."); 00247 } 00248 else if (height <= 0) 00249 { 00250 throw std::runtime_error("Height is zero."); 00251 } 00252 else if (fps < 0) 00253 { 00254 throw std::runtime_error("Negative fps."); 00255 } 00256 else if (ids.size() != width*height) 00257 { 00258 std::ostringstream err; 00259 err << "Number of ids (" << ids.size() << ") and " 00260 "dimensions of image (" << width << "x" << height << " = " << width*height << ") " 00261 "differ for image " << image_name; 00262 throw std::runtime_error(err.str()); 00263 } 00264 else if (has_attributes && (ids.size() != attributes.size())) 00265 { 00266 std::ostringstream err; 00267 err << "Number of ids (" << ids.size() << ") and attributes (" << attributes.size() 00268 << ") mismatch for image '" << image_name << "', but must be equal"; 00269 throw std::runtime_error(err.str()); 00270 } 00271 else if (has_datas && ids.size() != datas.size()) 00272 { 00273 std::ostringstream err; 00274 err << "Number of ids (" << ids.size() << ") and datas (" << datas.size() 00275 << ") mismatch for image '" << image_name << "', but must be equal"; 00276 throw std::runtime_error(err.str()); 00277 } 00278 else 00279 { 00280 for(std::vector<uint32_t>::size_type i = 0; i < ids.size() && i < width*height; ++i) 00281 { 00282 if (ids[i] != 0) 00283 { 00284 if (ids[i] >= m_tileset.tiles.size()) 00285 m_tileset.tiles.resize(ids[i]+1, 0); 00286 00287 int x = 32*(i % width); 00288 int y = 32*(i / width); 00289 00290 std::vector<Tile::ImageSpec> imagespecs; 00291 for(std::vector<std::string>::const_iterator j = images.begin(); j != images.end(); ++j) 00292 { 00293 imagespecs.push_back(Tile::ImageSpec(m_tiles_path + *j, Rectf(x, y, x + 32, y + 32))); 00294 } 00295 00296 std::vector<Tile::ImageSpec> editor_imagespecs; 00297 for(std::vector<std::string>::const_iterator j = editor_images.begin(); j != editor_images.end(); ++j) 00298 { 00299 editor_imagespecs.push_back(Tile::ImageSpec(m_tiles_path + *j, Rectf(x, y, x + 32, y + 32))); 00300 } 00301 00302 std::auto_ptr<Tile> tile(new Tile(imagespecs, editor_imagespecs, 00303 (has_attributes ? attributes[i] : 0), (has_datas ? datas[i] : 0), fps)); 00304 if (m_tileset.tiles[ids[i]] == 0) { 00305 m_tileset.tiles[ids[i]] = tile.release(); 00306 } else { 00307 log_warning << "Tile with ID " << ids[i] << " redefined" << std::endl; 00308 } 00309 } 00310 } 00311 } 00312 }
std::vector< Tile::ImageSpec > TileSetParser::parse_tile_images | ( | const Reader & | cur | ) | [private] |
Definition at line 156 of file tile_set_parser.cpp.
References lisp::Lisp::get(), lisp::Lisp::get_car(), lisp::Lisp::get_cdr(), lisp::Lisp::get_type(), log_warning, m_tiles_path, lisp::Lisp::TYPE_CONS, lisp::Lisp::TYPE_STRING, and lisp::Lisp::TYPE_SYMBOL.
Referenced by parse_tile().
00157 { 00158 std::vector<Tile::ImageSpec> imagespecs; 00159 00160 const lisp::Lisp* list = &images_lisp; 00161 while(list) 00162 { 00163 const lisp::Lisp* cur = list->get_car(); 00164 00165 if(cur->get_type() == lisp::Lisp::TYPE_STRING) 00166 { 00167 std::string file; 00168 cur->get(file); 00169 imagespecs.push_back(Tile::ImageSpec(m_tiles_path + file, Rectf(0, 0, 0, 0))); 00170 } 00171 else if(cur->get_type() == lisp::Lisp::TYPE_CONS && 00172 cur->get_car()->get_type() == lisp::Lisp::TYPE_SYMBOL && 00173 cur->get_car()->get_symbol() == "region") 00174 { 00175 const lisp::Lisp* ptr = cur->get_cdr(); 00176 00177 std::string file; 00178 float x = 0; 00179 float y = 0; 00180 float w = 0; 00181 float h = 0; 00182 ptr->get_car()->get(file); ptr = ptr->get_cdr(); 00183 ptr->get_car()->get(x); ptr = ptr->get_cdr(); 00184 ptr->get_car()->get(y); ptr = ptr->get_cdr(); 00185 ptr->get_car()->get(w); ptr = ptr->get_cdr(); 00186 ptr->get_car()->get(h); 00187 imagespecs.push_back(Tile::ImageSpec(m_tiles_path + file, Rectf(x, y, x+w, y+h))); 00188 } 00189 else 00190 { 00191 log_warning << "Expected string or list in images tag" << std::endl; 00192 } 00193 00194 list = list->get_cdr(); 00195 } 00196 00197 return imagespecs; 00198 }
TileSetParser& TileSetParser::operator= | ( | const TileSetParser & | ) | [private] |
TileSet& TileSetParser::m_tileset [private] |
Definition at line 34 of file tile_set_parser.hpp.
Referenced by parse(), parse_tile(), and parse_tiles().
std::string TileSetParser::m_filename [private] |
std::string TileSetParser::m_tiles_path [private] |
Definition at line 36 of file tile_set_parser.hpp.
Referenced by parse(), parse_tile_images(), and parse_tiles().