ManaPlus
Static Public Member Functions | Static Private Member Functions | Static Private Attributes
MapReader Class Reference

#include <mapreader.h>

Static Public Member Functions

static MapreadMap (const std::string &filename, const std::string &realFilename)
 
static MapreadMap (xmlNode *const node, const std::string &path)
 
static MapcreateEmptyMap (const std::string &filename, const std::string &realFilename)
 
static void readLayer (const xmlNodePtr node, Map *const map)
 
static void loadEmptyAtlas ()
 
static void unloadEmptyAtlas ()
 

Static Private Member Functions

static void readProperties (const xmlNode *const node, Properties *const props)
 
static bool readBase64Layer (const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, const std::string &compression, int &x, int &y, const int w, const int h)
 
static bool readCsvLayer (const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, int &x, int &y, const int w, const int h)
 
static TilesetreadTileset (xmlNodePtr node, const std::string &path, Map *const map)
 
static void updateMusic (Map *const map)
 
static void addLayerToList (const std::string &fileName, const SkipError skipError)
 
static void loadLayers (const std::string &path)
 
static void unloadTempLayers ()
 

Static Private Attributes

static ResourcemEmptyAtlas = 0
 

Detailed Description

Reader for XML map files (*.tmx)

Definition at line 41 of file mapreader.h.

Member Function Documentation

◆ addLayerToList()

void MapReader::addLayerToList ( const std::string &  fileName,
const SkipError  skipError 
)
staticprivate

Definition at line 230 of file mapreader.cpp.

232 {
235  skipError);
236  XmlNodePtrConst node = doc->rootNode();
237  if (node == nullptr)
238  {
239  delete doc;
240  return;
241  }
242 
243  int cnt = 0;
244  for_each_xml_child_node(childNode, node)
245  {
246  if (!xmlNameEqual(childNode, "layer"))
247  continue;
248  std::string name = XML::getProperty(childNode, "name", "");
249  if (name.empty())
250  continue;
251  name = toLower(name);
252  logger->log("found patch layer: " + name);
253  mKnownLayers[name] = childNode;
254  mKnownDocs.insert(doc);
255  cnt ++;
256  }
257  if (cnt == 0)
258  delete doc;
259 }
void log(const char *const log_text,...)
Definition: logger.cpp:269
xmlNodePtr rootNode()
Definition: libxml.cpp:169
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
Logger * logger
Definition: logger.cpp:89
std::string toLower(std::string const &s)
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:174
std::set< XML::Document * > mKnownDocs
Definition: mapreader.cpp:82
std::map< std::string, xmlNodePtr > mKnownLayers
Definition: mapreader.cpp:81
std::string fileName
Definition: testmain.cpp:39
const bool UseVirtFs_true
Definition: usevirtfs.h:30

References fileName, for_each_xml_child_node, XML::getProperty(), Logger::log(), logger, anonymous_namespace{mapreader.cpp}::mKnownDocs, anonymous_namespace{mapreader.cpp}::mKnownLayers, XML::Document::rootNode(), Catch::toLower(), and UseVirtFs_true.

Referenced by loadLayers().

◆ createEmptyMap()

Map * MapReader::createEmptyMap ( const std::string &  filename,
const std::string &  realFilename 
)
static

Definition at line 1275 of file mapreader.cpp.

