summaryrefslogblamecommitdiff
path: root/src/resources/mapreader.cpp
blob: c86f7fe4cfca702e6f23b56f8763d4774921d959 (plain) (tree)









































































































                                                                             












                                                                    

                             



                         



                                                              
                                                   
                                                            










                                                       


































































                                                                              
/*
 *  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;
    }
}