/*
* The Mana World
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
*
* The Mana World 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 2 of the License, or
* any later version.
*
* The Mana World 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 The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include "mapreader.h"
#include "../log.h"
#include <iostream>
#define DEFAULT_TILE_WIDTH 32
#define DEFAULT_TILE_HEIGHT 32
Map *MapReader::readMap(const std::string &filename)
{
std::cout << "Attempting to parse XML map data";
FILE* f = fopen(filename.c_str(), "rb");
char *map_string;
if (!f) {
error(std::string("Error: failed to open ") + filename);
}
// Get size of file
fseek(f, 0, SEEK_END);
long size = ftell(f);
rewind(f);
// Read file into character array
map_string = new char[size + 1];
fread(map_string, 1, size, f);
map_string[size] = '\0';
fclose(f);
xmlDocPtr doc = xmlReadMemory(map_string, size, NULL, NULL, 0);
delete[] map_string;
if (doc) {
std::cout << "Looking for root node";
xmlNodePtr node = xmlDocGetRootElement(doc);
if (!node || !xmlStrEqual(node->name, BAD_CAST "map")) {
log("Warning: No map file (%s)!", filename.c_str());
return NULL;
}
std::cout << "Loading map from XML tree";
return readMap(node, filename);
xmlFreeDoc(doc);
} else {
log("Error while parsing map file (%s)!", filename.c_str());
}
return NULL;
}
Map* MapReader::readMap(xmlNodePtr node, const std::string &path)
{
xmlChar *prop;
prop = xmlGetProp(node, BAD_CAST "version");
xmlFree(prop);
int w = getProperty(node, "width", 0);
int h = getProperty(node, "height", 0);
int tilew = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
int tileh = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
int layerNr = 0;
Map* map = new Map(w, h);
for (node = node->xmlChildrenNode; node != NULL; node = node->next)
{
if (xmlStrEqual(node->name, BAD_CAST "tileset")) {
/*
Tileset* set = readTileset(node, path);
if (set) {
map->tilesets.push_back(set);
}
*/
}
else if (xmlStrEqual(node->name, BAD_CAST "layer")) {
log("- Loading layer %d", layerNr);
readLayer(node, map, layerNr);
layerNr++;
}
}
return map;
}
void MapReader::readLayer(xmlNodePtr node, Map *map, int layer)
{
// Ignored layer attributes
//int w = getProperty(node, "width", 0); // Map width is used
//int h = getProperty(node, "height", 0); // Map height is used
//xmlChar *name = xmlGetProp(node, BAD_CAST "name");
node = node->xmlChildrenNode;
int h = map->getHeight();
int w = map->getWidth();
int x = 0;
int y = 0;
// Load the tile data
while (node != NULL)
{
if (xmlStrEqual(node->name, BAD_CAST "tile") && y < h)
{
int gid = getProperty(node, "gid", -1);
map->setTile(x, y, layer, (gid > -1) ? gid : 0);
x++;
if (x == w) {x = 0; y++;}
}
if (xmlStrEqual(node->name, BAD_CAST "data")) {
node = node->xmlChildrenNode;
} else {
node = node->next;
}
}
}
/*
Tileset* MapReader::readTileset(xmlNodePtr node, const std::string &path)
{
Tileset* set = NULL;
xmlChar* prop = xmlGetProp(node, BAD_CAST "source");
if (prop) {
console.log(CON_LOG, CON_ALWAYS,
"Warning: External tilesets not supported yet.");
xmlFree(prop);
return NULL;
}
int firstgid = getProperty(node, "firstgid", 0);
int tw = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
int th = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
int ts = getProperty(node, "spacing", 0);
xmlChar* name = xmlGetProp(node, BAD_CAST "name");
node = node->xmlChildrenNode;
while (node != NULL) {
if (xmlStrEqual(node->name, BAD_CAST "image")) {
xmlChar* source = xmlGetProp(node, BAD_CAST "source");
if (source) {
char* srcname = get_filename((char*)source);
BITMAP* tilebmp = module->findBitmap(srcname);
if (tilebmp) {
set = new Tileset();
set->importTileBitmap(tilebmp, (char*)source, tw, th, ts);
set->setFirstGid(firstgid);
if (name) { set->setName((char*)name); }
xmlFree(source);
} else {
printf("Warning: Failed to load tileset %s (%s)\n",
srcname, (char*)name);
}
}
break;
}
node = node->next;
}
xmlFree(name);
return set;
}
*/
int MapReader::getProperty(xmlNodePtr node, const char* name, int def)
{
xmlChar *prop = xmlGetProp(node, BAD_CAST name);
if (prop) {
int val = atoi((char*)prop);
xmlFree(prop);
return val;
}
else {
return def;
}
}