1277 {
1278  logger->log1("Creating empty map");
1279  Map *const map = new Map("empty map",
1280  300, 300,
1282  map->setProperty("_filename", realFilename);
1283  map->setProperty("_realfilename", filename);
1284  updateMusic(map);
1285  map->setCustom(true);
1286  MapLayer *layer = new MapLayer("nolayer",
1287  0, 0,
1288  300, 300,
1289  false,
1290  1,
1291  -1);
1292  map->addLayer(layer);
1293  layer = new MapLayer("nolayer",
1294  0, 0,
1295  300, 300,
1296  true,
1297  1,
1298  -1);
1299  map->addLayer(layer);
1300  map->updateDrawLayersList();
1301  map->updateConditionLayers();
1302  map->preCacheLayers();
1303 
1304  return map;
1305 }
void log1(const char *const log_text)
Definition: logger.cpp:238
static void updateMusic(Map *const map)
Definition: mapreader.cpp:1307
Definition: map.h:75
void preCacheLayers()
Definition: map.cpp:1746
void updateConditionLayers()
Definition: map.cpp:1732
void addLayer(MapLayer *const layer)
Definition: map.cpp:313
void setCustom(const bool b)
Definition: map.h:324
void updateDrawLayersList()
Definition: map.cpp:1638
void setProperty(const std::string &name, const std::string &value)
Definition: properties.h:128
static const int mapTileSize
Definition: map.h:27

References Map::addLayer(), Logger::log1(), logger, mapTileSize, Map::preCacheLayers(), Map::setCustom(), Properties::setProperty(), Map::updateConditionLayers(), Map::updateDrawLayersList(), and updateMusic().

◆ loadEmptyAtlas()

void MapReader::loadEmptyAtlas ( )
static

Definition at line 1319 of file mapreader.cpp.

1320 {
1322  return;
1323 
1324  const MapInfo *const info = MapDB::getAtlas(
1325  paths.getStringValue("emptyAtlasName"));
1326  if (info != nullptr)
1327  {
1329  info->atlas,
1330  *info->files);
1331  delete info;
1332  }
1333 }
std::string getStringValue(const std::string &key) const
bool getUseAtlases() const
static Resource * mEmptyAtlas
Definition: mapreader.h:120
Configuration paths
GraphicsManager graphicsManager
bool info(InputEvent &event)
Definition: commands.cpp:57
Resource * getEmptyAtlas(const std::string &name, const StringVect &files)
const MapInfo * getAtlas(const std::string &name)
Definition: mapdb.cpp:226

References MapDB::getAtlas(), Loader::getEmptyAtlas(), Configuration::getStringValue(), GraphicsManager::getUseAtlases(), graphicsManager, Actions::info(), mEmptyAtlas, and paths.

Referenced by Game::Game().

◆ loadLayers()

void MapReader::loadLayers ( const std::string &  path)
staticprivate

Definition at line 307 of file mapreader.cpp.

308 {
309  BLOCK_START("MapReader::loadLayers")
312 }
#define loadXmlDir2(name, function, ext, skipError)
Definition: beingcommon.h:50
static void loadLayers(const std::string &path)
Definition: mapreader.cpp:307
static void addLayerToList(const std::string &fileName, const SkipError skipError)
Definition: mapreader.cpp:230
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
const bool SkipError_false
Definition: skiperror.h:30

References addLayerToList(), BLOCK_END, BLOCK_START, loadXmlDir2, and SkipError_false.

◆ readBase64Layer()

bool MapReader::readBase64Layer ( const xmlNode *const  childNode,
Map *const  map,
MapLayer *const  layer,
const MapLayerTypeT layerType,
MapHeights *const  heights,
const std::string &  compression,
int &  x,
int &  y,
const int  w,
const int  h 
)
staticprivate

Definition at line 664 of file mapreader.cpp.

