summaryrefslogtreecommitdiff
path: root/tools/tmxcopy/map.cpp
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2008-02-11 19:07:36 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2008-02-11 19:07:36 +0000
commit7f2a504d7bcbc255616af97e050e59b0a2d99c12 (patch)
tree358df0d3f4606aa5386a1937f4d8127633e99a99 /tools/tmxcopy/map.cpp
parent230c65a923aeaf456d61e5fbf4faec4c93313308 (diff)
downloadmana-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.cpp371
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;
+ }
+}