1 // Copyright (C) 2003 Michael Bartl
2 // Copyright (C) 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Library General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 #include <sigc++/functors/mem_fun.h>
27 #include "SmallTile.h"
28 #include "xmlhelper.h"
29 #include "gui/image-helpers.h"
30 #include "GraphicsCache.h"
31 #include "tilesetlist.h"
36 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
39 #define DEFAULT_TILE_SIZE 40
41 std::string Tileset::d_tag = "tileset";
42 std::string Tileset::d_road_smallmap_tag = "road_smallmap";
43 std::string Tileset::file_extension = TILESET_EXT;
45 Tileset::Tileset(guint32 id, std::string name)
46 : Set(), d_name(name), d_copyright(""), d_license(""), d_id(id),
47 d_tileSize(DEFAULT_TILE_SIZE), d_subdir("")
50 d_large_selector = "";
51 d_small_selector = "";
56 d_road_color.set_rgb_p(0,0,0);
57 for (unsigned int i = 0; i < ROAD_TYPES; i++)
59 for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
61 for (unsigned int i = 0; i < FLAG_TYPES; i++)
63 for (unsigned int i = 0; i < FLAG_TYPES; i++)
65 number_of_selector_frames = 0;
68 number_of_small_selector_frames = 0;
69 smallselector.clear();
70 smallselectormask.clear();
72 for (unsigned int i = 0; i < FOG_TYPES; i++)
76 Tileset::Tileset(XML_Helper *helper, std::string directory)
79 setDirectory(directory);
80 helper->getData(d_id, "id");
81 helper->getData(d_name, "name");
82 helper->getData(d_copyright, "copyright");
83 helper->getData(d_license, "license");
84 helper->getData(d_info, "info");
85 helper->getData(d_tileSize, "tilesize");
86 helper->getData(d_large_selector, "large_selector");
87 helper->getData(d_small_selector, "small_selector");
88 helper->getData(d_explosion, "explosion");
89 helper->getData(d_roads, "roads");
90 helper->getData(d_bridges, "bridges");
91 helper->getData(d_fog, "fog");
92 helper->getData(d_flags, "flags");
93 helper->registerTag(Tile::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
94 helper->registerTag(Tileset::d_road_smallmap_tag, sigc::mem_fun((*this), &Tileset::loadTile));
95 helper->registerTag(SmallTile::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
96 helper->registerTag(TileStyle::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
97 helper->registerTag(TileStyleSet::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
98 for (unsigned int i = 0; i < ROAD_TYPES; i++)
100 for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
102 for (unsigned int i = 0; i < FLAG_TYPES; i++)
104 for (unsigned int i = 0; i < FLAG_TYPES; i++)
106 number_of_selector_frames = 0;
108 selectormask.clear();
109 number_of_small_selector_frames = 0;
110 smallselector.clear();
111 smallselectormask.clear();
113 for (unsigned int i = 0; i < FOG_TYPES; i++)
119 uninstantiateImages();
120 for (unsigned int i=0; i < size(); i++)
124 int Tileset::getIndex(Tile::Type type) const
126 for (guint32 i = 0; i < size(); i++)
127 if (type == (*this)[i]->getType())
134 bool Tileset::loadTile(string tag, XML_Helper* helper)
138 if (tag == Tile::d_tag)
140 // create a new tile with the information we got
141 Tile* tile = new Tile(helper);
142 this->push_back(tile);
147 if (tag == Tileset::d_road_smallmap_tag)
149 helper->getData(d_road_color, "color");
153 if (tag == SmallTile::d_tag)
155 Tile *tile = this->back();
156 SmallTile* smalltile = new SmallTile(helper);
157 tile->setSmallTile(smalltile);
161 if (tag == TileStyle::d_tag)
163 Tile *tile = this->back();
164 TileStyleSet *tilestyleset = tile->back();
165 // create a new tile style with the information we got
166 // put it on the latest tilestyleset
167 TileStyle* tilestyle = new TileStyle(helper);
168 tilestyleset->push_back(tilestyle);
169 d_tilestyles[tilestyle->getId()] = tilestyle;
174 if (tag == TileStyleSet::d_tag)
176 Tile *tile = this->back();
177 // create a new tile style set with the information we got
178 // put it on the latest tile
179 TileStyleSet* tilestyleset = new TileStyleSet(helper);
180 tilestyleset->setSubDir(getSubDir());
181 tile->push_back(tilestyleset);
188 TileStyle *Tileset::getRandomTileStyle(guint32 index, TileStyle::Type style) const
190 Tile *tile = (*this)[index];
192 return tile->getRandomTileStyle (style);
197 bool Tileset::save(XML_Helper *helper) const
201 retval &= helper->openTag(d_tag);
202 retval &= helper->saveData("id", d_id);
203 retval &= helper->saveData("name", d_name);
204 retval &= helper->saveData("copyright", d_copyright);
205 retval &= helper->saveData("license", d_license);
206 retval &= helper->saveData("info", d_info);
207 retval &= helper->saveData("tilesize", d_tileSize);
208 retval &= helper->saveData("large_selector", d_large_selector);
209 retval &= helper->saveData("small_selector", d_small_selector);
210 retval &= helper->saveData("explosion", d_explosion);
211 retval &= helper->saveData("roads", d_roads);
212 retval &= helper->saveData("bridges", d_bridges);
213 retval &= helper->saveData("fog", d_fog);
214 retval &= helper->saveData("flags", d_flags);
215 retval &= helper->openTag(d_road_smallmap_tag);
216 retval &= helper->saveData("color", d_road_color);
217 retval &= helper->closeTag();
218 for (Tileset::const_iterator i = begin(); i != end(); ++i)
219 retval &= (*i)->save(helper);
220 retval &= helper->closeTag();
225 int Tileset::getFreeTileStyleId() const
228 memset (ids, 0, sizeof (ids));
229 for (Tileset::const_iterator i = begin(); i != end(); ++i)
231 for (std::list<TileStyleSet*>::const_iterator j = (*i)->begin(); j != (*i)->end(); j++)
233 for (std::vector<TileStyle*>::const_iterator k = (*j)->begin(); k != (*j)->end(); k++)
235 ids[(*k)->getId()] = 1;
239 //these ids range from 0 to 65535.
240 for (unsigned int i = 0; i <= 65535; i++)
248 int Tileset::getLargestTileStyleId() const
250 unsigned int largest = 0;
251 for (Tileset::const_iterator i = begin(); i != end(); ++i)
253 for (std::list<TileStyleSet*>::const_iterator j = (*i)->begin(); j != (*i)->end(); j++)
255 for (std::vector<TileStyle*>::const_iterator k = (*j)->begin(); k != (*j)->end(); k++)
257 if ((*k)->getId() > largest)
258 largest = (*k)->getId();
265 void Tileset::setSubDir(std::string dir)
268 for (Tileset::iterator i = begin(); i != end(); ++i)
269 for (Tile::iterator j = (*i)->begin(); j != (*i)->end(); j++)
270 (*j)->setSubDir(dir);
273 guint32 Tileset::getDefaultTileSize()
275 return DEFAULT_TILE_SIZE;
278 bool Tileset::validate() const
282 for (Tileset::const_iterator i = begin(); i != end(); i++)
284 if ((*i)->validate() == false)
286 fprintf (stderr, "`%s' fails validation\n",
287 (*i)->getName().c_str());
297 TilesetLoader(std::string filename)
300 dir = File::get_dirname(filename);
301 if (File::nameEndsWith(filename, Tileset::file_extension) == false)
302 filename += Tileset::file_extension;
303 XML_Helper helper(filename, ios::in, false);
304 helper.registerTag(Tileset::d_tag, sigc::mem_fun((*this), &TilesetLoader::load));
307 std::cerr << "Error, while loading an tileset. Tileset Name: ";
308 std::cerr <<dir<<std::endl <<std::flush;
314 bool load(std::string tag, XML_Helper* helper)
316 if (tag == Tileset::d_tag)
318 tileset = new Tileset(helper, dir);
326 Tileset *Tileset::create(std::string file)
328 TilesetLoader d(file);
331 void Tileset::getFilenames(std::list<std::string> &files)
333 for (iterator it = begin(); it != end(); it++)
336 for (Tile::iterator sit = t->begin(); sit != t->end(); sit++)
338 std::string file = (*sit)->getName();
339 if (std::find(files.begin(), files.end(), file) == files.end())
340 files.push_back(file);
343 files.push_back(d_small_selector);
344 files.push_back(d_large_selector);
345 files.push_back(d_explosion);
346 files.push_back(d_fog);
347 files.push_back(d_roads);
348 files.push_back(d_bridges);
349 files.push_back(d_flags);
352 void Tileset::uninstantiateImages()
354 for (iterator it = begin(); it != end(); it++)
355 (*it)->uninstantiateImages();
357 if (getExplosionImage() != NULL)
359 delete getExplosionImage();
360 setExplosionImage(NULL);
362 for (unsigned int i = 0; i < ROAD_TYPES; i++)
364 if (getRoadImage(i) != NULL)
366 delete getRoadImage(i);
367 setRoadImage(i, NULL);
370 for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
372 if (getBridgeImage(i) != NULL)
374 delete getBridgeImage(i);
375 setBridgeImage(i, NULL);
378 for (unsigned int i = 0; i < FOG_TYPES; i++)
380 if (getFogImage(i) != NULL)
382 delete getFogImage(i);
383 setFogImage(i, NULL);
386 for (unsigned int i = 0; i < getNumberOfSelectorFrames(); i++)
388 if (getSelectorImage(i) != NULL)
390 delete getSelectorImage(i);
391 setSelectorImage(i, NULL);
394 for (unsigned int i = 0; i < getNumberOfSmallSelectorFrames(); i++)
396 if (getSmallSelectorImage(i) != NULL)
398 delete getSmallSelectorImage(i);
399 setSmallSelectorImage(i, NULL);
402 for (unsigned int i = 0; i < getNumberOfSmallSelectorFrames(); i++)
404 if (getSmallSelectorMask(i) != NULL)
406 delete getSmallSelectorMask(i);
407 setSmallSelectorMask(i, NULL);
410 for (unsigned int i = 0; i < FLAG_TYPES; i++)
412 if (getFlagImage(i) != NULL)
414 delete getFlagImage(i);
415 setFlagImage(i, NULL);
418 for (unsigned int i = 0; i < FLAG_TYPES; i++)
420 if (getFlagMask(i) != NULL)
422 delete getFlagMask(i);
423 setFlagMask(i, NULL);
428 void Tileset::instantiateImages(std::string explosion_filename,
429 std::string roads_filename,
430 std::string bridges_filename,
431 std::string fog_filename,
432 std::string flags_filename,
433 std::string selector_filename,
434 std::string small_selector_filename)
436 if (explosion_filename.empty() == false)
437 setExplosionImage (PixMask::create(explosion_filename));
439 if (roads_filename.empty() == false)
441 std::vector<PixMask* > roadpics;
442 roadpics = disassemble_row(roads_filename, ROAD_TYPES);
443 for (unsigned int i = 0; i < ROAD_TYPES ; i++)
445 if (roadpics[i]->get_width() != (int)d_tileSize)
446 PixMask::scale(roadpics[i], d_tileSize, d_tileSize);
447 setRoadImage(i, roadpics[i]);
451 if (bridges_filename.empty() == false)
453 std::vector<PixMask* > bridgepics;
454 bridgepics = disassemble_row(bridges_filename, BRIDGE_TYPES);
455 for (unsigned int i = 0; i < BRIDGE_TYPES ; i++)
457 if (bridgepics[i]->get_width() != (int)d_tileSize)
458 PixMask::scale(bridgepics[i], d_tileSize, d_tileSize);
459 setBridgeImage(i, bridgepics[i]);
463 if (fog_filename.empty() == false)
465 std::vector<PixMask* > fogpics;
466 fogpics = disassemble_row(fog_filename, FOG_TYPES);
467 for (unsigned int i = 0; i < FOG_TYPES ; i++)
469 if (fogpics[i]->get_width() != (int)d_tileSize)
470 PixMask::scale(fogpics[i], d_tileSize, d_tileSize);
471 setFogImage(i, fogpics[i]);
475 if (flags_filename.empty() == false)
477 std::vector<PixMask* > flagpics;
478 std::vector<PixMask* > maskpics;
479 GraphicsCache::loadFlagImages (flags_filename, d_tileSize,
481 for (unsigned int i = 0; i < flagpics.size(); i++)
482 setFlagImage(i, flagpics[i]);
483 for (unsigned int i = 0; i < maskpics.size(); i++)
484 setFlagMask(i, maskpics[i]);
488 std::vector<PixMask* > images;
489 std::vector<PixMask* > masks;
490 if (selector_filename.empty() == false)
492 GraphicsCache::loadSelectorImages (selector_filename, d_tileSize,
494 setNumberOfSelectorFrames(images.size());
495 for (unsigned int i = 0; i < images.size(); i++)
497 setSelectorImage(i, images[i]);
498 setSelectorMask(i, masks[i]);
504 if (small_selector_filename.empty() == false)
506 GraphicsCache::loadSelectorImages (small_selector_filename, d_tileSize,
508 setNumberOfSmallSelectorFrames(images.size());
509 for (unsigned int i = 0; i < images.size(); i++)
511 setSmallSelectorImage(i, images[i]);
512 setSmallSelectorMask(i, masks[i]);
517 void Tileset::instantiateImages()
519 int size = getTileSize();
520 debug("Loading images for tileset " << getName());
521 uninstantiateImages();
522 for (iterator it = begin(); it != end(); it++)
523 (*it)->instantiateImages(size, this);
524 std::string explosion_filename = "";
525 std::string roads_filename = "";
526 std::string bridges_filename = "";
527 std::string fog_filename = "";
528 std::string flags_filename = "";
529 std::string selector_filename = "";
530 std::string small_selector_filename = "";
532 if (getExplosionFilename().empty() == false)
533 explosion_filename = getFile(getExplosionFilename());
534 if (getRoadsFilename().empty() == false)
535 roads_filename = getFile(getRoadsFilename());
536 if (getBridgesFilename().empty() == false)
537 bridges_filename = getFile(getBridgesFilename());
538 if (getFogFilename().empty() == false)
539 fog_filename = getFile(getFogFilename());
540 if (getFlagsFilename().empty() == false)
541 flags_filename = getFile(getFlagsFilename());
542 if (getLargeSelectorFilename().empty() == false)
543 selector_filename = getFile(getLargeSelectorFilename());
544 if (getSmallSelectorFilename().empty() == false)
545 small_selector_filename = getFile(getSmallSelectorFilename());
546 instantiateImages(explosion_filename, roads_filename, bridges_filename,
547 fog_filename, flags_filename, selector_filename,
548 small_selector_filename);
551 std::string Tileset::getConfigurationFile() const
553 return getDirectory() + d_subdir + file_extension;
556 std::list<std::string> Tileset::scanUserCollection()
558 return File::scanFiles(File::getUserTilesetDir(), file_extension);
561 std::list<std::string> Tileset::scanSystemCollection()
563 std::list<std::string> retlist = File::scanFiles(File::getTilesetDir(),
567 std::cerr << "Couldn't find any tilesets!" << std::endl;
568 std::cerr << "Please check the path settings in /etc/lordsawarrc or ~/.lordsawarrc" << std::endl;
569 std::cerr << "Exiting!" << std::endl;
576 TileStyle *Tileset::getTileStyle(guint32 id) const
578 TileStyleIdMap::const_iterator it = d_tilestyles.find(id);
579 if (it == d_tilestyles.end())