672 {
673  if (childNode == nullptr)
674  return false;
675 
676  if (!compression.empty() && compression != "gzip"
677  && compression != "zlib")
678  {
679  reportAlways("Warning: only gzip and zlib layer"
680  " compression supported!")
681  return false;
682  }
683 
684  // Read base64 encoded map file
685  if (!XmlHaveChildContent(childNode))
686  return true;
687 
688  const size_t len = strlen(XmlChildContent(childNode)) + 1;
689  unsigned char *charData = new unsigned char[len + 1];
690  const char *const xmlChars = XmlChildContent(childNode);
691  const char *charStart = reinterpret_cast<const char*>(xmlChars);
692  if (charStart == nullptr)
693  {
694  delete [] charData;
695  return false;
696  }
697 
698  unsigned char *charIndex = charData;
699 
700  while (*charStart != 0)
701  {
702  if (*charStart != ' ' &&
703  *charStart != '\t' &&
704  *charStart != '\n')
705  {
706  *charIndex = *charStart;
707  charIndex++;
708  }
709  charStart++;
710  }
711  *charIndex = '\0';
712 
713  int binLen;
714  unsigned char *binData = php3_base64_decode(charData,
715  CAST_S32(strlen(reinterpret_cast<char*>(
716  charData))), &binLen);
717 
718  delete [] charData;
719 // XmlFree(const_cast<char*>(xmlChars));
720 
721  if (binData != nullptr)
722  {
723  if (compression == "gzip" || compression == "zlib")
724  {
725  // Inflate the gzipped layer data
726  unsigned char *inflated = nullptr;
727  const unsigned int inflatedSize =
728  inflateMemory(binData, binLen, inflated);
729 
730  free(binData);
731  binData = inflated;
732  binLen = inflatedSize;
733 
734  if (inflated == nullptr)
735  {
736  reportAlways("Error: Could not decompress layer!")
737  return false;
738  }
739  }
740 
741  const std::map<int, TileAnimation*> &tileAnimations
742  = map->getTileAnimations();
743 
744  const bool hasAnimations = !tileAnimations.empty();
745  if (hasAnimations)
746  {
747  for (int i = 0; i < binLen - 3; i += 4)
748  {
749  const int gid = binData[i] |
750  binData[i + 1] << 8 |
751  binData[i + 2] << 16 |
752  binData[i + 3] << 24;
753 
754  setTile(map, layer, layerType, heights, x, y, gid);
755  TileAnimationMapCIter it = tileAnimations.find(gid);
756  if (it != tileAnimations.end())
757  {
758  TileAnimation *const ani = it->second;
759  if (ani != nullptr)
760  ani->addAffectedTile(layer, x + y * w);
761  }
762 
763  x++;
764  if (x == w)
765  {
766  x = 0; y++;
767 
768  // When we're done, don't crash on too much data
769  if (y == h)
770  break;
771  }
772  }
773  }
774  else
775  {
776  for (int i = 0; i < binLen - 3; i += 4)
777  {
778  const int gid = binData[i] |
779  binData[i + 1] << 8 |
780  binData[i + 2] << 16 |
781  binData[i + 3] << 24;
782 
783  setTile(map, layer, layerType, heights, x, y, gid);
784 
785  x++;
786  if (x == w)
787  {
788  x = 0; y++;
789 
790  // When we're done, don't crash on too much data
791  if (y == h)
792  break;
793  }
794  }
795  }
796  free(binData);
797  }
798  return true;
799 }
unsigned char * php3_base64_decode(const unsigned char *const string, const int length, int *const ret_length)
Definition: base64.cpp:100
#define CAST_S32
Definition: cast.h:30
#define reportAlways(...)
Definition: checkutils.h:253
void addAffectedTile(MapLayer *const layer, const int index)
Definition: tileanimation.h:55
#define new
Definition: debug_new.h:147
if(!vert) return
static int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char *&out, unsigned int &outLength)
Definition: mapreader.cpp:124
static void setTile(Map *map, MapLayer *layer, MapLayerTypeT &layerType, MapHeights *heights, int x, int y, int gid)
Definition: mapreader.cpp:559
std::string empty
Definition: podict.cpp:26
TileAnimationMap::const_iterator TileAnimationMapCIter
Definition: tileanimation.h:65

References TileAnimation::addAffectedTile(), CAST_S32, Map::getTileAnimations(), inflateMemory(), php3_base64_decode(), reportAlways, setTile(), x, and y.

Referenced by readLayer().

◆ readCsvLayer()

bool MapReader::readCsvLayer ( const xmlNode *const  childNode,
Map *const  map,
MapLayer *const  layer,
const MapLayerTypeT layerType,
MapHeights *const  heights,
int &  x,
int &  y,
const int  w,
const int  h 
)
staticprivate

Definition at line 801 of file mapreader.cpp.

