1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * @constant
 29  * @type Number
 30  */
 31 cc.TMX_LAYER_ATTRIB_NONE = 1 << 0;
 32 /**
 33  * @constant
 34  * @type Number
 35  */
 36 cc.TMX_LAYER_ATTRIB_BASE64 = 1 << 1;
 37 /**
 38  * @constant
 39  * @type Number
 40  */
 41 cc.TMX_LAYER_ATTRIB_GZIP = 1 << 2;
 42 /**
 43  * @constant
 44  * @type Number
 45  */
 46 cc.TMX_LAYER_ATTRIB_ZLIB = 1 << 3;
 47 
 48 /**
 49  * @constant
 50  * @type Number
 51  */
 52 cc.TMX_PROPERTY_NONE = 0;
 53 
 54 /**
 55  * @constant
 56  * @type Number
 57  */
 58 cc.TMX_PROPERTY_MAP = 1;
 59 
 60 /**
 61  * @constant
 62  * @type Number
 63  */
 64 cc.TMX_PROPERTY_LAYER = 2;
 65 
 66 /**
 67  * @constant
 68  * @type Number
 69  */
 70 cc.TMX_PROPERTY_OBJECTGROUP = 3;
 71 
 72 /**
 73  * @constant
 74  * @type Number
 75  */
 76 cc.TMX_PROPERTY_OBJECT = 4;
 77 
 78 /**
 79  * @constant
 80  * @type Number
 81  */
 82 cc.TMX_PROPERTY_TILE = 5;
 83 
 84 /**
 85  * @constant
 86  * @type Number
 87  */
 88 cc.TMX_TILE_HORIZONTAL_FLAG = 0x80000000;
 89 
 90 
 91 /**
 92  * @constant
 93  * @type Number
 94  */
 95 cc.TMX_TILE_VERTICAL_FLAG = 0x40000000;
 96 
 97 /**
 98  * @constant
 99  * @type Number
100  */
101 cc.TMX_TILE_DIAGONAL_FLAG = 0x20000000;
102 
103 /**
104  * @constant
105  * @type Number
106  */
107 cc.TMX_TILE_FLIPPED_ALL = (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_DIAGONAL_FLAG) >>> 0;
108 
109 /**
110  * @constant
111  * @type Number
112  */
113 cc.TMX_TILE_FLIPPED_MASK = (~(cc.TMX_TILE_FLIPPED_ALL)) >>> 0;
114 
115 // Bits on the far end of the 32-bit global tile ID (GID's) are used for tile flags
116 
117 /**
118  * <p>cc.TMXLayerInfo contains the information about the layers like: <br />
119  * - Layer name<br />
120  * - Layer size <br />
121  * - Layer opacity at creation time (it can be modified at runtime)  <br />
122  * - Whether the layer is visible (if it's not visible, then the CocosNode won't be created) <br />
123  *  <br />
124  * This information is obtained from the TMX file.</p>
125  * @class
126  * @extends cc.Class
127  */
128 cc.TMXLayerInfo = cc.Class.extend(/** @lends cc.TMXLayerInfo# */{
129     _properties:null,
130     name:"",
131     _layerSize:null,
132     _tiles:null,
133     visible:null,
134     _opacity:null,
135     ownTiles:true,
136     _minGID:100000,
137     _maxGID:0,
138     offset:null,
139 
140     ctor:function () {
141         this._properties = [];
142         this.name = "";
143         this._layerSize = null;
144         this._tiles = [];
145         this.visible = true;
146         this._opacity = 0;
147         this.ownTiles = true;
148         this._minGID = 100000;
149         this._maxGID = 0;
150         this.offset = cc.PointZero();
151     },
152 
153     /**
154      * @return {Array}
155      */
156     getProperties:function () {
157         return this._properties;
158     },
159 
160     /**
161      * @param {object} Var
162      */
163     setProperties:function (Var) {
164         this._properties = Var;
165     }
166 });
167 
168 /**
169  * <p>cc.TMXTilesetInfo contains the information about the tilesets like: <br />
170  * - Tileset name<br />
171  * - Tileset spacing<br />
172  * - Tileset margin<br />
173  * - size of the tiles<br />
174  * - Image used for the tiles<br />
175  * - Image size<br />
176  *
177  * This information is obtained from the TMX file. </p>
178  * @class
179  * @extends cc.Class
180  */
181 cc.TMXTilesetInfo = cc.Class.extend(/** @lends cc.TMXTilesetInfo# */{
182 
183     /**
184      * Tileset name
185      */
186     name:"",
187 
188     /**
189      * First grid
190      */
191     firstGid:0,
192     _tileSize:null,
193 
194     /**
195      * Spacing
196      */
197     spacing:0,
198 
199     /**
200      *  Margin
201      */
202     margin:0,
203 
204     /**
205      * Filename containing the tiles (should be sprite sheet / texture atlas)
206      */
207     sourceImage:"",
208 
209     /**
210      * Size in pixels of the image
211      */
212     imageSize:null,
213 
214     ctor:function () {
215         this._tileSize = cc.SizeZero();
216         this.imageSize = cc.SizeZero();
217     },
218 
219     /**
220      * @param {Number} gid
221      * @return {cc.Rect}
222      */
223     rectForGID:function (gid) {
224         var rect = cc.RectZero();
225         rect.size = this._tileSize;
226         gid &= cc.TMX_TILE_FLIPPED_MASK;
227         gid = gid - parseInt(this.firstGid, 10);
228         var max_x = parseInt((this.imageSize.width - this.margin * 2 + this.spacing) / (this._tileSize.width + this.spacing), 10);
229         rect.origin.x = parseInt((gid % max_x) * (this._tileSize.width + this.spacing) + this.margin, 10);
230         rect.origin.y = parseInt(parseInt(gid / max_x, 10) * (this._tileSize.height + this.spacing) + this.margin, 10);
231         return rect;
232     }
233 });
234 
235 /**
236  * <p>cc.TMXMapInfo contains the information about the map like: <br/>
237  *- Map orientation (hexagonal, isometric or orthogonal)<br/>
238  *- Tile size<br/>
239  *- Map size</p>
240  *
241  * <p>And it also contains: <br/>
242  * - Layers (an array of TMXLayerInfo objects)<br/>
243  * - Tilesets (an array of TMXTilesetInfo objects) <br/>
244  * - ObjectGroups (an array of TMXObjectGroupInfo objects) </p>
245  *
246  * <p>This information is obtained from the TMX file. </p>
247  * @class
248  * @extends cc.SAXParser
249  */
250 cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
251     // map orientation
252     _orientation:null,
253     _mapSize:null,
254     _tileSize:null,
255     _layers:null,
256     _tileSets:null,
257     _objectGroups:null,
258     _parentElement:null,
259     _parentGID:null,
260     _layerAttribs:0,
261     _storingCharacters:false,
262     _properties:null,
263     // tmx filename
264     _TMXFileName:null,
265     //current string
266     _currentString:null,
267     // tile properties
268     _tileProperties:null,
269     _resources:"",
270     _currentFirstGID:0,
271 
272     ctor:function () {
273         this._tileSets = [];
274         this._tileProperties = [];
275         this._properties = [];
276         this._mapSize = cc.SizeZero();
277         this._tileSize = cc.SizeZero();
278         this._currentFirstGID = 0;
279     },
280     /**
281      * @return {Number}
282      */
283     getOrientation:function () {
284         return this._orientation;
285     },
286 
287     /**
288      * @param {Number} Var
289      */
290     setOrientation:function (Var) {
291         this._orientation = Var;
292     },
293 
294     /**
295      * Map width & height
296      * @return {cc.Size}
297      */
298     getMapSize:function () {
299         return this._mapSize;
300     },
301 
302     /**
303      * @param {cc.Size} Var
304      */
305     setMapSize:function (Var) {
306         this._mapSize = Var;
307     },
308 
309     /**
310      * Tiles width & height
311      * @return {cc.Size}
312      */
313     getTileSize:function () {
314         return this._tileSize;
315     },
316 
317     /**
318      * @param {cc.Size} Var
319      */
320     setTileSize:function (Var) {
321         this._tileSize = Var;
322     },
323 
324     /**
325      * Layers
326      * @return {Array}
327      */
328     getLayers:function () {
329         return this._layers;
330     },
331 
332     /**
333      * @param {cc.TMXLayerInfo} Var
334      */
335     setLayers:function (Var) {
336         this._layers.push(Var);
337     },
338 
339     /**
340      * tilesets
341      * @return {Array}
342      */
343     getTilesets:function () {
344         return this._tileSets;
345     },
346 
347     /**
348      * @param {cc.TMXTilesetInfo} Var
349      */
350     setTilesets:function (Var) {
351         this._tileSets.push(Var);
352     },
353 
354     /**
355      * ObjectGroups
356      * @return {Array}
357      */
358     getObjectGroups:function () {
359         return this._objectGroups;
360     },
361 
362     /**
363      * @param {cc.TMXObjectGroup} Var
364      */
365     setObjectGroups:function (Var) {
366         this._objectGroups.push(Var);
367     },
368 
369     /**
370      * parent element
371      * @return {Number}
372      */
373     getParentElement:function () {
374         return this._parentElement;
375     },
376 
377     /**
378      * @param {Number} Var
379      */
380     setParentElement:function (Var) {
381         this._parentElement = Var;
382     },
383 
384     /**
385      * parent GID
386      * @return {Number}
387      */
388     getParentGID:function () {
389         return this._parentGID;
390     },
391 
392     /**
393      * @param {Number} Var
394      */
395     setParentGID:function (Var) {
396         this._parentGID = Var;
397     },
398 
399     /**
400      *  layer attribute
401      * @return {Number}
402      */
403     getLayerAttribs:function () {
404         return this._layerAttribs;
405     },
406 
407     /**
408      * @param {Number} Var
409      */
410     setLayerAttribs:function (Var) {
411         this._layerAttribs = Var;
412     },
413 
414     /**
415      * is string characters?
416      * @return {Boolean}
417      */
418     getStoringCharacters:function () {
419         return this._storingCharacters;
420     },
421 
422     /**
423      * @param {Boolean} Var
424      */
425     setStoringCharacters:function (Var) {
426         this._storingCharacters = Var;
427     },
428 
429     /**
430      * Properties
431      * @return {Array}
432      */
433     getProperties:function () {
434         return this._properties;
435     },
436 
437     /**
438      * @param {object} Var
439      */
440     setProperties:function (Var) {
441         this._properties.push(Var);
442     },
443 
444     /**
445      * Initializes a TMX format with a  tmx file
446      * @param {String} tmxFile
447      * @param {String} resourcePath
448      * @return {Element}
449      */
450     initWithTMXFile:function (tmxFile, resourcePath) {
451         this._internalInit(tmxFile, resourcePath);
452         return this.parseXMLFile(this._TMXFileName);
453         //return this.parseXMLFile(cc.FileUtils.getInstance().fullPathForFilename(this._TMXFileName));
454     },
455 
456     /**
457      * initializes a TMX format with an XML string and a TMX resource path
458      * @param {String} tmxString
459      * @param {String} resourcePath
460      * @return {Boolean}
461      */
462     initWithXML:function (tmxString, resourcePath) {
463         this._internalInit(null, resourcePath);
464         return this.parseXMLString(tmxString);
465     },
466 
467     /** Initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file
468      * @param {String} tmxFile
469      * @param {boolean} [isXmlString=false]
470      * @return {Element}
471      */
472     parseXMLFile:function (tmxFile, isXmlString) {
473         isXmlString = isXmlString || false;
474         tmxFile = cc.FileUtils.getInstance().fullPathForFilename(tmxFile);
475         var mapXML = cc.SAXParser.getInstance().tmxParse(tmxFile, isXmlString);
476         var i, j;
477 
478         // PARSE <map>
479         var map = mapXML.documentElement;
480 
481         var version = map.getAttribute('version');
482         var orientationStr = map.getAttribute('orientation');
483 
484         if (map.nodeName == "map") {
485             if (version != "1.0" && version !== null)
486                 cc.log("cocos2d: TMXFormat: Unsupported TMX version:" + version);
487 
488             if (orientationStr == "orthogonal")
489                 this.setOrientation(cc.TMX_ORIENTATION_ORTHO);
490             else if (orientationStr == "isometric")
491                 this.setOrientation(cc.TMX_ORIENTATION_ISO);
492             else if (orientationStr == "hexagonal")
493                 this.setOrientation(cc.TMX_ORIENTATION_HEX);
494             else if (orientationStr !== null)
495                 cc.log("cocos2d: TMXFomat: Unsupported orientation:" + this.getOrientation());
496 
497             var mapSize = cc.size(0, 0);
498             mapSize.width = parseFloat(map.getAttribute('width'));
499             mapSize.height = parseFloat(map.getAttribute('height'));
500             this.setMapSize(mapSize);
501 
502             mapSize = cc.size(0, 0);
503             mapSize.width = parseFloat(map.getAttribute('tilewidth'));
504             mapSize.height = parseFloat(map.getAttribute('tileheight'));
505             this.setTileSize(mapSize);
506 
507             // The parent element is the map
508             var propertyArr = map.querySelectorAll("map > properties >  property");
509             if (propertyArr) {
510                 for (i = 0; i < propertyArr.length; i++) {
511                     var aProperty = {};
512                     aProperty[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value');
513                     this.setProperties(aProperty);
514                 }
515             }
516         }
517 
518         // PARSE <tileset>
519         var tilesets = map.getElementsByTagName('tileset');
520         if (map.nodeName !== "map") {
521             tilesets = [];
522             tilesets.push(map);
523         }
524 
525         for (i = 0; i < tilesets.length; i++) {
526             var selTileset = tilesets[i];
527             // If this is an external tileset then start parsing that
528             var externalTilesetFilename = selTileset.getAttribute('source');
529             if (externalTilesetFilename) {
530                 //this._currentFirstGID = parseInt(selTileset.getAttribute('firstgid'));
531                 this.parseXMLFile(cc.FileUtils.getInstance().fullPathFromRelativeFile(externalTilesetFilename, isXmlString ? this._resources + "/" : tmxFile));
532             } else {
533                 var tileset = new cc.TMXTilesetInfo();
534                 tileset.name = selTileset.getAttribute('name') || "";
535                 //TODO need fix
536                 //if(this._currentFirstGID === 0){
537                 tileset.firstGid = parseInt(selTileset.getAttribute('firstgid')) || 0;
538                 //}else{
539                 //    tileset.firstGid = this._currentFirstGID;
540                 //    this._currentFirstGID = 0;
541                 //}
542 
543                 tileset.spacing = parseInt(selTileset.getAttribute('spacing')) || 0;
544                 tileset.margin = parseInt(selTileset.getAttribute('margin')) || 0;
545 
546                 var tilesetSize = cc.size(0, 0);
547                 tilesetSize.width = parseFloat(selTileset.getAttribute('tilewidth'));
548                 tilesetSize.height = parseFloat(selTileset.getAttribute('tileheight'));
549                 tileset._tileSize = tilesetSize;
550 
551                 var image = selTileset.getElementsByTagName('image')[0];
552                 var imagename = image.getAttribute('source');
553                 var num = -1;
554                 if(this._TMXFileName)
555                     num  = this._TMXFileName.lastIndexOf("/");
556                 if (num !== -1) {
557                     var dir = this._TMXFileName.substr(0, num + 1);
558                     tileset.sourceImage = dir + imagename;
559                 } else {
560                     tileset.sourceImage = this._resources + (this._resources ? "/" : "") + imagename;
561                 }
562                 this.setTilesets(tileset);
563             }
564         }
565 
566         // PARSE  <tile>
567         var tiles = map.querySelectorAll('tile');
568         if (tiles) {
569             for (i = 0; i < tiles.length; i++) {
570                 var info = this._tileSets[0];
571                 var t = tiles[i];
572                 this.setParentGID(parseInt(info.firstGid) + parseInt(t.getAttribute('id') || 0));
573                 var tp = t.querySelectorAll("properties > property");
574                 if (tp) {
575                     var dict = {};
576                     for (j = 0; j < tp.length; j++) {
577                         var name = tp[j].getAttribute('name');
578                         var value = tp[j].getAttribute('value');
579                         dict[name] = value;
580                     }
581                     this._tileProperties[this.getParentGID()] = dict;
582                 }
583             }
584         }
585 
586         // PARSE  <layer>
587         var layers = map.getElementsByTagName('layer');
588         if (layers) {
589             for (i = 0; i < layers.length; i++) {
590                 var selLayer = layers[i];
591                 var data = selLayer.getElementsByTagName('data')[0];
592 
593                 var layer = new cc.TMXLayerInfo();
594                 layer.name = selLayer.getAttribute('name');
595 
596                 var layerSize = cc.size(0, 0);
597                 layerSize.width = parseFloat(selLayer.getAttribute('width'));
598                 layerSize.height = parseFloat(selLayer.getAttribute('height'));
599                 layer._layerSize = layerSize;
600 
601                 var visible = selLayer.getAttribute('visible');
602                 layer.visible = !(visible == "0");
603 
604                 var opacity = selLayer.getAttribute('opacity') || 1;
605 
606                 if (opacity)
607                     layer._opacity = parseInt(255 * parseFloat(opacity));
608                 else
609                     layer._opacity = 255;
610                 layer.offset = cc.p(parseFloat(selLayer.getAttribute('x')) || 0, parseFloat(selLayer.getAttribute('y')) || 0);
611 
612                 var nodeValue = '';
613                 for (j = 0; j < data.childNodes.length; j++) {
614                     nodeValue += data.childNodes[j].nodeValue
615                 }
616                 nodeValue = nodeValue.trim();
617 
618                 // Unpack the tilemap data
619                 var compression = data.getAttribute('compression');
620                 var encoding = data.getAttribute('encoding');
621                 cc.Assert(compression == null || compression === "gzip" || compression === "zlib", "TMX: unsupported compression method");
622                 switch (compression) {
623                     case 'gzip':
624                         layer._tiles = cc.unzipBase64AsArray(nodeValue, 4);
625                         break;
626                     case 'zlib':
627                         var inflator = new Zlib.Inflate(cc.Codec.Base64.decodeAsArray(nodeValue, 1));
628                         layer._tiles = cc.uint8ArrayToUint32Array(inflator.decompress());
629                         break;
630                     case null:
631                     case '':
632                         // Uncompressed
633                         if (encoding == "base64")
634                             layer._tiles = cc.Codec.Base64.decodeAsArray(nodeValue, 4);
635                         else if (encoding === "csv") {
636                             layer._tiles = [];
637                             var csvTiles = nodeValue.split(',');
638                             for (var csvIdx = 0; csvIdx < csvTiles.length; csvIdx++)
639                                 layer._tiles.push(parseInt(csvTiles[csvIdx]));
640                         } else {
641                             //XML format
642                             var selDataTiles = data.getElementsByTagName("tile");
643                             layer._tiles = [];
644                             for (var xmlIdx = 0; xmlIdx < selDataTiles.length; xmlIdx++)
645                                 layer._tiles.push(parseInt(selDataTiles[xmlIdx].getAttribute("gid")));
646                         }
647                         break;
648                     default:
649                         cc.Assert(this.getLayerAttribs() != cc.TMX_LAYER_ATTRIB_NONE, "TMX tile map: Only base64 and/or gzip/zlib maps are supported");
650                 }
651 
652                 // The parent element is the last layer
653                 var layerProps = selLayer.querySelectorAll("properties > property");
654                 if (layerProps) {
655                     var layerProp = {};
656                     for (j = 0; j < layerProps.length; j++) {
657                         layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value');
658                     }
659                     layer.setProperties(layerProp);
660                 }
661                 this.setLayers(layer);
662             }
663         }
664 
665         // PARSE <objectgroup>
666         var objectGroups = map.getElementsByTagName('objectgroup');
667         if (objectGroups) {
668             for (i = 0; i < objectGroups.length; i++) {
669                 var selGroup = objectGroups[i];
670                 var objectGroup = new cc.TMXObjectGroup();
671                 objectGroup.setGroupName(selGroup.getAttribute('name'));
672                 objectGroup.setPositionOffset(cc.p(parseFloat(selGroup.getAttribute('x')) * this.getTileSize().width || 0,
673                     parseFloat(selGroup.getAttribute('y')) * this.getTileSize().height || 0));
674 
675                 var groupProps = selGroup.querySelectorAll("objectgroup > properties > property");
676                 if (groupProps) {
677                     for (j = 0; j < groupProps.length; j++) {
678                         var groupProp = {};
679                         groupProp[groupProps[j].getAttribute('name')] = groupProps[j].getAttribute('value');
680                         // Add the property to the layer
681                         objectGroup.setProperties(groupProp);
682                     }
683                 }
684 
685                 var objects = selGroup.querySelectorAll('object');
686                 if (objects) {
687                     for (j = 0; j < objects.length; j++) {
688                         var selObj = objects[j];
689                         // The value for "type" was blank or not a valid class name
690                         // Create an instance of TMXObjectInfo to store the object and its properties
691                         var objectProp = {};
692 
693                         // Set the name of the object to the value for "name"
694                         objectProp["name"] = selObj.getAttribute('name') || "";
695 
696                         // Assign all the attributes as key/name pairs in the properties dictionary
697                         objectProp["type"] = selObj.getAttribute('type') || "";
698 
699                         objectProp["x"] = parseInt(selObj.getAttribute('x') || 0) + objectGroup.getPositionOffset().x;
700                         var y = parseInt(selObj.getAttribute('y') || 0) + objectGroup.getPositionOffset().y;
701 
702                         objectProp["width"] = parseInt(selObj.getAttribute('width')) || 0;
703                         objectProp["height"] = parseInt(selObj.getAttribute('height')) || 0;
704 
705                         // Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
706                         objectProp["y"] = parseInt(this.getMapSize().height * this.getTileSize().height) - y - objectProp["height"];
707 
708                         var docObjProps = selObj.querySelectorAll("properties > property");
709                         if (docObjProps) {
710                             for (var k = 0; k < docObjProps.length; k++)
711                                 objectProp[docObjProps[k].getAttribute('name')] = docObjProps[k].getAttribute('value');
712                         }
713 
714                         //polygon
715                         var polygonProps = selObj.querySelectorAll("polygon");
716                         if(polygonProps && polygonProps.length > 0) {
717                             var selPgPointStr = polygonProps[0].getAttribute('points');
718                             if(selPgPointStr)
719                                 objectProp["polygonPoints"] = this._parsePointsString(selPgPointStr);
720                         }
721 
722                         //polyline
723                         var polylineProps = selObj.querySelectorAll("polyline");
724                         if(polylineProps && polylineProps.length > 0) {
725                             var selPlPointStr = polylineProps[0].getAttribute('points');
726                             if(selPlPointStr)
727                                 objectProp["polylinePoints"] = this._parsePointsString(selPlPointStr);
728                         }
729 
730                         // Add the object to the objectGroup
731                         objectGroup.setObjects(objectProp);
732                     }
733                 }
734 
735                 this.setObjectGroups(objectGroup);
736             }
737         }
738         return map;
739     },
740 
741     _parsePointsString:function(pointsString){
742          if(!pointsString)
743             return null;
744 
745         var points = [];
746         var pointsStr = pointsString.split(' ');
747         for(var i = 0; i < pointsStr.length; i++){
748             var selPointStr = pointsStr[i].split(',');
749             points.push({'x':selPointStr[0], 'y':selPointStr[1]});
750         }
751         return points;
752     },
753 
754     /**
755      * initializes parsing of an XML string, either a tmx (Map) string or tsx (Tileset) string
756      * @param {String} xmlString
757      * @return {Boolean}
758      */
759     parseXMLString:function (xmlString) {
760         return this.parseXMLFile(xmlString, true);
761     },
762 
763     /**
764      * @return {object}
765      */
766     getTileProperties:function () {
767         return this._tileProperties;
768     },
769 
770     /**
771      * @param {object} tileProperties
772      */
773     setTileProperties:function (tileProperties) {
774         this._tileProperties.push(tileProperties);
775     },
776 
777     /**
778      * @return {String}
779      */
780     getCurrentString:function () {
781         return this._currentString;
782     },
783 
784     /**
785      * @param {String} currentString
786      */
787     setCurrentString:function (currentString) {
788         this._currentString = currentString;
789     },
790 
791     /**
792      * @return {String}
793      */
794     getTMXFileName:function () {
795         return this._TMXFileName;
796     },
797 
798     /**
799      * @param {String} fileName
800      */
801     setTMXFileName:function (fileName) {
802         this._TMXFileName = fileName;
803     },
804 
805     _internalInit:function (tmxFileName, resourcePath) {
806         this._tileSets = [];
807         this._layers = [];
808 
809         //this._TMXFileName = cc.FileUtils.getInstance().fullPathForFilename(tmxFileName);
810         this._TMXFileName = tmxFileName;
811 
812         if (resourcePath) {
813             this._resources = resourcePath;
814         }
815 
816         this._objectGroups = [];
817 
818         this._properties = [];
819         this._tileProperties = [];
820 
821         // tmp vars
822         this._currentString = "";
823         this._storingCharacters = false;
824         this._layerAttribs = cc.TMX_LAYER_ATTRIB_NONE;
825         this._parentElement = cc.TMX_PROPERTY_NONE;
826         this._currentFirstGID = 0;
827     }
828 });
829 
830 /**
831  * Creates a TMX Format with a tmx file
832  * @param {String} tmxFile
833  * @param {String} resourcePath
834  * @return {cc.TMXMapInfo}
835  */
836 cc.TMXMapInfo.create = function (tmxFile, resourcePath) {
837     var ret = new cc.TMXMapInfo();
838     if (ret.initWithTMXFile(tmxFile, resourcePath))
839         return ret;
840     return null;
841 };
842 
843 /**
844  * creates a TMX Format with an XML string and a TMX resource path
845  * @param {String} tmxString
846  * @param {String} resourcePath
847  * @return {cc.TMXMapInfo}
848  */
849 cc.TMXMapInfo.createWithXML = function (tmxString, resourcePath) {
850     var ret = new cc.TMXMapInfo();
851     if (ret.initWithXML(tmxString, resourcePath))
852         return ret;
853     return null;
854 };
855