2010-08-26 17:53:35 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
2010-08-27 18:07:37 +08:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xmlmemory.h>
|
2010-09-06 20:26:19 +08:00
|
|
|
#include <map>
|
2010-08-27 18:07:37 +08:00
|
|
|
#include "CCTMXXMLParser.h"
|
2010-08-31 16:48:42 +08:00
|
|
|
#include "CCTMXTiledMap.h"
|
2010-08-27 18:07:37 +08:00
|
|
|
#include "ccMacros.h"
|
2010-11-29 10:49:43 +08:00
|
|
|
#include "support/file_support/FileData.h"
|
2010-08-27 18:07:37 +08:00
|
|
|
#include "CGPointExtension.h"
|
|
|
|
#include "support/base64.h"
|
|
|
|
#include "platform/platform.h"
|
|
|
|
|
|
|
|
namespace cocos2d {
|
|
|
|
|
2010-08-27 18:14:17 +08:00
|
|
|
void tmx_startElement(void *ctx, const xmlChar *name, const xmlChar **atts);
|
|
|
|
void tmx_endElement(void *ctx, const xmlChar *name);
|
|
|
|
void tmx_characters(void *ctx, const xmlChar *ch, int len);
|
2010-09-06 20:26:19 +08:00
|
|
|
const char* valueForKey(const char *key, std::map<std::string, std::string>* dict)
|
|
|
|
{
|
|
|
|
if (dict)
|
|
|
|
{
|
|
|
|
std::map<std::string, std::string>::iterator it = dict->find(key);
|
|
|
|
return it!=dict->end() ? it->second.c_str() : "";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2010-08-27 18:07:37 +08:00
|
|
|
// implementation CCTMXLayerInfo
|
|
|
|
CCTMXLayerInfo::CCTMXLayerInfo()
|
2010-08-31 18:11:31 +08:00
|
|
|
:m_bOwnTiles(true)
|
|
|
|
,m_uMinGID(100000)
|
|
|
|
,m_uMaxGID(0)
|
|
|
|
,m_sName("")
|
|
|
|
,m_pTiles(NULL)
|
|
|
|
,m_tOffset(CGPointZero)
|
2010-08-27 18:07:37 +08:00
|
|
|
{
|
2010-09-07 11:26:28 +08:00
|
|
|
m_pProperties= new CCXStringToStringDictionary();;
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
CCTMXLayerInfo::~CCTMXLayerInfo()
|
|
|
|
{
|
|
|
|
CCLOGINFO("cocos2d: deallocing.");
|
2010-09-06 20:26:19 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pProperties);
|
2010-08-27 18:07:37 +08:00
|
|
|
if( m_bOwnTiles && m_pTiles )
|
|
|
|
{
|
|
|
|
delete [] m_pTiles;
|
|
|
|
m_pTiles = NULL;
|
|
|
|
}
|
|
|
|
}
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary * CCTMXLayerInfo::getProperties()
|
|
|
|
{
|
|
|
|
return m_pProperties;
|
|
|
|
}
|
|
|
|
void CCTMXLayerInfo::setProperties(CCXStringToStringDictionary* var)
|
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(var);
|
2010-09-07 11:26:28 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pProperties);
|
|
|
|
m_pProperties = var;
|
|
|
|
}
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// implementation CCTMXTilesetInfo
|
2010-08-31 18:11:31 +08:00
|
|
|
CCTMXTilesetInfo::CCTMXTilesetInfo()
|
|
|
|
:m_uFirstGid(0)
|
|
|
|
,m_tTileSize(CGSizeZero)
|
|
|
|
,m_uSpacing(0)
|
|
|
|
,m_uMargin(0)
|
|
|
|
,m_tImageSize(CGSizeZero)
|
|
|
|
{
|
|
|
|
}
|
2010-08-27 18:07:37 +08:00
|
|
|
CCTMXTilesetInfo::~CCTMXTilesetInfo()
|
|
|
|
{
|
|
|
|
CCLOGINFO("cocos2d: deallocing.");
|
|
|
|
}
|
|
|
|
CGRect CCTMXTilesetInfo::rectForGID(unsigned int gid)
|
|
|
|
{
|
|
|
|
CGRect rect;
|
|
|
|
rect.size = m_tTileSize;
|
|
|
|
gid = gid - m_uFirstGid;
|
|
|
|
int max_x = (int)((m_tImageSize.width - m_uMargin*2 + m_uSpacing) / (m_tTileSize.width + m_uSpacing));
|
|
|
|
// int max_y = (imageSize.height - margin*2 + spacing) / (tileSize.height + spacing);
|
|
|
|
rect.origin.x = (gid % max_x) * (m_tTileSize.width + m_uSpacing) + m_uMargin;
|
|
|
|
rect.origin.y = (gid / max_x) * (m_tTileSize.height + m_uSpacing) + m_uMargin;
|
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
// implementation CCTMXMapInfo
|
|
|
|
|
|
|
|
CCTMXMapInfo * CCTMXMapInfo::formatWithTMXFile(const char *tmxFile)
|
|
|
|
{
|
|
|
|
CCTMXMapInfo *pRet = new CCTMXMapInfo();
|
|
|
|
if(pRet->initWithTMXFile(tmxFile))
|
|
|
|
{
|
2010-08-30 11:45:46 +08:00
|
|
|
pRet->autorelease();
|
|
|
|
return pRet;
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
CCX_SAFE_DELETE(pRet);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bool CCTMXMapInfo::initWithTMXFile(const char *tmxFile)
|
|
|
|
{
|
2010-08-30 11:45:46 +08:00
|
|
|
m_pTilesets = new NSMutableArray<CCTMXTilesetInfo*>();
|
|
|
|
m_pLayers = new NSMutableArray<CCTMXLayerInfo*>();
|
2010-09-07 18:04:57 +08:00
|
|
|
m_sTMXFileName = CCFileUtils::fullPathFromRelativePath(tmxFile);
|
2010-08-30 11:45:46 +08:00
|
|
|
m_pObjectGroups = new NSMutableArray<CCTMXObjectGroup*>();
|
2010-09-07 11:26:28 +08:00
|
|
|
m_pProperties = new CCXStringToStringDictionary();
|
|
|
|
m_pTileProperties = new NSDictionary<int, CCXStringToStringDictionary*>();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// tmp vars
|
|
|
|
m_sCurrentString = "";
|
|
|
|
m_bStoringCharacters = false;
|
|
|
|
m_nLayerAttribs = TMXLayerAttribNone;
|
|
|
|
m_nParentElement = TMXPropertyNone;
|
|
|
|
|
2010-09-07 18:04:57 +08:00
|
|
|
return parseXMLFile(m_sTMXFileName.c_str());
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
2010-08-31 18:11:31 +08:00
|
|
|
CCTMXMapInfo::CCTMXMapInfo()
|
|
|
|
:m_bStoringCharacters(false)
|
|
|
|
,m_nLayerAttribs(0)
|
|
|
|
,m_tMapSize(CGSizeZero)
|
|
|
|
,m_tTileSize(CGSizeZero)
|
|
|
|
,m_pLayers(NULL)
|
|
|
|
,m_pTilesets(NULL)
|
2010-09-07 11:26:28 +08:00
|
|
|
,m_pObjectGroups(NULL)
|
|
|
|
,m_pProperties(NULL)
|
|
|
|
,m_pTileProperties(NULL)
|
2010-08-31 18:11:31 +08:00
|
|
|
{
|
|
|
|
}
|
2010-08-27 18:07:37 +08:00
|
|
|
CCTMXMapInfo::~CCTMXMapInfo()
|
|
|
|
{
|
|
|
|
CCLOGINFO("cocos2d: deallocing.");
|
2010-09-06 20:26:19 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pTilesets);
|
|
|
|
CCX_SAFE_RELEASE(m_pLayers);
|
|
|
|
CCX_SAFE_RELEASE(m_pProperties);
|
|
|
|
CCX_SAFE_RELEASE(m_pTileProperties);
|
|
|
|
CCX_SAFE_RELEASE(m_pObjectGroups);
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
2010-09-04 18:06:26 +08:00
|
|
|
NSMutableArray<CCTMXLayerInfo*> * CCTMXMapInfo::getLayers()
|
|
|
|
{
|
|
|
|
return m_pLayers;
|
|
|
|
}
|
|
|
|
void CCTMXMapInfo::setLayers(NSMutableArray<CCTMXLayerInfo*>* var)
|
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(var);
|
2010-09-06 11:45:02 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pLayers);
|
2010-09-04 18:06:26 +08:00
|
|
|
m_pLayers = var;
|
|
|
|
}
|
|
|
|
NSMutableArray<CCTMXTilesetInfo*> * CCTMXMapInfo::getTilesets()
|
|
|
|
{
|
|
|
|
return m_pTilesets;
|
|
|
|
}
|
|
|
|
void CCTMXMapInfo::setTilesets(NSMutableArray<CCTMXTilesetInfo*>* var)
|
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(var);
|
2010-09-06 11:45:02 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pTilesets);
|
2010-09-04 18:06:26 +08:00
|
|
|
m_pTilesets = var;
|
|
|
|
}
|
|
|
|
NSMutableArray<CCTMXObjectGroup*> * CCTMXMapInfo::getObjectGroups()
|
|
|
|
{
|
|
|
|
return m_pObjectGroups;
|
|
|
|
}
|
|
|
|
void CCTMXMapInfo::setObjectGroups(NSMutableArray<CCTMXObjectGroup*>* var)
|
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(var);
|
2010-09-06 11:45:02 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pObjectGroups);
|
2010-09-04 18:06:26 +08:00
|
|
|
m_pObjectGroups = var;
|
|
|
|
}
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary * CCTMXMapInfo::getProperties()
|
2010-09-06 20:26:19 +08:00
|
|
|
{
|
|
|
|
return m_pProperties;
|
|
|
|
}
|
2010-09-07 11:26:28 +08:00
|
|
|
void CCTMXMapInfo::setProperties(CCXStringToStringDictionary* var)
|
2010-09-06 20:26:19 +08:00
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(var);
|
2010-09-06 20:26:19 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pProperties);
|
|
|
|
m_pProperties = var;
|
|
|
|
}
|
2010-09-07 11:26:28 +08:00
|
|
|
NSDictionary<int, CCXStringToStringDictionary*> * CCTMXMapInfo::getTileProperties()
|
2010-09-06 20:26:19 +08:00
|
|
|
{
|
|
|
|
return m_pTileProperties;
|
|
|
|
}
|
2010-09-07 11:26:28 +08:00
|
|
|
void CCTMXMapInfo::setTileProperties(NSDictionary<int, CCXStringToStringDictionary*> * tileProperties)
|
2010-09-06 20:26:19 +08:00
|
|
|
{
|
2010-09-27 18:19:10 +08:00
|
|
|
CCX_SAFE_RETAIN(tileProperties);
|
2010-09-06 20:26:19 +08:00
|
|
|
CCX_SAFE_RELEASE(m_pTileProperties);
|
|
|
|
m_pTileProperties = tileProperties;
|
|
|
|
}
|
|
|
|
|
2010-08-27 18:07:37 +08:00
|
|
|
bool CCTMXMapInfo::parseXMLFile(const char *xmlFilename)
|
|
|
|
{
|
2010-11-29 10:49:43 +08:00
|
|
|
FileData data;
|
|
|
|
unsigned long size = 0;
|
|
|
|
char *pBuffer = (char*) data.getFileData(xmlFilename, "r", &size);
|
|
|
|
|
2010-08-27 18:07:37 +08:00
|
|
|
/*
|
|
|
|
* this initialize the library and check potential ABI mismatches
|
|
|
|
* between the version it was compiled for and the actual shared
|
|
|
|
* library used.
|
|
|
|
*/
|
|
|
|
LIBXML_TEST_VERSION
|
|
|
|
xmlSAXHandler saxHandler;
|
|
|
|
memset( &saxHandler, 0, sizeof(saxHandler) );
|
|
|
|
// Using xmlSAXVersion( &saxHandler, 2 ) generate crash as it sets plenty of other pointers...
|
|
|
|
saxHandler.initialized = XML_SAX2_MAGIC; // so we do this to force parsing as SAX2.
|
2010-08-27 18:14:17 +08:00
|
|
|
saxHandler.startElement = &tmx_startElement;
|
|
|
|
saxHandler.endElement = &tmx_endElement;
|
|
|
|
saxHandler.characters = &tmx_characters;
|
2010-08-27 18:07:37 +08:00
|
|
|
|
2010-11-29 10:49:43 +08:00
|
|
|
int result = xmlSAXUserParseMemory( &saxHandler, this, pBuffer, size );
|
2010-08-27 18:07:37 +08:00
|
|
|
if ( result != 0 )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Cleanup function for the XML library.
|
|
|
|
*/
|
|
|
|
xmlCleanupParser();
|
|
|
|
/*
|
|
|
|
* this is to debug memory for regression tests
|
|
|
|
*/
|
|
|
|
xmlMemoryDump();
|
2010-11-29 10:49:43 +08:00
|
|
|
|
2010-08-27 18:07:37 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// the XML parser calls here with all the elements
|
2010-08-27 18:14:17 +08:00
|
|
|
void tmx_startElement(void *ctx, const xmlChar *name, const xmlChar **atts)
|
2010-08-27 18:07:37 +08:00
|
|
|
{
|
|
|
|
CCTMXMapInfo *pTMXMapInfo = (CCTMXMapInfo*)(ctx);
|
|
|
|
std::string elementName = (char*)name;
|
2010-09-06 20:26:19 +08:00
|
|
|
std::map<std::string, std::string> *attributeDict = new std::map<std::string, std::string>();
|
2010-08-27 18:07:37 +08:00
|
|
|
if(atts && atts[0])
|
|
|
|
{
|
|
|
|
for(int i = 0; atts[i]; i += 2)
|
|
|
|
{
|
|
|
|
std::string key = (char*)atts[i];
|
|
|
|
std::string value = (char*)atts[i+1];
|
2010-09-06 20:26:19 +08:00
|
|
|
attributeDict->insert(pair<std::string, std::string>(key, value));
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(elementName == "map")
|
|
|
|
{
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string version = valueForKey("version", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
if ( version != "1.0")
|
|
|
|
{
|
|
|
|
CCLOG("cocos2d: TMXFormat: Unsupported TMX version: %@", version);
|
|
|
|
}
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string orientationStr = valueForKey("orientation", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
if( orientationStr == "orthogonal")
|
|
|
|
pTMXMapInfo->setOrientation(CCTMXOrientationOrtho);
|
|
|
|
else if ( orientationStr == "isometric")
|
|
|
|
pTMXMapInfo->setOrientation(CCTMXOrientationIso);
|
|
|
|
else if( orientationStr == "hexagonal")
|
|
|
|
pTMXMapInfo->setOrientation(CCTMXOrientationHex);
|
|
|
|
else
|
|
|
|
CCLOG("cocos2d: TMXFomat: Unsupported orientation: %d", pTMXMapInfo->getOrientation());
|
|
|
|
|
|
|
|
CGSize s;
|
2010-09-02 18:16:02 +08:00
|
|
|
s.width = (float)atof(valueForKey("width", attributeDict));
|
|
|
|
s.height = (float)atof(valueForKey("height", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
pTMXMapInfo->setMapSize(s);
|
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
s.width = (float)atof(valueForKey("tilewidth", attributeDict));
|
|
|
|
s.height = (float)atof(valueForKey("tileheight", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
pTMXMapInfo->setTileSize(s);
|
|
|
|
|
|
|
|
// The parent element is now "map"
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyMap);
|
|
|
|
}
|
|
|
|
else if(elementName == "tileset")
|
|
|
|
{
|
|
|
|
// If this is an external tileset then start parsing that
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string externalTilesetFilename = valueForKey("source", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
if (externalTilesetFilename != "")
|
|
|
|
{
|
2010-09-07 18:04:57 +08:00
|
|
|
externalTilesetFilename = CCFileUtils::fullPathFromRelativeFile(externalTilesetFilename.c_str(), pTMXMapInfo->getTMXFileName());
|
2010-08-27 18:07:37 +08:00
|
|
|
pTMXMapInfo->parseXMLFile(externalTilesetFilename.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCTMXTilesetInfo *tileset = new CCTMXTilesetInfo();
|
2010-09-02 18:16:02 +08:00
|
|
|
tileset->m_sName = valueForKey("name", attributeDict);
|
|
|
|
tileset->m_uFirstGid = (unsigned int)atoi(valueForKey("firstgid", attributeDict));
|
|
|
|
tileset->m_uSpacing = (unsigned int)atoi(valueForKey("spacing", attributeDict));
|
|
|
|
tileset->m_uMargin = (unsigned int)atoi(valueForKey("margin", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
CGSize s;
|
2010-09-02 18:16:02 +08:00
|
|
|
s.width = (float)atof(valueForKey("tilewidth", attributeDict));
|
|
|
|
s.height = (float)atof(valueForKey("tileheight", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
tileset->m_tTileSize = s;
|
|
|
|
|
|
|
|
pTMXMapInfo->getTilesets()->addObject(tileset);
|
|
|
|
tileset->release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(elementName == "tile")
|
|
|
|
{
|
|
|
|
CCTMXTilesetInfo* info = pTMXMapInfo->getTilesets()->getLastObject();
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary *dict = new CCXStringToStringDictionary();
|
2010-09-02 18:16:02 +08:00
|
|
|
pTMXMapInfo->setParentGID(info->m_uFirstGid + atoi(valueForKey("id", attributeDict)));
|
2010-09-06 20:26:19 +08:00
|
|
|
pTMXMapInfo->getTileProperties()->setObject(dict, pTMXMapInfo->getParentGID());
|
2010-09-08 14:52:56 +08:00
|
|
|
CCX_SAFE_RELEASE(dict);
|
2010-09-06 20:26:19 +08:00
|
|
|
|
2010-08-27 18:07:37 +08:00
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyTile);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "layer")
|
|
|
|
{
|
|
|
|
CCTMXLayerInfo *layer = new CCTMXLayerInfo();
|
2010-09-02 18:16:02 +08:00
|
|
|
layer->m_sName = valueForKey("name", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
CGSize s;
|
2010-09-02 18:16:02 +08:00
|
|
|
s.width = (float)atof(valueForKey("width", attributeDict));
|
|
|
|
s.height = (float)atof(valueForKey("height", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
layer->m_tLayerSize = s;
|
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string visible = valueForKey("visible", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
layer->m_bVisible = !(visible == "0");
|
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string opacity = valueForKey("opacity", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
if( opacity != "" )
|
|
|
|
{
|
|
|
|
layer->m_cOpacity = (unsigned char)(255 * atof(opacity.c_str()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
layer->m_cOpacity = 255;
|
|
|
|
}
|
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
float x = (float)atof(valueForKey("x", attributeDict));
|
|
|
|
float y = (float)atof(valueForKey("y", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
layer->m_tOffset = ccp(x,y);
|
|
|
|
|
|
|
|
pTMXMapInfo->getLayers()->addObject(layer);
|
|
|
|
layer->release();
|
|
|
|
|
|
|
|
// The parent element is now "layer"
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyLayer);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "objectgroup")
|
|
|
|
{
|
2010-08-30 11:45:46 +08:00
|
|
|
CCTMXObjectGroup *objectGroup = new CCTMXObjectGroup();
|
2010-09-02 18:16:02 +08:00
|
|
|
objectGroup->setGroupName(valueForKey("name", attributeDict));
|
2010-08-27 18:07:37 +08:00
|
|
|
CGPoint positionOffset;
|
2010-09-02 18:16:02 +08:00
|
|
|
positionOffset.x = (float)atof(valueForKey("x", attributeDict)) * pTMXMapInfo->getTileSize().width;
|
|
|
|
positionOffset.y = (float)atof(valueForKey("y", attributeDict)) * pTMXMapInfo->getTileSize().height;
|
2010-08-30 11:45:46 +08:00
|
|
|
objectGroup->setPositionOffset(positionOffset);
|
2010-08-27 18:07:37 +08:00
|
|
|
|
2010-08-30 11:45:46 +08:00
|
|
|
pTMXMapInfo->getObjectGroups()->addObject(objectGroup);
|
|
|
|
objectGroup->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// The parent element is now "objectgroup"
|
2010-08-30 11:45:46 +08:00
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyObjectGroup);
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "image")
|
|
|
|
{
|
|
|
|
CCTMXTilesetInfo *tileset = pTMXMapInfo->getTilesets()->getLastObject();
|
|
|
|
|
|
|
|
// build full path
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string imagename = valueForKey("source", attributeDict);
|
2010-09-07 18:04:57 +08:00
|
|
|
tileset->m_sSourceImage = CCFileUtils::fullPathFromRelativeFile(imagename.c_str(), pTMXMapInfo->getTMXFileName());
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "data")
|
|
|
|
{
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string encoding = valueForKey("encoding", attributeDict);
|
|
|
|
std::string compression = valueForKey("compression", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
if( encoding == "base64" )
|
|
|
|
{
|
|
|
|
int layerAttribs = pTMXMapInfo->getLayerAttribs();
|
|
|
|
pTMXMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribBase64);
|
|
|
|
pTMXMapInfo->setStoringCharacters(true);
|
|
|
|
|
|
|
|
if( compression == "gzip" )
|
|
|
|
{
|
|
|
|
layerAttribs = pTMXMapInfo->getLayerAttribs();
|
|
|
|
pTMXMapInfo->setLayerAttribs(layerAttribs | TMXLayerAttribGzip);
|
|
|
|
}
|
2010-09-01 17:26:16 +08:00
|
|
|
NSAssert( compression == "" || compression == "gzip", "TMX: unsupported compression method" );
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
NSAssert( pTMXMapInfo->getLayerAttribs() != TMXLayerAttribNone, "TMX tile map: Only base64 and/or gzip maps are supported" );
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "object")
|
|
|
|
{
|
2010-08-30 15:23:07 +08:00
|
|
|
char buffer[32];
|
2010-08-30 11:45:46 +08:00
|
|
|
CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// The value for "type" was blank or not a valid class name
|
|
|
|
// Create an instance of TMXObjectInfo to store the object and its properties
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary *dict = new CCXStringToStringDictionary();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// Set the name of the object to the value for "name"
|
2010-08-30 11:45:46 +08:00
|
|
|
std::string key = "name";
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *value = new NSString(valueForKey("name", attributeDict));
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// Assign all the attributes as key/name pairs in the properties dictionary
|
2010-08-30 11:45:46 +08:00
|
|
|
key = "type";
|
2010-09-06 20:26:19 +08:00
|
|
|
value = new NSString(valueForKey("type", attributeDict));
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-30 11:45:46 +08:00
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
int x = atoi(valueForKey("x", attributeDict)) + (int)objectGroup->getPositionOffset().x;
|
2010-08-30 11:45:46 +08:00
|
|
|
key = "x";
|
2010-09-03 14:40:48 +08:00
|
|
|
sprintf(buffer, "%d", x);
|
2010-09-06 20:26:19 +08:00
|
|
|
value = new NSString(buffer);
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-30 11:45:46 +08:00
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
int y = atoi(valueForKey("y", attributeDict)) + (int)objectGroup->getPositionOffset().y;
|
2010-08-27 18:07:37 +08:00
|
|
|
// Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
|
2010-09-02 18:16:02 +08:00
|
|
|
y = (int)(pTMXMapInfo->getMapSize().height * pTMXMapInfo->getTileSize().height) - y - atoi(valueForKey("height", attributeDict));
|
2010-08-30 11:45:46 +08:00
|
|
|
key = "y";
|
2010-09-03 14:40:48 +08:00
|
|
|
sprintf(buffer, "%d", y);
|
2010-09-06 20:26:19 +08:00
|
|
|
value = new NSString(buffer);
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-30 11:45:46 +08:00
|
|
|
|
|
|
|
key = "width";
|
2010-09-06 20:26:19 +08:00
|
|
|
value = new NSString(valueForKey("width", attributeDict));
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-30 11:45:46 +08:00
|
|
|
|
|
|
|
key = "height";
|
2010-09-06 20:26:19 +08:00
|
|
|
value = new NSString(valueForKey("height", attributeDict));
|
|
|
|
dict->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// Add the object to the objectGroup
|
2010-09-06 20:26:19 +08:00
|
|
|
objectGroup->getObjects()->addObject(dict);
|
|
|
|
dict->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
// The parent element is now "object"
|
2010-08-30 11:45:46 +08:00
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyObject);
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if(elementName == "property")
|
|
|
|
{
|
|
|
|
if ( pTMXMapInfo->getParentElement() == TMXPropertyNone )
|
|
|
|
{
|
|
|
|
CCLOG( "TMX tile map: Parent element is unsupported. Cannot add property named '%s' with value '%s'",
|
2010-09-02 18:16:02 +08:00
|
|
|
valueForKey("name", attributeDict), valueForKey("value",attributeDict) );
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
else if ( pTMXMapInfo->getParentElement() == TMXPropertyMap )
|
|
|
|
{
|
|
|
|
// The parent element is the map
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *value = new NSString(valueForKey("value", attributeDict));
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string key = valueForKey("name", attributeDict);
|
2010-09-06 20:26:19 +08:00
|
|
|
pTMXMapInfo->getProperties()->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if ( pTMXMapInfo->getParentElement() == TMXPropertyLayer )
|
|
|
|
{
|
|
|
|
// The parent element is the last layer
|
|
|
|
CCTMXLayerInfo *layer = pTMXMapInfo->getLayers()->getLastObject();
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *value = new NSString(valueForKey("value", attributeDict));
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string key = valueForKey("name", attributeDict);
|
2010-08-27 18:07:37 +08:00
|
|
|
// Add the property to the layer
|
2010-09-07 11:26:28 +08:00
|
|
|
layer->getProperties()->setObject(value, key);
|
2010-09-06 20:26:19 +08:00
|
|
|
value->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if ( pTMXMapInfo->getParentElement() == TMXPropertyObjectGroup )
|
|
|
|
{
|
|
|
|
// The parent element is the last object group
|
2010-08-30 11:45:46 +08:00
|
|
|
CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *value = new NSString(valueForKey("value", attributeDict));
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string key = valueForKey("name", attributeDict);
|
2010-09-06 20:26:19 +08:00
|
|
|
objectGroup->getProperties()->setObject(value, key);
|
|
|
|
value->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else if ( pTMXMapInfo->getParentElement() == TMXPropertyObject )
|
|
|
|
{
|
|
|
|
// The parent element is the last object
|
2010-08-30 11:45:46 +08:00
|
|
|
CCTMXObjectGroup *objectGroup = pTMXMapInfo->getObjectGroups()->getLastObject();
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary *dict = objectGroup->getObjects()->getLastObject();
|
2010-08-27 18:07:37 +08:00
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string propertyName = valueForKey("name", attributeDict);
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *propertyValue = new NSString(valueForKey("value", attributeDict));
|
|
|
|
dict->setObject(propertyValue, propertyName);
|
|
|
|
propertyValue->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
else if ( pTMXMapInfo->getParentElement() == TMXPropertyTile )
|
|
|
|
{
|
2010-09-07 11:26:28 +08:00
|
|
|
CCXStringToStringDictionary *dict;
|
2010-09-06 20:26:19 +08:00
|
|
|
dict = pTMXMapInfo->getTileProperties()->objectForKey(pTMXMapInfo->getParentGID());
|
|
|
|
|
2010-09-02 18:16:02 +08:00
|
|
|
std::string propertyName = valueForKey("name", attributeDict);
|
2010-09-06 20:26:19 +08:00
|
|
|
NSString *propertyValue = new NSString(valueForKey("value", attributeDict));
|
|
|
|
dict->setObject(propertyValue, propertyName);
|
|
|
|
propertyValue->release();
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
}
|
2010-09-02 18:16:02 +08:00
|
|
|
if (attributeDict)
|
|
|
|
{
|
|
|
|
attributeDict->clear();
|
|
|
|
delete attributeDict;
|
|
|
|
}
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
|
2010-08-27 18:14:17 +08:00
|
|
|
void tmx_endElement(void *ctx, const xmlChar *name)
|
2010-08-27 18:07:37 +08:00
|
|
|
{
|
|
|
|
CCTMXMapInfo *pTMXMapInfo = (CCTMXMapInfo*)(ctx);
|
|
|
|
std::string elementName = (char*)name;
|
|
|
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
if(elementName == "data" && pTMXMapInfo->getLayerAttribs()&TMXLayerAttribBase64)
|
|
|
|
{
|
|
|
|
pTMXMapInfo->setStoringCharacters(false);
|
|
|
|
|
|
|
|
CCTMXLayerInfo *layer = pTMXMapInfo->getLayers()->getLastObject();
|
|
|
|
|
|
|
|
std::string currentString = pTMXMapInfo->getCurrentString();
|
|
|
|
unsigned char *buffer;
|
|
|
|
len = base64Decode((unsigned char*)currentString.c_str(), currentString.length(), &buffer);
|
|
|
|
if( ! buffer )
|
|
|
|
{
|
|
|
|
CCLOG("cocos2d: TiledMap: decode data error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pTMXMapInfo->getLayerAttribs() & TMXLayerAttribGzip )
|
|
|
|
{
|
|
|
|
unsigned char *deflated;
|
|
|
|
ZipUtils::inflateMemory(buffer, len, &deflated);
|
2010-09-02 15:31:37 +08:00
|
|
|
delete [] buffer;
|
|
|
|
buffer = NULL;
|
2010-08-27 18:07:37 +08:00
|
|
|
|
|
|
|
if( ! deflated )
|
|
|
|
{
|
|
|
|
CCLOG("cocos2d: TiledMap: inflate data error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->m_pTiles = (unsigned int*) deflated;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
layer->m_pTiles = (unsigned int*) buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
pTMXMapInfo->setCurrentString("");
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (elementName == "map")
|
|
|
|
{
|
|
|
|
// The map element has ended
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyNone);
|
|
|
|
}
|
|
|
|
else if (elementName == "layer")
|
|
|
|
{
|
|
|
|
// The layer element has ended
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyNone);
|
|
|
|
}
|
|
|
|
else if (elementName == "objectgroup")
|
|
|
|
{
|
|
|
|
// The objectgroup element has ended
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyNone);
|
|
|
|
}
|
|
|
|
else if (elementName == "object")
|
|
|
|
{
|
|
|
|
// The object element has ended
|
|
|
|
pTMXMapInfo->setParentElement(TMXPropertyNone);
|
|
|
|
}
|
|
|
|
}
|
2010-08-27 18:14:17 +08:00
|
|
|
void tmx_characters(void *ctx, const xmlChar *ch, int len)
|
2010-08-27 18:07:37 +08:00
|
|
|
{
|
|
|
|
CCTMXMapInfo *pTMXMapInfo = (CCTMXMapInfo*)(ctx);
|
|
|
|
std::string pText((char*)ch,0,len);
|
|
|
|
|
|
|
|
if (pTMXMapInfo->getStoringCharacters())
|
|
|
|
{
|
|
|
|
std::string currentString = pTMXMapInfo->getCurrentString();
|
|
|
|
currentString += pText;
|
2010-09-06 11:59:28 +08:00
|
|
|
pTMXMapInfo->setCurrentString(currentString.c_str());
|
2010-08-27 18:07:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}//namespace cocos2d
|