808 {
809  if (childNode == nullptr)
810  return false;
811 
812  if (!XmlHaveChildContent(childNode))
813  return true;
814 
815  const char *const xmlChars = XmlChildContent(childNode);
816  const char *const data = reinterpret_cast<const char*>(xmlChars);
817  if (data == nullptr)
818  return false;
819 
820  std::string csv(data);
821  size_t oldPos = 0;
822 
823  const std::map<int, TileAnimation*> &tileAnimations
824  = map->getTileAnimations();
825  const bool hasAnimations = !tileAnimations.empty();
826 
827  if (hasAnimations)
828  {
829  while (oldPos != std::string::npos)
830  {
831  const size_t pos = csv.find_first_of(',', oldPos);
832  if (pos == std::string::npos)
833  return false;
834 
835  const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
836  setTile(map, layer, layerType, heights, x, y, gid);
837  TileAnimationMapCIter it = tileAnimations.find(gid);
838  if (it != tileAnimations.end())
839  {
840  TileAnimation *const ani = it->second;
841  if (ani != nullptr)
842  ani->addAffectedTile(layer, x + y * w);
843  }
844 
845  x++;
846  if (x == w)
847  {
848  x = 0; y++;
849 
850  // When we're done, don't crash on too much data
851  if (y == h)
852  return false;
853  }
854  oldPos = pos + 1;
855  }
856  }
857  else
858  {
859  while (oldPos != std::string::npos)
860  {
861  const size_t pos = csv.find_first_of(',', oldPos);
862  if (pos == std::string::npos)
863  return false;
864 
865  const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
866  setTile(map, layer, layerType, heights, x, y, gid);
867 
868  x++;
869  if (x == w)
870  {
871  x = 0; y++;
872 
873  // When we're done, don't crash on too much data
874  if (y == h)
875  return false;
876  }
877  oldPos = pos + 1;
878  }
879  }
880  return true;
881 }
const std::map< int, TileAnimation * > & getTileAnimations() const
Definition: map.h:330
uint32_t data

References TileAnimation::addAffectedTile(), data, Map::getTileAnimations(), setTile(), x, and y.

Referenced by readLayer().

◆ readLayer()

void MapReader::readLayer ( const xmlNodePtr  node,
Map *const  map 
)
static

Reads a map layer and adds it to the given map.

Definition at line 883 of file mapreader.cpp.

