diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-02-11 19:07:36 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-02-11 19:07:36 +0000 |
commit | 7f2a504d7bcbc255616af97e050e59b0a2d99c12 (patch) | |
tree | 358df0d3f4606aa5386a1937f4d8127633e99a99 /tools/tmxcopy/map.cpp | |
parent | 230c65a923aeaf456d61e5fbf4faec4c93313308 (diff) | |
download | mana-7f2a504d7bcbc255616af97e050e59b0a2d99c12.tar.gz mana-7f2a504d7bcbc255616af97e050e59b0a2d99c12.tar.bz2 mana-7f2a504d7bcbc255616af97e050e59b0a2d99c12.tar.xz mana-7f2a504d7bcbc255616af97e050e59b0a2d99c12.zip |
Merged revisions 3750-3751,3755-3759,3761,3766-3767,3773-3776,3779,3781,3783-3789,3791-3800,3807,3814-3815,3817,3819-3820,3822,3824-3825,3827,3829-3838,3840-3841,3843-3858,3860-3875 via svnmerge from
https://themanaworld.svn.sourceforge.net/svnroot/themanaworld/tmw/branches/0.0
........
r3750 | crush_tmw | 2007-11-20 00:36:02 +0100 (Tue, 20 Nov 2007) | 1 line
Updated desert maps with new tiles by Len.
........
r3755 | crush_tmw | 2007-11-20 17:47:44 +0100 (Tue, 20 Nov 2007) | 1 line
fixed a collision layer error
........
r3773 | crush_tmw | 2007-12-12 16:45:25 +0100 (Wed, 12 Dec 2007) | 2 lines
Added my tmxcopy tool for copying parts of maps to other maps.
........
r3774 | b_lindeijer | 2007-12-12 20:06:49 +0100 (Wed, 12 Dec 2007) | 2 lines
Added two new cave tiles by yosuhara.
........
r3775 | crush_tmw | 2007-12-12 20:25:40 +0100 (Wed, 12 Dec 2007) | 1 line
Fixed the blurred outlines of the new tiles.
........
r3791 | b_lindeijer | 2007-12-18 17:19:53 +0100 (Tue, 18 Dec 2007) | 2 lines
Added initial version of the update analysis tool upalyzer.
........
r3792 | b_lindeijer | 2007-12-18 17:22:27 +0100 (Tue, 18 Dec 2007) | 2 lines
Small fix to the displayed obsolete data percentage.
........
r3793 | b_lindeijer | 2007-12-18 17:31:52 +0100 (Tue, 18 Dec 2007) | 2 lines
Calculate usage percentage correctly and display zip file overhead.
........
r3794 | b_lindeijer | 2007-12-18 19:44:12 +0100 (Tue, 18 Dec 2007) | 4 lines
Optimized with single loop approach and nicer printing calls, inspired by
doener's version. Also added list of update entries and their respective
update.
........
r3795 | b_lindeijer | 2007-12-19 10:26:21 +0100 (Wed, 19 Dec 2007) | 4 lines
Fixed association of entries to update, added no-cache headers, added a bit of
error reporting in case of invalid zip files, kept original ordering of the
update list and sorted the list of entries on their filename.
........
r3796 | b_lindeijer | 2007-12-19 11:32:28 +0100 (Wed, 19 Dec 2007) | 3 lines
Added list of files in each update with indication on whether they are still
used.
........
r3797 | b_lindeijer | 2007-12-19 12:16:24 +0100 (Wed, 19 Dec 2007) | 2 lines
Fixed weird problem with zip_open failing with relative path.
........
r3798 | b_lindeijer | 2007-12-19 12:22:50 +0100 (Wed, 19 Dec 2007) | 2 lines
Incorporated some more of doener's leet PHP skills. ;)
........
r3800 | crush_tmw | 2007-12-19 19:11:22 +0100 (Wed, 19 Dec 2007) | 1 line
Fixed a map bug (monster trap) on map 18 (woodland village surrounding)
........
r3814 | b_lindeijer | 2007-12-24 17:23:56 +0100 (Mon, 24 Dec 2007) | 2 lines
Updated debian subfolder.
........
r3817 | b_lindeijer | 2007-12-25 15:26:22 +0100 (Tue, 25 Dec 2007) | 2 lines
Fixed missing backslash.
........
r3822 | crush_tmw | 2007-12-28 01:26:57 +0100 (Fri, 28 Dec 2007) | 1 line
Some mapping errors fixed by Zipon.
........
r3824 | crush_tmw | 2007-12-29 03:25:16 +0100 (Sat, 29 Dec 2007) | 1 line
Added new map by 5t3v3 (east desert cave) and enhanced version of eastern desert by Len.
........
r3827 | crush_tmw | 2007-12-30 01:28:00 +0100 (Sun, 30 Dec 2007) | 1 line
switched layer compression on.
........
r3830 | crush_tmw | 2008-01-03 18:17:00 +0100 (Thu, 03 Jan 2008) | 1 line
Some map bugs reported by Strump, fixed by Zipon.
........
r3840 | crush_tmw | 2008-01-14 11:22:14 +0100 (Mon, 14 Jan 2008) | 1 line
Added new versions of snow maps by 5t3v3 (with minor fixes)
........
r3845 | crush_tmw | 2008-01-19 12:43:32 +0100 (Sat, 19 Jan 2008) | 1 line
Fixes for the new snowland maps by 5t3v3.
........
r3846 | crush_tmw | 2008-01-19 14:00:37 +0100 (Sat, 19 Jan 2008) | 1 line
Added hot spring particle effect to pond south of snow village.
........
r3873 | crush_tmw | 2008-02-08 23:07:21 +0100 (Fri, 08 Feb 2008) | 1 line
Added Dimonds Cove Restaurant maps.
........
r3875 | crush_tmw | 2008-02-10 15:40:00 +0100 (Sun, 10 Feb 2008) | 1 line
Added Dimonds Cove outdoor map.
........
Diffstat (limited to 'tools/tmxcopy/map.cpp')
-rw-r--r-- | tools/tmxcopy/map.cpp | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/tools/tmxcopy/map.cpp b/tools/tmxcopy/map.cpp new file mode 100644 index 00000000..0674ae1a --- /dev/null +++ b/tools/tmxcopy/map.cpp @@ -0,0 +1,371 @@ +/* + * TMXCopy + * Copyright 2007 Philipp Sehmisch + * + * + * TMXCopy 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. + * + * TMXCopy 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 TMXCopy; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <iostream> +#include <map> +#include <list> + +#include <zlib.h> + +#include "xmlutils.h" +#include "zlibutils.h" +#include "base64.h" +#include "tostring.h" + +#include "map.hpp" + +Map::Map(std::string filename): + mMaxGid(0) +{ + std::cout<<"Loading map "<<filename<<std::endl; + //load XML tree + mXmlDoc = xmlReadFile(filename.c_str(), NULL, 0); + + if (!mXmlDoc) + { + std::cerr<<"Could not load "<<filename; + throw 1; + } + + xmlNodePtr rootNode = xmlDocGetRootElement(mXmlDoc); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "map")) { + std::cerr<<filename<<"is not a Tiled map file!"; + throw 1; + } + + mWidth = XML::getProperty(rootNode, "width", 0); + mHeight = XML::getProperty(rootNode, "height", 0); + int layerNum = 0; + for_each_xml_child_node(node, rootNode) + { + if (xmlStrEqual(node->name, BAD_CAST "tileset")) + { + //add tilesets to vector of used tilesets + Tileset* tileset = new Tileset; + tileset->name = XML::getProperty(node, "name", "Unnamed"); + tileset->tilewidth = XML::getProperty(node, "tilewidth", 0); + tileset->tileheight = XML::getProperty(node, "tileheight", 0); + tileset->firstgid = XML::getProperty(node, "firstgid", 0); + for_each_xml_child_node(imageNode, node) + { + if (xmlStrEqual(imageNode->name, BAD_CAST "image")) + tileset->imagefile = XML::getProperty(imageNode, "source", ""); + } + + //add tileset to tileset list + Map::mTilesets.push_back(tileset); + } + } + + for_each_xml_child_node(node, rootNode) + { + if (xmlStrEqual(node->name, BAD_CAST "layer")) + { + Layer* layer = new Layer; + layer->resize(mWidth * mHeight); + //build layer information + for_each_xml_child_node(dataNode, node) + { + if (!xmlStrEqual(dataNode->name, BAD_CAST "data")) continue; + + std::string encoding = XML::getProperty(dataNode, "encoding", ""); + std::string compression = XML::getProperty(dataNode, "compression", ""); + + if (encoding != "base64") + { + std::cerr<<"Layers in "<<filename<<" are not base64 encoded!"; + return; + } + + // Read base64 encoded map file + xmlNodePtr dataChild = dataNode->xmlChildrenNode; + if (!dataChild) + continue; + + int len = strlen((const char*)dataChild->content) + 1; + unsigned char *charData = new unsigned char[len + 1]; + const char *charStart = (const char*)dataChild->content; + unsigned char *charIndex = charData; + + while (*charStart) { + if (*charStart != ' ' && *charStart != '\t' && + *charStart != '\n') + { + *charIndex = *charStart; + charIndex++; + } + charStart++; + } + *charIndex = '\0'; + + int binLen; + unsigned char *binData = + php3_base64_decode(charData, strlen((char*)charData), &binLen); + + delete[] charData; + + if (binData) { + if (compression == "gzip") + { + unsigned char *inflated; + unsigned int inflatedSize = + inflateMemory(binData, binLen, inflated); + free(binData); + binData = inflated; + binLen = inflatedSize; + if (inflated == NULL) + { + std::cerr<<"Error: while decompressing layer "<<layerNum<<" in "<<filename; + throw 1; + } + } + + int c = 0; + for (int i = 0; i < binLen - 3; i += 4) { + int gid = binData[i] | + binData[i + 1] << 8 | + binData[i + 2] << 16 | + binData[i + 3] << 24; + + if (gid == 0) + { + layer->at(c).tileset = -1; + layer->at(c).index = 0; + } + else + { + for (int s = mTilesets.size()-1; s >= 0; s--) + { + if (mTilesets.at(s)->firstgid < gid) + { + layer->at(c).tileset = s; + layer->at(c).index = gid - mTilesets.at(s)->firstgid; + if (mMaxGid < gid) mMaxGid = gid; + break; + } + } + } + + c++; + } + free(binData); + } else { + std::cerr<<"error processing layer data in "<<filename<<std::endl; + } + } + mLayers.push_back(layer); + layerNum++; + } + } + + std::cout<<"tilesets: "<<mTilesets.size()<<std::endl; + std::cout<<"layers:"<<mLayers.size()<<std::endl; + std::cout<<"largest GID:"<<mMaxGid<<std::endl<<std::endl; +} + +bool Map::overwrite( Map* srcMap, + int srcX, int srcY, int srcWidth, int srcHeight, + int destX, int destY) +{ + //plausibility check of coordinates + bool checkPassed = true; + if (srcX + srcWidth > srcMap->getWidth()) { + std::cerr<<"Error: Area exceeds right map border of source map!"; + checkPassed = false; + } + if (srcY + srcHeight > srcMap->getHeight()) { + std::cerr<<"Error: Area exceeds lower map border of source map!"; + checkPassed = false; + } + if (destX + srcWidth > mWidth) { + std::cerr<<"Error: Area exceeds right map border of target map!"; + checkPassed = false; + } + if (destY + srcHeight > mHeight) { + std::cerr<<"Error: Area exceeds lower map border of target map!"; + checkPassed = false; + } + if (!checkPassed) return false; + + std::map<int, int> translation; + translation[-1] = -1; + std::vector<Tileset*>* srcTilesets = srcMap->getTilesets(); + + //add new tilesets and add redundant tilesets to list of redundand tilesets + for (int a = 0; a < srcTilesets->size(); a++) + { + int b; + for (b = 0; b < mTilesets.size(); b++) + { + if (*srcTilesets->at(a) == *mTilesets.at(b)) + { + break; + } + } + if (b == mTilesets.size()) + { + mMaxGid += srcTilesets->at(a)->firstgid; + srcTilesets->at(a)->firstgid = mMaxGid;//it is possible to get some holes in the gid index this way but who cares, we got 32bit. + mTilesets.push_back(srcTilesets->at(a)); + } + translation[a] = b; + } + + //combining layer information + for (int i = 0; i < srcMap->getNumberOfLayers(); i++) + { + Layer* srcLayer = srcMap->getLayer(i); + Layer* destLayer = mLayers.at(i); + + for (int y=0; y<srcWidth; y++) + { + + for (int x=0; x<srcHeight; x++) + { + int srcIndex = srcMap->getWidth() * (y + srcY) + (x + srcX); + int tgtIndex = mWidth * (y + destY) + (x + destX); + Tile tmpTile = srcLayer->at(srcIndex); + tmpTile.tileset = translation[tmpTile.tileset]; + destLayer->at(tgtIndex) = tmpTile; + } + } + } + + std::clog<<"copying successful!"<<std::endl; +} + +int Map::save(std::string filename) +{ + //remove old tileset and layer information in XML tree + xmlNodePtr rootNode = xmlDocGetRootElement(mXmlDoc); + std::list<xmlNodePtr> toRemove; + for_each_xml_child_node(node, rootNode) + { + if ( xmlStrEqual(node->name, BAD_CAST "tileset") + || xmlStrEqual(node->name, BAD_CAST "layer")) + { + toRemove.push_back(node); + } + } + + while (!toRemove.empty()) + { + xmlUnlinkNode(toRemove.back()); + xmlFreeNode(toRemove.back()); + toRemove.pop_back(); + } + + //TODO: reorganize GIDs + + //add new tileset information to XML tree + for (int i = 0; i< mTilesets.size(); i++) + { + xmlNodePtr newNode; + + xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST " ")); + newNode = xmlNewNode(NULL, BAD_CAST "tileset"); + xmlNewProp(newNode, BAD_CAST "name", BAD_CAST mTilesets.at(i)->name.c_str()); + xmlNewProp(newNode, BAD_CAST "firstgid", BAD_CAST toString(mTilesets.at(i)->firstgid).c_str()); + xmlNewProp(newNode, BAD_CAST "tilewidth", BAD_CAST toString(mTilesets.at(i)->tilewidth).c_str()); + xmlNewProp(newNode, BAD_CAST "tileheight", BAD_CAST toString(mTilesets.at(i)->tileheight).c_str()); + xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlNodePtr imageNode = xmlNewNode(NULL, BAD_CAST "image"); + xmlNewProp(imageNode, BAD_CAST "source", BAD_CAST mTilesets.at(i)->imagefile.c_str()); + xmlAddChild(newNode, imageNode); + xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlAddChild(rootNode, newNode); + xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n")); + } + + //add new layer information to XML tree + for (int i = 0; i < mLayers.size(); i++) + { + //lay out layer information in binary + unsigned char* binData = (unsigned char*)malloc(mWidth * mHeight * 4); + + for (int a=0; a < mWidth * mHeight; a++) + { + Tile tile = mLayers.at(i)->at(a); + int ldata; + if (tile.tileset != -1) + { + ldata = tile.index + mTilesets.at(tile.tileset)->firstgid; + } else { + ldata = 0; + } + + binData[a * 4 + 0] = (ldata & 0x000000ff); + binData[a * 4 + 1] = (ldata & 0x0000ff00) >> 8; + binData[a * 4 + 2] = (ldata & 0x00ff0000) >> 16; + binData[a * 4 + 3] = (ldata & 0xff000000) >> 24; + } + + + // GZIP layer information + // Doesn't work yet. + /* + unsigned char* gzipData = (unsigned char*)malloc((mWidth * mHeight * 4) + 128); + unsigned int gzipLen; + compressMemory (binData, (mWidth * mHeight * 4) + 128, gzipData, gzipLen); + free (binData); + std::cout<<"GZIP length: "<<gzipLen<<std::endl; + */ + + //encode layer information in base64 + unsigned char* base64Data; + int base64len; + //base64Data = php3_base64_encode(gzipData, gzipLen, &base64len); + base64Data = php3_base64_encode(binData, (mWidth * mHeight * 4), &base64len); + //free(gzipData); + + xmlNodePtr newNode; + xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST " ")); + newNode = xmlNewNode(NULL, BAD_CAST "layer"); + xmlNewProp(newNode, BAD_CAST "name", BAD_CAST ("Layer" + toString(i)).c_str()); + xmlNewProp(newNode, BAD_CAST "width", BAD_CAST toString(mWidth).c_str()); + xmlNewProp(newNode, BAD_CAST "height", BAD_CAST toString(mHeight).c_str()); + xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlNodePtr dataNode = xmlNewNode(NULL, BAD_CAST "data"); + xmlNewProp(dataNode, BAD_CAST "encoding", BAD_CAST "base64"); + //xmlNewProp(dataNode, BAD_CAST "compression", BAD_CAST "gzip"); + xmlAddChild(dataNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlAddChild(dataNode, xmlNewDocText(mXmlDoc, BAD_CAST base64Data)); + xmlAddChild(dataNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlAddChild(newNode, dataNode); + xmlAddChild(newNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n ")); + xmlAddChild(rootNode, newNode); + xmlAddChild(rootNode, xmlNewDocText(mXmlDoc, BAD_CAST "\n")); + } + + //save XML tree + int retval = xmlSaveFile(filename.c_str(), mXmlDoc); + + if (retval == -1) + { + std::cerr<<"Could not write outfile "<<filename<<std::endl; + return false; + } + else + { + std::cout<<"File saved successfully to"<<filename<<std::endl; + return true; + } +} |