123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- /****************************************************************************
- Copyright (c) 2011 Максим Аксенов
- Copyright (c) 2009-2010 Ricardo Quesada
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2011 Zynga Inc.
- Copyright (c) 2013-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- http://www.cocos2d-x.org
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include "2d/CCTMXXMLParser.h"
- #include <unordered_map>
- #include <sstream>
- #include "2d/CCTMXTiledMap.h"
- #include "base/ZipUtils.h"
- #include "base/base64.h"
- #include "base/CCDirector.h"
- #include "platform/CCFileUtils.h"
- using namespace std;
- NS_CC_BEGIN
- // implementation TMXLayerInfo
- TMXLayerInfo::TMXLayerInfo()
- : _name("")
- , _tiles(nullptr)
- , _ownTiles(true)
- {
- }
- TMXLayerInfo::~TMXLayerInfo()
- {
- CCLOGINFO("deallocing TMXLayerInfo: %p", this);
- if (_ownTiles && _tiles)
- {
- free(_tiles);
- _tiles = nullptr;
- }
- }
- ValueMap& TMXLayerInfo::getProperties()
- {
- return _properties;
- }
- void TMXLayerInfo::setProperties(ValueMap var)
- {
- _properties = var;
- }
- // implementation TMXTilesetInfo
- TMXTilesetInfo::TMXTilesetInfo()
- :_firstGid(0)
- ,_tileSize(Size::ZERO)
- ,_spacing(0)
- ,_margin(0)
- ,_imageSize(Size::ZERO)
- {
- }
- TMXTilesetInfo::~TMXTilesetInfo()
- {
- CCLOGINFO("deallocing TMXTilesetInfo: %p", this);
- }
- Rect TMXTilesetInfo::getRectForGID(uint32_t gid)
- {
- Rect rect;
- rect.size = _tileSize;
- gid &= kTMXFlippedMask;
- gid = gid - _firstGid;
- // max_x means the column count in tile map
- // in the origin:
- // max_x = (int)((_imageSize.width - _margin*2 + _spacing) / (_tileSize.width + _spacing));
- // but in editor "Tiled", _margin variable only effect the left side
- // for compatible with "Tiled", change the max_x calculation
- int max_x = (int)((_imageSize.width - _margin + _spacing) / (_tileSize.width + _spacing));
-
- rect.origin.x = (gid % max_x) * (_tileSize.width + _spacing) + _margin;
- rect.origin.y = (gid / max_x) * (_tileSize.height + _spacing) + _margin;
- return rect;
- }
- // implementation TMXMapInfo
- TMXMapInfo * TMXMapInfo::create(const std::string& tmxFile)
- {
- TMXMapInfo *ret = new (std::nothrow) TMXMapInfo();
- if (ret->initWithTMXFile(tmxFile))
- {
- ret->autorelease();
- return ret;
- }
- CC_SAFE_DELETE(ret);
- return nullptr;
- }
- TMXMapInfo * TMXMapInfo::createWithXML(const std::string& tmxString, const std::string& resourcePath)
- {
- TMXMapInfo *ret = new (std::nothrow) TMXMapInfo();
- if (ret->initWithXML(tmxString, resourcePath))
- {
- ret->autorelease();
- return ret;
- }
- CC_SAFE_DELETE(ret);
- return nullptr;
- }
- void TMXMapInfo::internalInit(const std::string& tmxFileName, const std::string& resourcePath)
- {
- if (!tmxFileName.empty())
- {
- _TMXFileName = FileUtils::getInstance()->fullPathForFilename(tmxFileName);
- }
-
- if (!resourcePath.empty())
- {
- _resources = resourcePath;
- }
-
- _objectGroups.reserve(4);
- // tmp vars
- _currentString = "";
- _storingCharacters = false;
- _layerAttribs = TMXLayerAttribNone;
- _parentElement = TMXPropertyNone;
- _currentFirstGID = -1;
- }
- bool TMXMapInfo::initWithXML(const std::string& tmxString, const std::string& resourcePath)
- {
- internalInit("", resourcePath);
- return parseXMLString(tmxString);
- }
- bool TMXMapInfo::initWithTMXFile(const std::string& tmxFile)
- {
- internalInit(tmxFile, "");
- return parseXMLFile(_TMXFileName);
- }
- TMXMapInfo::TMXMapInfo()
- : _orientation(TMXOrientationOrtho)
- , _staggerAxis(TMXStaggerAxis_Y)
- , _staggerIndex(TMXStaggerIndex_Even)
- , _hexSideLength(0)
- , _parentElement(0)
- , _parentGID(0)
- , _mapSize(Size::ZERO)
- , _tileSize(Size::ZERO)
- , _layerAttribs(0)
- , _storingCharacters(false)
- , _xmlTileIndex(0)
- , _currentFirstGID(-1)
- , _recordFirstGID(true)
- {
- }
- TMXMapInfo::~TMXMapInfo()
- {
- CCLOGINFO("deallocing TMXMapInfo: %p", this);
- }
- bool TMXMapInfo::parseXMLString(const std::string& xmlString)
- {
- size_t len = xmlString.size();
- if (len <= 0)
- return false;
- SAXParser parser;
- if (false == parser.init("UTF-8") )
- {
- return false;
- }
- parser.setDelegator(this);
- return parser.parse(xmlString.c_str(), len);
- }
- bool TMXMapInfo::parseXMLFile(const std::string& xmlFilename)
- {
- SAXParser parser;
-
- if (false == parser.init("UTF-8") )
- {
- return false;
- }
-
- parser.setDelegator(this);
- return parser.parse(FileUtils::getInstance()->fullPathForFilename(xmlFilename));
- }
- // the XML parser calls here with all the elements
- void TMXMapInfo::startElement(void* /*ctx*/, const char *name, const char **atts)
- {
- TMXMapInfo *tmxMapInfo = this;
- std::string elementName = name;
- ValueMap attributeDict;
- if (atts && atts[0])
- {
- for (int i = 0; atts[i]; i += 2)
- {
- std::string key = atts[i];
- std::string value = atts[i+1];
- attributeDict.emplace(key, Value(value));
- }
- }
- if (elementName == "map")
- {
- std::string version = attributeDict["version"].asString();
- if ( version != "1.0")
- {
- CCLOG("cocos2d: TMXFormat: Unsupported TMX version: %s", version.c_str());
- }
- std::string orientationStr = attributeDict["orientation"].asString();
- if (orientationStr == "orthogonal") {
- tmxMapInfo->setOrientation(TMXOrientationOrtho);
- }
- else if (orientationStr == "isometric") {
- tmxMapInfo->setOrientation(TMXOrientationIso);
- }
- else if (orientationStr == "hexagonal") {
- tmxMapInfo->setOrientation(TMXOrientationHex);
- }
- else if (orientationStr == "staggered") {
- tmxMapInfo->setOrientation(TMXOrientationStaggered);
- }
- else {
- CCLOG("cocos2d: TMXFomat: Unsupported orientation: %d", tmxMapInfo->getOrientation());
- }
-
- std::string staggerAxisStr = attributeDict["staggeraxis"].asString();
- if (staggerAxisStr == "x") {
- tmxMapInfo->setStaggerAxis(TMXStaggerAxis_X);
- }
- else if (staggerAxisStr == "y") {
- tmxMapInfo->setStaggerAxis(TMXStaggerAxis_Y);
- }
- std::string staggerIndex = attributeDict["staggerindex"].asString();
- if (staggerIndex == "odd") {
- tmxMapInfo->setStaggerIndex(TMXStaggerIndex_Odd);
- }
- else if (staggerIndex == "even") {
- tmxMapInfo->setStaggerIndex(TMXStaggerIndex_Even);
- }
- float hexSideLength = attributeDict["hexsidelength"].asFloat();
- tmxMapInfo->setHexSideLength(hexSideLength);
- Size s;
- s.width = attributeDict["width"].asFloat();
- s.height = attributeDict["height"].asFloat();
- tmxMapInfo->setMapSize(s);
- s.width = attributeDict["tilewidth"].asFloat();
- s.height = attributeDict["tileheight"].asFloat();
- tmxMapInfo->setTileSize(s);
-
- // The parent element is now "map"
- tmxMapInfo->setParentElement(TMXPropertyMap);
- }
- else if (elementName == "tileset")
- {
- // If this is an external tileset then start parsing that
- std::string externalTilesetFilename = attributeDict["source"].asString();
- if (externalTilesetFilename != "")
- {
- _externalTilesetFilename = externalTilesetFilename;
- // Tileset file will be relative to the map file. So we need to convert it to an absolute path
- if (_TMXFileName.find_last_of("/") != string::npos)
- {
- string dir = _TMXFileName.substr(0, _TMXFileName.find_last_of("/") + 1);
- externalTilesetFilename = dir + externalTilesetFilename;
- }
- else
- {
- externalTilesetFilename = _resources + "/" + externalTilesetFilename;
- }
- externalTilesetFilename = FileUtils::getInstance()->fullPathForFilename(externalTilesetFilename);
-
- _currentFirstGID = attributeDict["firstgid"].asInt();
- if (_currentFirstGID < 0)
- {
- _currentFirstGID = 0;
- }
- _recordFirstGID = false;
-
- tmxMapInfo->parseXMLFile(externalTilesetFilename);
- }
- else
- {
- TMXTilesetInfo *tileset = new (std::nothrow) TMXTilesetInfo();
- tileset->_name = attributeDict["name"].asString();
-
- if (_recordFirstGID)
- {
- // unset before, so this is tmx file.
- tileset->_firstGid = attributeDict["firstgid"].asInt();
-
- if (tileset->_firstGid < 0)
- {
- tileset->_firstGid = 0;
- }
- }
- else
- {
- tileset->_firstGid = _currentFirstGID;
- _currentFirstGID = 0;
- }
-
- tileset->_spacing = attributeDict["spacing"].asInt();
- tileset->_margin = attributeDict["margin"].asInt();
- Size s;
- s.width = attributeDict["tilewidth"].asFloat();
- s.height = attributeDict["tileheight"].asFloat();
- tileset->_tileSize = s;
- tmxMapInfo->getTilesets().pushBack(tileset);
- tileset->release();
- }
- }
- else if (elementName == "tile")
- {
- if (tmxMapInfo->getParentElement() == TMXPropertyLayer)
- {
- TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
- Size layerSize = layer->_layerSize;
- uint32_t gid = static_cast<uint32_t>(attributeDict["gid"].asUnsignedInt());
- int tilesAmount = layerSize.width*layerSize.height;
-
- if (_xmlTileIndex < tilesAmount)
- {
- layer->_tiles[_xmlTileIndex++] = gid;
- }
- }
- else
- {
- TMXTilesetInfo* info = tmxMapInfo->getTilesets().back();
- tmxMapInfo->setParentGID(info->_firstGid + attributeDict["id"].asInt());
- tmxMapInfo->getTileProperties()[tmxMapInfo->getParentGID()] = Value(ValueMap());
- tmxMapInfo->setParentElement(TMXPropertyTile);
- }
- }
- else if (elementName == "layer")
- {
- TMXLayerInfo *layer = new (std::nothrow) TMXLayerInfo();
- layer->_name = attributeDict["name"].asString();
- Size s;
- s.width = attributeDict["width"].asFloat();
- s.height = attributeDict["height"].asFloat();
- layer->_layerSize = s;
- Value& visibleValue = attributeDict["visible"];
- layer->_visible = visibleValue.isNull() ? true : visibleValue.asBool();
- Value& opacityValue = attributeDict["opacity"];
- layer->_opacity = opacityValue.isNull() ? 255 : (unsigned char)(255.0f * opacityValue.asFloat());
- float x = attributeDict["x"].asFloat();
- float y = attributeDict["y"].asFloat();
- layer->_offset.set(x, y);
- tmxMapInfo->getLayers().pushBack(layer);
- layer->release();
- // The parent element is now "layer"
- tmxMapInfo->setParentElement(TMXPropertyLayer);
- }
- else if (elementName == "objectgroup")
- {
- TMXObjectGroup *objectGroup = new (std::nothrow) TMXObjectGroup();
- objectGroup->setGroupName(attributeDict["name"].asString());
- Vec2 positionOffset;
- positionOffset.x = attributeDict["x"].asFloat() * tmxMapInfo->getTileSize().width;
- positionOffset.y = attributeDict["y"].asFloat() * tmxMapInfo->getTileSize().height;
- objectGroup->setPositionOffset(positionOffset);
- tmxMapInfo->getObjectGroups().pushBack(objectGroup);
- objectGroup->release();
- // The parent element is now "objectgroup"
- tmxMapInfo->setParentElement(TMXPropertyObjectGroup);
- }
- else if (elementName == "tileoffset")
- {
- TMXTilesetInfo* tileset = tmxMapInfo->getTilesets().back();
-
- double tileOffsetX = attributeDict["x"].asDouble();
-
- double tileOffsetY = attributeDict["y"].asDouble();
-
- tileset->_tileOffset = Vec2(tileOffsetX, tileOffsetY);
-
- }
- else if (elementName == "image")
- {
- TMXTilesetInfo* tileset = tmxMapInfo->getTilesets().back();
- // build full path
- std::string imagename = attributeDict["source"].asString();
- tileset->_originSourceImage = imagename;
- if (_TMXFileName.find_last_of("/") != string::npos)
- {
- string dir = _TMXFileName.substr(0, _TMXFileName.find_last_of("/") + 1);
- tileset->_sourceImage = dir + imagename;
- }
- else
- {
- tileset->_sourceImage = _resources + (_resources.size() ? "/" : "") + imagename;
- }
- }
- else if (elementName == "data")
- {
- std::string encoding = attributeDict["encoding"].asString();
- std::string compression = attributeDict["compression"].asString();
- if (encoding == "")
- {
- tmxMapInfo->setLayerAttribs(tmxMapInfo->getLayerAttribs() | TMXLayerAttribNone);
-
- TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
- Size layerSize = layer->_layerSize;
- int tilesAmount = layerSize.width*layerSize.height;
- uint32_t *tiles = (uint32_t*) malloc(tilesAmount*sizeof(uint32_t));
- // set all value to 0
- memset(tiles, 0, tilesAmount*sizeof(int));
- layer->_tiles = tiles;
- }
- else if (encoding == "base64")
- {
- int layerAttribs = tmxMapInfo->getLayerAttribs();
- tmxMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribBase64);
- tmxMapInfo->setStoringCharacters(true);
- if (compression == "gzip")
- {
- layerAttribs = tmxMapInfo->getLayerAttribs();
- tmxMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribGzip);
- } else
- if (compression == "zlib")
- {
- layerAttribs = tmxMapInfo->getLayerAttribs();
- tmxMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribZlib);
- }
- CCASSERT( compression == "" || compression == "gzip" || compression == "zlib", "TMX: unsupported compression method" );
- }
- else if (encoding == "csv")
- {
- int layerAttribs = tmxMapInfo->getLayerAttribs();
- tmxMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribCSV);
- tmxMapInfo->setStoringCharacters(true);
- }
- }
- else if (elementName == "object")
- {
- TMXObjectGroup* objectGroup = tmxMapInfo->getObjectGroups().back();
- // The value for "type" was blank or not a valid class name
- // Create an instance of TMXObjectInfo to store the object and its properties
- ValueMap dict;
- // Parse everything automatically
- const char* keys[] = {"name", "type", "width", "height", "gid", "id"};
-
- for (const auto& key : keys)
- {
- Value value = attributeDict[key];
- dict[key] = value;
- }
- // But X and Y since they need special treatment
- // X
- int x = attributeDict["x"].asInt();
- // Y
- int y = attributeDict["y"].asInt();
-
- Vec2 p(x + objectGroup->getPositionOffset().x, _mapSize.height * _tileSize.height - y - objectGroup->getPositionOffset().y - attributeDict["height"].asInt());
- p = CC_POINT_PIXELS_TO_POINTS(p);
- dict["x"] = Value(p.x);
- dict["y"] = Value(p.y);
-
- int width = attributeDict["width"].asInt();
- int height = attributeDict["height"].asInt();
- Size s(width, height);
- s = CC_SIZE_PIXELS_TO_POINTS(s);
- dict["width"] = Value(s.width);
- dict["height"] = Value(s.height);
- dict["rotation"] = attributeDict["rotation"].asDouble();
- // Add the object to the objectGroup
- objectGroup->getObjects().push_back(Value(dict));
- // The parent element is now "object"
- tmxMapInfo->setParentElement(TMXPropertyObject);
- }
- else if (elementName == "property")
- {
- if ( tmxMapInfo->getParentElement() == TMXPropertyNone )
- {
- CCLOG( "TMX tile map: Parent element is unsupported. Cannot add property named '%s' with value '%s'",
- attributeDict["name"].asString().c_str(), attributeDict["value"].asString().c_str() );
- }
- else if ( tmxMapInfo->getParentElement() == TMXPropertyMap )
- {
- // The parent element is the map
- Value value = attributeDict["value"];
- std::string key = attributeDict["name"].asString();
- tmxMapInfo->getProperties().emplace(key, value);
- }
- else if ( tmxMapInfo->getParentElement() == TMXPropertyLayer )
- {
- // The parent element is the last layer
- TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
- Value value = attributeDict["value"];
- std::string key = attributeDict["name"].asString();
- // Add the property to the layer
- layer->getProperties().emplace(key, value);
- }
- else if ( tmxMapInfo->getParentElement() == TMXPropertyObjectGroup )
- {
- // The parent element is the last object group
- TMXObjectGroup* objectGroup = tmxMapInfo->getObjectGroups().back();
- Value value = attributeDict["value"];
- std::string key = attributeDict["name"].asString();
- objectGroup->getProperties().emplace(key, value);
- }
- else if ( tmxMapInfo->getParentElement() == TMXPropertyObject )
- {
- // The parent element is the last object
- TMXObjectGroup* objectGroup = tmxMapInfo->getObjectGroups().back();
- ValueMap& dict = objectGroup->getObjects().rbegin()->asValueMap();
- std::string propertyName = attributeDict["name"].asString();
- dict[propertyName] = attributeDict["value"];
- }
- else if ( tmxMapInfo->getParentElement() == TMXPropertyTile )
- {
- ValueMap& dict = tmxMapInfo->getTileProperties().at(tmxMapInfo->getParentGID()).asValueMap();
- std::string propertyName = attributeDict["name"].asString();
- dict[propertyName] = attributeDict["value"];
- }
- }
- else if (elementName == "polygon")
- {
- // find parent object's dict and add polygon-points to it
- TMXObjectGroup* objectGroup = _objectGroups.back();
- ValueMap& dict = objectGroup->getObjects().rbegin()->asValueMap();
- // get points value string
- std::string value = attributeDict["points"].asString();
- if (!value.empty())
- {
- ValueVector pointsArray;
- pointsArray.reserve(10);
- // parse points string into a space-separated set of points
- stringstream pointsStream(value);
- string pointPair;
- while (std::getline(pointsStream, pointPair, ' '))
- {
- // parse each point combo into a comma-separated x,y point
- stringstream pointStream(pointPair);
- string xStr, yStr;
-
- ValueMap pointDict;
- // set x
- if (std::getline(pointStream, xStr, ','))
- {
- int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x;
- pointDict["x"] = Value(x);
- }
- // set y
- if (std::getline(pointStream, yStr, ','))
- {
- int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y;
- pointDict["y"] = Value(y);
- }
-
- // add to points array
- pointsArray.push_back(Value(pointDict));
- }
-
- dict["points"] = Value(pointsArray);
- }
- }
- else if (elementName == "polyline")
- {
- // find parent object's dict and add polyline-points to it
- TMXObjectGroup* objectGroup = _objectGroups.back();
- ValueMap& dict = objectGroup->getObjects().rbegin()->asValueMap();
-
- // get points value string
- std::string value = attributeDict["points"].asString();
- if (!value.empty())
- {
- ValueVector pointsArray;
- pointsArray.reserve(10);
-
- // parse points string into a space-separated set of points
- stringstream pointsStream(value);
- string pointPair;
- while (std::getline(pointsStream, pointPair, ' '))
- {
- // parse each point combo into a comma-separated x,y point
- stringstream pointStream(pointPair);
- string xStr, yStr;
-
- ValueMap pointDict;
-
- // set x
- if (std::getline(pointStream, xStr, ','))
- {
- int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x;
- pointDict["x"] = Value(x);
- }
-
- // set y
- if (std::getline(pointStream, yStr, ','))
- {
- int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y;
- pointDict["y"] = Value(y);
- }
-
- // add to points array
- pointsArray.push_back(Value(pointDict));
- }
-
- dict["polylinePoints"] = Value(pointsArray);
- }
- }
- }
- void TMXMapInfo::endElement(void* /*ctx*/, const char *name)
- {
- TMXMapInfo *tmxMapInfo = this;
- std::string elementName = name;
- if (elementName == "data")
- {
- if (tmxMapInfo->getLayerAttribs() & TMXLayerAttribBase64)
- {
- tmxMapInfo->setStoringCharacters(false);
-
- TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
-
- std::string currentString = tmxMapInfo->getCurrentString();
- unsigned char *buffer;
- auto len = base64Decode((unsigned char*)currentString.c_str(), (unsigned int)currentString.length(), &buffer);
- if (!buffer)
- {
- CCLOG("cocos2d: TiledMap: decode data error");
- return;
- }
-
- if (tmxMapInfo->getLayerAttribs() & (TMXLayerAttribGzip | TMXLayerAttribZlib))
- {
- unsigned char *deflated = nullptr;
- Size s = layer->_layerSize;
- // int sizeHint = s.width * s.height * sizeof(uint32_t);
- ssize_t sizeHint = s.width * s.height * sizeof(unsigned int);
-
- ssize_t CC_UNUSED inflatedLen = ZipUtils::inflateMemoryWithHint(buffer, len, &deflated, sizeHint);
- CCASSERT(inflatedLen == sizeHint, "inflatedLen should be equal to sizeHint!");
-
- free(buffer);
- buffer = nullptr;
-
- if (!deflated)
- {
- CCLOG("cocos2d: TiledMap: inflate data error");
- return;
- }
-
- layer->_tiles = reinterpret_cast<uint32_t*>(deflated);
- }
- else
- {
- layer->_tiles = reinterpret_cast<uint32_t*>(buffer);
- }
-
- tmxMapInfo->setCurrentString("");
- }
- else if (tmxMapInfo->getLayerAttribs() & TMXLayerAttribCSV)
- {
- unsigned char *buffer;
- TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
- tmxMapInfo->setStoringCharacters(false);
- std::string currentString = tmxMapInfo->getCurrentString();
- vector<string> gidTokens;
- istringstream filestr(currentString);
- string sRow;
- while(getline(filestr, sRow, '\n')) {
- string sGID;
- istringstream rowstr(sRow);
- while (getline(rowstr, sGID, ',')) {
- gidTokens.push_back(sGID);
- }
- }
- // 32-bits per gid
- buffer = (unsigned char*)malloc(gidTokens.size() * 4);
- if (!buffer)
- {
- CCLOG("cocos2d: TiledMap: CSV buffer not allocated.");
- return;
- }
- uint32_t* bufferPtr = reinterpret_cast<uint32_t*>(buffer);
- for(auto gidToken : gidTokens) {
- auto tileGid = (uint32_t)strtoul(gidToken.c_str(), nullptr, 10);
- *bufferPtr = tileGid;
- bufferPtr++;
- }
- layer->_tiles = reinterpret_cast<uint32_t*>(buffer);
- tmxMapInfo->setCurrentString("");
- }
- else if (tmxMapInfo->getLayerAttribs() & TMXLayerAttribNone)
- {
- _xmlTileIndex = 0;
- }
- }
- else if (elementName == "map")
- {
- // The map element has ended
- tmxMapInfo->setParentElement(TMXPropertyNone);
- }
- else if (elementName == "layer")
- {
- // The layer element has ended
- tmxMapInfo->setParentElement(TMXPropertyNone);
- }
- else if (elementName == "objectgroup")
- {
- // The objectgroup element has ended
- tmxMapInfo->setParentElement(TMXPropertyNone);
- }
- else if (elementName == "object")
- {
- // The object element has ended
- tmxMapInfo->setParentElement(TMXPropertyNone);
- }
- else if (elementName == "tileset")
- {
- _recordFirstGID = true;
- }
- }
- void TMXMapInfo::textHandler(void* /*ctx*/, const char *ch, size_t len)
- {
- TMXMapInfo *tmxMapInfo = this;
- std::string text(ch, 0, len);
- if (tmxMapInfo->isStoringCharacters())
- {
- std::string currentString = tmxMapInfo->getCurrentString();
- currentString += text;
- tmxMapInfo->setCurrentString(currentString);
- }
- }
- NS_CC_END
|