884 {
885  if (node == nullptr)
886  return;
887 
888  // Layers are not necessarily the same size as the map
889  const int w = XML::getProperty(node, "width", map->getWidth());
890  const int h = XML::getProperty(node, "height", map->getHeight());
891  const int offsetX = XML::getProperty(node, "x", 0);
892  const int offsetY = XML::getProperty(node, "y", 0);
893  std::string name = XML::getProperty(node, "name", "");
894  name = toLower(name);
895 
896  const bool isFringeLayer = (name.substr(0, 6) == "fringe");
897  const bool isCollisionLayer = (name.substr(0, 9) == "collision");
898  const bool isHeightLayer = (name.substr(0, 7) == "heights");
899  const bool isActionsLayer = (name.substr(0, 7) == "actions");
900  int mask = 1;
901  int tileCondition = -1;
902  int conditionLayer = 0;
903 
905  if (isCollisionLayer)
906  layerType = MapLayerType::COLLISION;
907  else if (isHeightLayer)
908  layerType = MapLayerType::HEIGHTS;
909  else if (isActionsLayer)
910  layerType = MapLayerType::ACTIONS;
911 
912  map->indexTilesets();
913 
914  MapLayer *layer = nullptr;
915  MapHeights *heights = nullptr;
916 
917  logger->log("- Loading layer \"%s\"", name.c_str());
918  int x = 0;
919  int y = 0;
920 
921  // Load the tile data
922  for_each_xml_child_node(childNode, node)
923  {
924  if (xmlNameEqual(childNode, "properties"))
925  {
926  for_each_xml_child_node(prop, childNode)
927  {
928  if (!xmlNameEqual(prop, "property"))
929  continue;
930  const std::string pname = XML::getProperty(prop, "name", "");
931  const std::string value = XML::getProperty(prop, "value", "");
932  // ignoring any layer if property Hidden is 1
933  if (pname == "Hidden")
934  {
935  if (value == "1")
936  return;
937  }
938  else if (pname == "Version")
939  {
940  if (value > CHECK_VERSION)
941  return;
942  }
943  else if (pname == "NotVersion")
944  {
945  if (value <= CHECK_VERSION)
946  return;
947  }
948  else if (pname == "Mask")
949  {
950  mask = atoi(value.c_str());
951  }
952  else if (pname == "TileCondition")
953  {
954  tileCondition = atoi(value.c_str());
955  }
956  else if (pname == "ConditionLayer")
957  {
958  conditionLayer = atoi(value.c_str());
959  }
960  else if (pname == "SideView")
961  {
962  if (value != "down")
963  return;
964  }
965  }
966  }
967 
968  if (!xmlNameEqual(childNode, "data"))
969  continue;
970 
971  // Disable for future usage "TileCondition" attribute
972  // if already set ConditionLayer to non zero
973  if (conditionLayer != 0)
974  tileCondition = -1;
975 
976  switch (layerType)
977  {
978  case MapLayerType::TILES:
979  {
980  layer = new MapLayer(name,
981  offsetX, offsetY,
982  w, h,
983  isFringeLayer,
984  mask,
985  tileCondition);
986  map->addLayer(layer);
987  break;
988  }
990  {
991  heights = new MapHeights(w, h);
992  map->addHeights(heights);
993  break;
994  }
995  default:
998  break;
999  }
1000 
1001  const std::string encoding =
1002  XML::getProperty(childNode, "encoding", "");
1003  const std::string compression =
1004  XML::getProperty(childNode, "compression", "");
1005 
1006  if (encoding == "base64")
1007  {
1008  if (readBase64Layer(childNode, map, layer, layerType,
1009  heights, compression, x, y, w, h))
1010  {
1011  continue;
1012  }
1013  else
1014  {
1015  return;
1016  }
1017  }
1018  else if (encoding == "csv")
1019  {
1020  if (readCsvLayer(childNode, map, layer, layerType,
1021  heights, x, y, w, h))
1022  {
1023  continue;
1024  }
1025  else
1026  {
1027  return;
1028  }
1029  }
1030  else
1031  {
1032  const std::map<int, TileAnimation*> &tileAnimations
1033  = map->getTileAnimations();
1034  const bool hasAnimations = !tileAnimations.empty();
1035 
1036  // Read plain XML map file
1037  for_each_xml_child_node(childNode2, childNode)
1038  {
1039  if (!xmlNameEqual(childNode2, "tile"))
1040  continue;
1041 
1042  const int gid = XML::getProperty(childNode2, "gid", -1);
1043  setTile(map, layer, layerType, heights, x, y, gid);
1044  if (hasAnimations)
1045  {
1046  TileAnimationMapCIter it = tileAnimations.find(gid);
1047  if (it != tileAnimations.end())
1048  {
1049  TileAnimation *const ani = it->second;
1050  if (ani != nullptr)
1051  ani->addAffectedTile(layer, x + y * w);
1052  }
1053  }
1054 
1055  x++;
1056  if (x == w)
1057  {
1058  x = 0; y++;
1059  if (y >= h)
1060  break;
1061  }
1062  }
1063  }
1064 
1065  if (y < h)
1066  std::cerr << "TOO SMALL!\n";
1067  if (x != 0)
1068  std::cerr << "TOO SMALL!\n";
1069 
1070  // There can be only one data element
1071  break;
1072  }
1073 }
static bool readBase64Layer(const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, const std::string &compression, int &x, int &y, const int w, const int h)
Definition: mapreader.cpp:664
static bool readCsvLayer(const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, int &x, int &y, const int w, const int h)
Definition: mapreader.cpp:801
int getHeight() const
Definition: map.h:172
void indexTilesets()
Definition: map.cpp:1415
int getWidth() const
Definition: map.h:166
void addHeights(const MapHeights *const heights)
Definition: map.cpp:1625
#define CHECK_VERSION
Definition: main.h:45
MapLayerType ::T MapLayerTypeT
Definition: maplayertype.h:38

References MapLayerType::ACTIONS, TileAnimation::addAffectedTile(), Map::addHeights(), Map::addLayer(), CHECK_VERSION, MapLayerType::COLLISION, for_each_xml_child_node, Map::getHeight(), XML::getProperty(), Map::getTileAnimations(), Map::getWidth(), MapLayerType::HEIGHTS, Map::indexTilesets(), Logger::log(), logger, readBase64Layer(), readCsvLayer(), setTile(), MapLayerType::TILES, Catch::toLower(), x, and y.

