initial commit, lordsawar source, slightly modified
[lordsawar] / src / tileset.cpp
diff --git a/src/tileset.cpp b/src/tileset.cpp
new file mode 100644 (file)
index 0000000..9495f7f
--- /dev/null
@@ -0,0 +1,584 @@
+// Copyright (C) 2003 Michael Bartl
+// Copyright (C) 2003, 2004, 2005, 2006 Ulf Lorenz
+// Copyright (C) 2007, 2008, 2009 Ben Asselstine
+//
+//  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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#include <sigc++/functors/mem_fun.h>
+#include <string.h>
+
+#include "tileset.h"
+
+#include "defs.h"
+#include "File.h"
+#include "SmallTile.h"
+#include "xmlhelper.h"
+#include "gui/image-helpers.h"
+#include "GraphicsCache.h"
+#include "tilesetlist.h"
+
+using namespace std;
+
+#include <iostream>
+//#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
+#define debug(x)
+
+#define DEFAULT_TILE_SIZE 40
+
+std::string Tileset::d_tag = "tileset";
+std::string Tileset::d_road_smallmap_tag = "road_smallmap";
+std::string Tileset::file_extension = TILESET_EXT;
+
+Tileset::Tileset(guint32 id, std::string name)
+       : Set(), d_name(name), d_copyright(""), d_license(""), d_id(id), 
+       d_tileSize(DEFAULT_TILE_SIZE), d_subdir("")
+{
+  d_info = "";
+  d_large_selector = "";
+  d_small_selector = "";
+  d_fog = "";
+  d_roads = "";
+  d_bridges = "";
+  d_flags = "";
+  d_road_color.set_rgb_p(0,0,0);
+  for (unsigned int i = 0; i < ROAD_TYPES; i++)
+    roadpic[i] = NULL;
+  for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
+    bridgepic[i] = NULL;
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    flagpic[i] = NULL;
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    flagmask[i] = NULL;
+  number_of_selector_frames = 0;
+  selector.clear();
+  selectormask.clear();
+  number_of_small_selector_frames = 0;
+  smallselector.clear();
+  smallselectormask.clear();
+  explosion = NULL;
+  for (unsigned int i = 0; i < FOG_TYPES; i++)
+    fogpic[i] = NULL;
+}
+
+Tileset::Tileset(XML_Helper *helper, std::string directory)
+       :Set()
+{
+  setDirectory(directory);
+  helper->getData(d_id, "id"); 
+  helper->getData(d_name, "name"); 
+  helper->getData(d_copyright, "copyright"); 
+  helper->getData(d_license, "license"); 
+  helper->getData(d_info, "info");
+  helper->getData(d_tileSize, "tilesize");
+  helper->getData(d_large_selector, "large_selector");
+  helper->getData(d_small_selector, "small_selector");
+  helper->getData(d_explosion, "explosion");
+  helper->getData(d_roads, "roads");
+  helper->getData(d_bridges, "bridges");
+  helper->getData(d_fog, "fog");
+  helper->getData(d_flags, "flags");
+  helper->registerTag(Tile::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
+  helper->registerTag(Tileset::d_road_smallmap_tag, sigc::mem_fun((*this), &Tileset::loadTile));
+  helper->registerTag(SmallTile::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
+  helper->registerTag(TileStyle::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
+  helper->registerTag(TileStyleSet::d_tag, sigc::mem_fun((*this), &Tileset::loadTile));
+  for (unsigned int i = 0; i < ROAD_TYPES; i++)
+    roadpic[i] = NULL;
+  for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
+    bridgepic[i] = NULL;
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    flagpic[i] = NULL;
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    flagmask[i] = NULL;
+  number_of_selector_frames = 0;
+  selector.clear();
+  selectormask.clear();
+  number_of_small_selector_frames = 0;
+  smallselector.clear();
+  smallselectormask.clear();
+  explosion = NULL;
+  for (unsigned int i = 0; i < FOG_TYPES; i++)
+    fogpic[i] = NULL;
+}
+
+Tileset::~Tileset()
+{
+  uninstantiateImages();
+  for (unsigned int i=0; i < size(); i++)
+    delete (*this)[i];
+}
+
+int Tileset::getIndex(Tile::Type type) const
+{
+  for (guint32 i = 0; i < size(); i++)
+    if (type == (*this)[i]->getType())
+      return i;
+
+  // catch errors?
+  return -1;
+}
+
+bool Tileset::loadTile(string tag, XML_Helper* helper)
+{
+  debug("loadTile()")
+
+    if (tag == Tile::d_tag)
+      {
+       // create a new tile with the information we got
+       Tile* tile = new Tile(helper);
+       this->push_back(tile);
+
+       return true;
+      }
+
+  if (tag == Tileset::d_road_smallmap_tag)
+    {
+      helper->getData(d_road_color, "color");
+      return true;
+    }
+
+  if (tag == SmallTile::d_tag)
+    {
+      Tile *tile = this->back();
+      SmallTile* smalltile = new SmallTile(helper);
+      tile->setSmallTile(smalltile);
+      return true;
+    }
+
+  if (tag == TileStyle::d_tag)
+    {
+      Tile *tile = this->back();
+      TileStyleSet *tilestyleset = tile->back();
+      // create a new tile style with the information we got
+      // put it on the latest tilestyleset
+      TileStyle* tilestyle = new TileStyle(helper);
+      tilestyleset->push_back(tilestyle);
+      d_tilestyles[tilestyle->getId()] = tilestyle;
+
+      return true;
+    }
+
+  if (tag == TileStyleSet::d_tag)
+    {
+      Tile *tile = this->back();
+      // create a new tile style set with the information we got
+      // put it on the latest tile
+      TileStyleSet* tilestyleset = new TileStyleSet(helper);
+      tilestyleset->setSubDir(getSubDir());
+      tile->push_back(tilestyleset);
+      return true;
+    }
+
+  return false;
+}
+
+TileStyle *Tileset::getRandomTileStyle(guint32 index, TileStyle::Type style) const
+{
+  Tile *tile = (*this)[index];
+  if (tile)
+    return tile->getRandomTileStyle (style);
+  else
+    return NULL;
+}
+
+bool Tileset::save(XML_Helper *helper) const
+{
+  bool retval = true;
+
+  retval &= helper->openTag(d_tag);
+  retval &= helper->saveData("id", d_id);
+  retval &= helper->saveData("name", d_name);
+  retval &= helper->saveData("copyright", d_copyright);
+  retval &= helper->saveData("license", d_license);
+  retval &= helper->saveData("info", d_info);
+  retval &= helper->saveData("tilesize", d_tileSize);
+  retval &= helper->saveData("large_selector", d_large_selector);
+  retval &= helper->saveData("small_selector", d_small_selector);
+  retval &= helper->saveData("explosion", d_explosion);
+  retval &= helper->saveData("roads", d_roads);
+  retval &= helper->saveData("bridges", d_bridges);
+  retval &= helper->saveData("fog", d_fog);
+  retval &= helper->saveData("flags", d_flags);
+  retval &= helper->openTag(d_road_smallmap_tag);
+  retval &= helper->saveData("color", d_road_color);
+  retval &= helper->closeTag();
+  for (Tileset::const_iterator i = begin(); i != end(); ++i)
+    retval &= (*i)->save(helper);
+  retval &= helper->closeTag();
+
+  return retval;
+}
+
+int Tileset::getFreeTileStyleId() const
+{
+  int ids[65535];
+  memset (ids, 0, sizeof (ids));
+  for (Tileset::const_iterator i = begin(); i != end(); ++i)
+    {
+      for (std::list<TileStyleSet*>::const_iterator j = (*i)->begin(); j != (*i)->end(); j++)
+       {
+         for (std::vector<TileStyle*>::const_iterator k = (*j)->begin(); k != (*j)->end(); k++)
+           {
+             ids[(*k)->getId()] = 1;
+           }
+       }
+    }
+  //these ids range from 0 to 65535.
+  for (unsigned int i = 0; i <= 65535; i++)
+    {
+      if (ids[i] == 0)
+       return i;
+    }
+  return -1;
+}
+
+int Tileset::getLargestTileStyleId() const
+{
+  unsigned int largest = 0;
+  for (Tileset::const_iterator i = begin(); i != end(); ++i)
+    {
+      for (std::list<TileStyleSet*>::const_iterator j = (*i)->begin(); j != (*i)->end(); j++)
+       {
+         for (std::vector<TileStyle*>::const_iterator k = (*j)->begin(); k != (*j)->end(); k++)
+           {
+             if ((*k)->getId() > largest)
+               largest = (*k)->getId();
+           }
+       }
+    }
+  return largest;
+}
+
+void Tileset::setSubDir(std::string dir)
+{
+  d_subdir = dir;
+  for (Tileset::iterator i = begin(); i != end(); ++i)
+    for (Tile::iterator j = (*i)->begin(); j != (*i)->end(); j++)
+      (*j)->setSubDir(dir);
+}
+
+guint32 Tileset::getDefaultTileSize()
+{
+  return DEFAULT_TILE_SIZE;
+}
+
+bool Tileset::validate() const
+{
+  if (size() == 0)
+    return false;
+  for (Tileset::const_iterator i = begin(); i != end(); i++)
+    {
+      if ((*i)->validate() == false)
+       {
+         fprintf (stderr, "`%s' fails validation\n", 
+                  (*i)->getName().c_str());
+         return false;
+       }
+    }
+  return true;
+}
+
+class TilesetLoader
+{
+public:
+    TilesetLoader(std::string filename) 
+      {
+       tileset = NULL;
+       dir = File::get_dirname(filename);
+       if (File::nameEndsWith(filename, Tileset::file_extension) == false)
+         filename += Tileset::file_extension;
+       XML_Helper helper(filename, ios::in, false);
+       helper.registerTag(Tileset::d_tag, sigc::mem_fun((*this), &TilesetLoader::load));
+       if (!helper.parse())
+         {
+           std::cerr << "Error, while loading an tileset. Tileset Name: ";
+           std::cerr <<dir<<std::endl <<std::flush;
+           if (tileset != NULL)
+             delete tileset;
+           tileset = NULL;
+         }
+      };
+    bool load(std::string tag, XML_Helper* helper)
+      {
+       if (tag == Tileset::d_tag)
+         {
+           tileset = new Tileset(helper, dir);
+           return true;
+         }
+       return false;
+      };
+    std::string dir;
+    Tileset *tileset;
+};
+Tileset *Tileset::create(std::string file)
+{
+  TilesetLoader d(file);
+  return d.tileset;
+}
+void Tileset::getFilenames(std::list<std::string> &files)
+{
+  for (iterator it = begin(); it != end(); it++)
+    {
+      Tile *t = *it;
+      for (Tile::iterator sit = t->begin(); sit != t->end(); sit++)
+       {
+         std::string file = (*sit)->getName();
+         if (std::find(files.begin(), files.end(), file) == files.end())
+           files.push_back(file);
+       }
+    }
+  files.push_back(d_small_selector);
+  files.push_back(d_large_selector);
+  files.push_back(d_explosion);
+  files.push_back(d_fog);
+  files.push_back(d_roads);
+  files.push_back(d_bridges);
+  files.push_back(d_flags);
+}
+
+void Tileset::uninstantiateImages()
+{
+  for (iterator it = begin(); it != end(); it++)
+    (*it)->uninstantiateImages();
+
+  if (getExplosionImage() != NULL)
+    {
+      delete getExplosionImage();
+      setExplosionImage(NULL);
+    }
+  for (unsigned int i = 0; i < ROAD_TYPES; i++)
+    {
+      if (getRoadImage(i) != NULL)
+       {
+         delete getRoadImage(i);
+         setRoadImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < BRIDGE_TYPES; i++)
+    {
+      if (getBridgeImage(i) != NULL)
+       {
+         delete getBridgeImage(i);
+         setBridgeImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < FOG_TYPES; i++)
+    {
+      if (getFogImage(i) != NULL)
+       {
+         delete getFogImage(i);
+         setFogImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < getNumberOfSelectorFrames(); i++)
+    {
+      if (getSelectorImage(i) != NULL)
+       {
+         delete getSelectorImage(i);
+         setSelectorImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < getNumberOfSmallSelectorFrames(); i++)
+    {
+      if (getSmallSelectorImage(i) != NULL)
+       {
+         delete getSmallSelectorImage(i);
+         setSmallSelectorImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < getNumberOfSmallSelectorFrames(); i++)
+    {
+      if (getSmallSelectorMask(i) != NULL)
+       {
+         delete getSmallSelectorMask(i);
+         setSmallSelectorMask(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    {
+      if (getFlagImage(i) != NULL)
+       {
+         delete getFlagImage(i);
+         setFlagImage(i, NULL);
+       }
+    }
+  for (unsigned int i = 0; i < FLAG_TYPES; i++)
+    {
+      if (getFlagMask(i) != NULL)
+       {
+         delete getFlagMask(i);
+         setFlagMask(i, NULL);
+       }
+    }
+}
+
+void Tileset::instantiateImages(std::string explosion_filename,
+                               std::string roads_filename,
+                               std::string bridges_filename,
+                               std::string fog_filename,
+                               std::string flags_filename,
+                               std::string selector_filename,
+                               std::string small_selector_filename)
+{
+  if (explosion_filename.empty() == false)
+    setExplosionImage (PixMask::create(explosion_filename));
+
+  if (roads_filename.empty() == false)
+    {
+      std::vector<PixMask* > roadpics;
+      roadpics = disassemble_row(roads_filename, ROAD_TYPES);
+      for (unsigned int i = 0; i < ROAD_TYPES ; i++)
+       {
+         if (roadpics[i]->get_width() != (int)d_tileSize)
+           PixMask::scale(roadpics[i], d_tileSize, d_tileSize);
+         setRoadImage(i, roadpics[i]);
+       }
+    }
+
+  if (bridges_filename.empty() == false)
+    {
+      std::vector<PixMask* > bridgepics;
+      bridgepics = disassemble_row(bridges_filename, BRIDGE_TYPES);
+      for (unsigned int i = 0; i < BRIDGE_TYPES ; i++)
+       {
+         if (bridgepics[i]->get_width() != (int)d_tileSize)
+           PixMask::scale(bridgepics[i], d_tileSize, d_tileSize);
+         setBridgeImage(i, bridgepics[i]);
+       }
+    }
+
+  if (fog_filename.empty() == false)
+    {
+      std::vector<PixMask* > fogpics;
+      fogpics = disassemble_row(fog_filename, FOG_TYPES);
+      for (unsigned int i = 0; i < FOG_TYPES ; i++)
+       {
+         if (fogpics[i]->get_width() != (int)d_tileSize)
+           PixMask::scale(fogpics[i], d_tileSize, d_tileSize);
+         setFogImage(i, fogpics[i]);
+       }
+    }
+
+  if (flags_filename.empty() == false)
+    {
+      std::vector<PixMask* > flagpics;
+      std::vector<PixMask* > maskpics;
+      GraphicsCache::loadFlagImages (flags_filename, d_tileSize, 
+                                    flagpics, maskpics);
+      for (unsigned int i = 0; i < flagpics.size(); i++)
+       setFlagImage(i, flagpics[i]);
+      for (unsigned int i = 0; i < maskpics.size(); i++)
+       setFlagMask(i, maskpics[i]);
+    }
+
+      
+  std::vector<PixMask* > images;
+  std::vector<PixMask* > masks;
+  if (selector_filename.empty() == false)
+    {
+      GraphicsCache::loadSelectorImages (selector_filename, d_tileSize, 
+                                        images, masks);
+      setNumberOfSelectorFrames(images.size());
+      for (unsigned int i = 0; i < images.size(); i++)
+       {
+         setSelectorImage(i, images[i]);
+         setSelectorMask(i, masks[i]);
+       }
+    }
+
+  images.clear();
+  masks.clear();
+  if (small_selector_filename.empty() == false)
+    {
+      GraphicsCache::loadSelectorImages (small_selector_filename, d_tileSize,
+                                        images, masks);
+      setNumberOfSmallSelectorFrames(images.size());
+      for (unsigned int i = 0; i < images.size(); i++)
+       {
+         setSmallSelectorImage(i, images[i]);
+         setSmallSelectorMask(i, masks[i]);
+       }
+    }
+}
+
+void Tileset::instantiateImages()
+{
+  int size = getTileSize();
+  debug("Loading images for tileset " << getName());
+  uninstantiateImages();
+  for (iterator it = begin(); it != end(); it++)
+    (*it)->instantiateImages(size, this);
+  std::string explosion_filename = "";
+  std::string roads_filename = "";
+  std::string bridges_filename = "";
+  std::string fog_filename = "";
+  std::string flags_filename = "";
+  std::string selector_filename = "";
+  std::string small_selector_filename = "";
+
+  if (getExplosionFilename().empty() == false)
+    explosion_filename = getFile(getExplosionFilename());
+  if (getRoadsFilename().empty() == false)
+    roads_filename = getFile(getRoadsFilename());
+  if (getBridgesFilename().empty() == false)
+    bridges_filename = getFile(getBridgesFilename());
+  if (getFogFilename().empty() == false)
+    fog_filename = getFile(getFogFilename());
+  if (getFlagsFilename().empty() == false)
+    flags_filename = getFile(getFlagsFilename());
+  if (getLargeSelectorFilename().empty() == false)
+    selector_filename = getFile(getLargeSelectorFilename());
+  if (getSmallSelectorFilename().empty() == false)
+    small_selector_filename = getFile(getSmallSelectorFilename());
+  instantiateImages(explosion_filename, roads_filename, bridges_filename, 
+                   fog_filename, flags_filename, selector_filename, 
+                   small_selector_filename);
+}
+
+std::string Tileset::getConfigurationFile() const
+{
+  return getDirectory() + d_subdir + file_extension;
+}
+
+std::list<std::string> Tileset::scanUserCollection()
+{
+  return File::scanFiles(File::getUserTilesetDir(), file_extension);
+}
+
+std::list<std::string> Tileset::scanSystemCollection()
+{
+  std::list<std::string> retlist = File::scanFiles(File::getTilesetDir(), 
+                                                  file_extension);
+  if (retlist.empty())
+    {
+      std::cerr << "Couldn't find any tilesets!" << std::endl;
+      std::cerr << "Please check the path settings in /etc/lordsawarrc or ~/.lordsawarrc" << std::endl;
+      std::cerr << "Exiting!" << std::endl;
+      exit(-1);
+    }
+
+  return retlist;
+}
+
+TileStyle *Tileset::getTileStyle(guint32 id) const
+{
+  TileStyleIdMap::const_iterator it = d_tilestyles.find(id);
+  if (it == d_tilestyles.end())
+    return NULL;
+  else
+    return (*it).second;
+}
+//End of file