Referenced by loadReplaceLayer().

◆ readMap() [1/2]

static Map* MapReader::readMap ( const std::string &  filename,
const std::string &  realFilename 
)
static

Read an XML map from a file.

Referenced by Game::changeMap().

◆ readMap() [2/2]

static Map* MapReader::readMap ( xmlNode *const  node,
const std::string &  path 
)
static

Read an XML map from a parsed XML tree. The path is used to find the location of referenced tileset images.

◆ readProperties()

void MapReader::readProperties ( const xmlNode *const  node,
Properties *const  props 
)
staticprivate

Reads the properties element.

Parameters
nodeThe properties element.
propsThe Properties instance to which the properties will be assigned.

Definition at line 522 of file mapreader.cpp.

524 {
525  BLOCK_START("MapReader::readProperties")
526  if (node == nullptr)
527  {
528  BLOCK_END("MapReader::readProperties")
529  return;
530  }
531 
532  for_each_xml_child_node(childNode, node)
533  {
534  if (!xmlNameEqual(childNode, "property"))
535  continue;
536 
537  // Example: <property name="name" value="value"/>
538  const std::string name = XML::getProperty(childNode, "name", "");
539  const std::string value = XML::getProperty(childNode, "value", "");
540 
541  if (!name.empty() && !value.empty())
542  {
543  if (name == "name")
544  props->setProperty(name, translator->getStr(value));
545  else
546  props->setProperty(name, value);
547  }
548  }
549  BLOCK_END("MapReader::readProperties")
550 }
const std::string getStr(const std::string &str)
Definition: podict.cpp:45
PoDict * translator
Definition: podict.cpp:28

References BLOCK_END, BLOCK_START, for_each_xml_child_node, XML::getProperty(), PoDict::getStr(), and translator.

◆ readTileset()

Tileset * MapReader::readTileset ( xmlNodePtr  node,
const std::string &  path,
Map *const  map 
)
staticprivate

Reads a tile set.

Definition at line 1075 of file mapreader.cpp.

1078 {
1079  BLOCK_START("MapReader::readTileset")
1080  if (node == nullptr)
1081  {
1082  BLOCK_END("MapReader::readTileset")
1083  return nullptr;
1084  }
1085 
1086  const int firstGid = XML::getProperty(node, "firstgid", 0);
1087  const int margin = XML::getProperty(node, "margin", 0);
1088  const int spacing = XML::getProperty(node, "spacing", 0);
1089  XML::Document* doc = nullptr;
1090  Tileset *set = nullptr;
1091  std::string pathDir(path);
1092  std::map<std::string, std::string> props;
1093 
1094  if (XmlHasProp(node, "source"))
1095  {
1096  std::string filename = XML::getProperty(node, "source", "");
1097  filename = resolveRelativePath(path, filename);
1098 
1099  doc = new XML::Document(filename, UseVirtFs_true, SkipError_false);
1100  node = doc->rootNode();
1101  if (node == nullptr)
1102  {
1103  delete doc;
1104  BLOCK_END("MapReader::readTileset")
1105  return nullptr;
1106  }
1107 
1108  // Reset path to be realtive to the tsx file
1109  pathDir = filename.substr(0, filename.rfind('/') + 1);
1110  }
1111 
1112  const int tw = XML::getProperty(node, "tilewidth", map->getTileWidth());
1113  const int th = XML::getProperty(node, "tileheight", map->getTileHeight());
1114 
1115  for_each_xml_child_node(childNode, node)
1116  {
1117  if (xmlNameEqual(childNode, "image"))
1118  {
1119  // ignore second other <image> tags in tileset
1120  if (set != nullptr)
1121  continue;
1122 
1123  const std::string source = XML::getProperty(
1124  childNode, "source", "");
1125 
1126  if (!source.empty())
1127  {
1128  const std::string sourceResolved = resolveRelativePath(pathDir,
1129  source);
1130 
1131  Image *const tilebmp = Loader::getImage(sourceResolved);
1132 
1133  if (tilebmp != nullptr)
1134  {
1135  set = new Tileset(tilebmp,
1136  tw, th,
1137  firstGid,
1138  margin,
1139  spacing);
1140  tilebmp->decRef();
1141 #ifdef USE_OPENGL
1142  if (MapDB::isEmptyTileset(sourceResolved))
1143  set->setEmpty(true);
1144  if (tilebmp->getType() == ImageType::Image &&
1145  map->haveAtlas() == true &&
1147  {
1148  reportAlways("Error: image '%s' not present in atlas",
1149  source.c_str())
1150  }
1151 #endif // USE_OPENGL
1152  }
1153  else
1154  {
1155  reportAlways("Error: Failed to load tileset (%s)",
1156  source.c_str())
1157  }
1158  }
1159  }
1160  else if (xmlNameEqual(childNode, "properties"))
1161  {
1162  for_each_xml_child_node(propertyNode, childNode)
1163  {
1164  if (!xmlNameEqual(propertyNode, "property"))
1165  continue;
1166  const std::string name = XML::getProperty(
1167  propertyNode, "name", "");
1168  if (!name.empty())
1169  props[name] = XML::getProperty(propertyNode, "value", "");
1170  }
1171  }
1172  else if (xmlNameEqual(childNode, "tile"))
1173  {
1174  bool haveAnimation(false);
1175 
1176  for_each_xml_child_node(tileNode, childNode)
1177  {
1178  const bool isProps = xmlNameEqual(tileNode, "properties");
1179  const bool isAnim = xmlNameEqual(tileNode, "animation");
1180  if (!isProps && !isAnim)
1181  continue;
1182 
1183  const int tileGID = firstGid + XML::getProperty(
1184  childNode, "id", 0);
1185 
1186  Animation *ani = new Animation("from map");
1187 
1188  if (isProps)
1189  {
1190  // read tile properties to a map for simpler handling
1191  StringIntMap tileProperties;
1192  for_each_xml_child_node(propertyNode, tileNode)
1193  {
1194  if (!xmlNameEqual(propertyNode, "property"))
1195  continue;
1196 
1197  haveAnimation = true;
1198  const std::string name = XML::getProperty(
1199  propertyNode, "name", "");
1200  if (!name.empty())
1201  {
1202  const int value = XML::getProperty(
1203  propertyNode, "value", 0);
1204  tileProperties[name] = value;
1205  logger->log("Tile Prop of %d \"%s\" = \"%d\"",
1206  tileGID, name.c_str(), value);
1207  }
1208  }
1209 
1210  // create animation
1211  if (set == nullptr ||
1212  !config.getBoolValue("playMapAnimations"))
1213  {
1214  delete ani;
1215  continue;
1216  }
1217 
1218  for (int i = 0; ; i++)
1219  {
1220  const std::string iStr(toString(i));
1221  StringIntMapCIter iFrame
1222  = tileProperties.find("animation-frame" + iStr);
1223  StringIntMapCIter iDelay
1224  = tileProperties.find("animation-delay" + iStr);
1225  // possible need add random attribute?
1226  if (iFrame != tileProperties.end()
1227  && iDelay != tileProperties.end())
1228  {
1229  ani->addFrame(set->get(iFrame->second),
1230  iDelay->second, 0, 0, 100);
1231  }
1232  else
1233  {
1234  break;
1235  }
1236  }
1237  }
1238  else if (isAnim && !haveAnimation)
1239  {
1240  for_each_xml_child_node(frameNode, tileNode)
1241  {
1242  if (!xmlNameEqual(frameNode, "frame"))
1243  continue;
1244 
1245  if (set != nullptr)
1246  {
1247  const int tileId = XML::getProperty(
1248  frameNode, "tileid", 0);
1249  const int duration = XML::getProperty(
1250  frameNode, "duration", 0) / 10;
1251 
1252  ani->addFrame(set->get(tileId),
1253  duration,
1254  0, 0, 100);
1255  }
1256  }
1257  }
1258 
1259  if (ani->getLength() > 0)
1260  map->addAnimation(tileGID, new TileAnimation(ani));
1261  else
1262  delete2(ani)
1263  }
1264  }
1265  }
1266 
1267  delete doc;
1268 
1269  if (set != nullptr)
1270  set->setProperties(props);
1271  BLOCK_END("MapReader::readTileset")
1272  return set;
1273 }
void addFrame(Image *const image, const int delay, const int offsetX, const int offsetY, const int rand)
Definition: animation.cpp:46
size_t getLength() const
Definition: animation.h:70
bool getBoolValue(const std::string &key) const
bool haveAtlas() const
Definition: map.h:340
void addAnimation(const int gid, TileAnimation *const animation)
Definition: map.cpp:1691
Configuration config
#define delete2(var)
Definition: delete2.h:25
static std::string resolveRelativePath(std::string base, std::string relative)
Definition: mapreader.cpp:94
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
Image * getImage(const std::string &idPath)
Definition: imageloader.cpp:86
bool isEmptyTileset(const std::string &name)
Definition: mapdb.cpp:238
Definition: libxml.cpp:86
std::map< std::string, int > StringIntMap
Definition: stringmap.h:28
StringIntMap::const_iterator StringIntMapCIter
Definition: stringmap.h:30

References Map::addAnimation(), Animation::addFrame(), ParticleType::Animation, BLOCK_END, BLOCK_START, config, delete2, for_each_xml_child_node, ImageSet::get(), Configuration::getBoolValue(), Loader::getImage(), Animation::getLength(), XML::getProperty(), Map::getTileHeight(), Map::getTileWidth(), GraphicsManager::getUseAtlases(), graphicsManager, Map::haveAtlas(), ImageType::Image, MapDB::isEmptyTileset(), Logger::log(), logger, reportAlways, resolveRelativePath(), XML::Document::rootNode(), Tileset::setEmpty(), Tileset::setProperties(), SkipError_false, Catch::toString(), and UseVirtFs_true.

◆ unloadEmptyAtlas()

void MapReader::unloadEmptyAtlas ( )
static

Definition at line 1335 of file mapreader.cpp.

1336 {
1337  if (mEmptyAtlas != nullptr)
1338  mEmptyAtlas->decRef();
1339 }
virtual void decRef()
Definition: resource.cpp:50

References Resource::decRef(), and mEmptyAtlas.

Referenced by Game::~Game().

◆ unloadTempLayers()

void MapReader::unloadTempLayers ( )
staticprivate

Definition at line 314 of file mapreader.cpp.

315 {
317  delete (*it);
318  mKnownLayers.clear();
319  mKnownDocs.clear();
320 }
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
std::set< XML::Document * >::iterator DocIterator
Definition: mapreader.cpp:73

References FOR_EACH, anonymous_namespace{mapreader.cpp}::mKnownDocs, and anonymous_namespace{mapreader.cpp}::mKnownLayers.

◆ updateMusic()

void MapReader::updateMusic ( Map *const  map)
staticprivate

Definition at line 1307 of file mapreader.cpp.

1308 {
1309  std::string name = map->getProperty("shortName", std::string());
1310  const size_t p = name.rfind('.');
1311  if (p != std::string::npos)
1312  name = name.substr(0, p);
1313  name.append(".ogg");
1314  if (VirtFs::exists(pathJoin(paths.getStringValue("music"), name)))
1315  map->setProperty("music", name);
1316 }
const std::string getProperty(const std::string &name, const std::string &def) const
Definition: properties.h:59
bool exists(std::string name)
Definition: fs.cpp:124
std::string pathJoin(std::string str1, const std::string &str2)

References VirtFs::exists(), Properties::getProperty(), Configuration::getStringValue(), pathJoin(), paths, and Properties::setProperty().

Referenced by createEmptyMap().

Field Documentation

◆ mEmptyAtlas

Resource * MapReader::mEmptyAtlas = 0
staticprivate

Definition at line 120 of file mapreader.h.

Referenced by loadEmptyAtlas(), and unloadEmptyAtlas().


The documentation for this class was generated from the following files: