1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * @ignore
 28  */
 29 ccs.CONST_VERSION = "version";
 30 ccs.CONST_VERSION_2_0 = 2.0;
 31 ccs.CONST_VERSION_COMBINED = 0.3;
 32 
 33 ccs.CONST_ARMATURES = "armatures";
 34 ccs.CONST_ARMATURE = "armature";
 35 ccs.CONST_BONE = "b";
 36 ccs.CONST_DISPLAY = "d";
 37 
 38 ccs.CONST_ANIMATIONS = "animations";
 39 ccs.CONST_ANIMATION = "animation";
 40 ccs.CONST_MOVEMENT = "mov";
 41 ccs.CONST_FRAME = "f";
 42 
 43 ccs.CONST_TEXTURE_ATLAS = "TextureAtlas";
 44 ccs.CONST_SUB_TEXTURE = "SubTexture";
 45 
 46 ccs.CONST_SKELETON = "skeleton";
 47 
 48 ccs.CONST_A_NAME = "name";
 49 ccs.CONST_A_DURATION = "dr";
 50 ccs.CONST_A_FRAME_INDEX = "fi";
 51 ccs.CONST_A_DURATION_TO = "to";
 52 ccs.CONST_A_DURATION_TWEEN = "drTW";
 53 ccs.CONST_A_LOOP = "lp";
 54 ccs.CONST_A_MOVEMENT_SCALE = "sc";
 55 ccs.CONST_A_MOVEMENT_DELAY = "dl";
 56 ccs.CONST_A_DISPLAY_INDEX = "dI";
 57 
 58 ccs.CONST_A_PLIST = "plist";
 59 
 60 ccs.CONST_A_PARENT = "parent";
 61 ccs.CONST_A_SKEW_X = "kX";
 62 ccs.CONST_A_SKEW_Y = "kY";
 63 ccs.CONST_A_SCALE_X = "cX";
 64 ccs.CONST_A_SCALE_Y = "cY";
 65 ccs.CONST_A_Z = "z";
 66 ccs.CONST_A_EVENT = "evt";
 67 ccs.CONST_A_SOUND = "sd";
 68 ccs.CONST_A_SOUND_EFFECT = "sdE";
 69 ccs.CONST_A_TWEEN_EASING = "twE";
 70 ccs.CONST_A_EASING_PARAM = "twEP";
 71 ccs.CONST_A_TWEEN_ROTATE = "twR";
 72 ccs.CONST_A_IS_ARMATURE = "isArmature";
 73 ccs.CONST_A_DISPLAY_TYPE = "displayType";
 74 ccs.CONST_A_MOVEMENT = "mov";
 75 
 76 ccs.CONST_A_X = "x";
 77 ccs.CONST_A_Y = "y";
 78 
 79 ccs.CONST_A_COCOS2DX_X = "cocos2d_x";
 80 ccs.CONST_A_COCOS2DX_Y = "cocos2d_y";
 81 
 82 ccs.CONST_A_WIDTH = "width";
 83 ccs.CONST_A_HEIGHT = "height";
 84 ccs.CONST_A_PIVOT_X = "pX";
 85 ccs.CONST_A_PIVOT_Y = "pY";
 86 
 87 ccs.CONST_A_COCOS2D_PIVOT_X = "cocos2d_pX";
 88 ccs.CONST_A_COCOS2D_PIVOT_Y = "cocos2d_pY";
 89 
 90 ccs.CONST_A_BLEND_TYPE = "bd";
 91 ccs.CONST_A_BLEND_SRC = "bd_src";
 92 ccs.CONST_A_BLEND_DST = "bd_dst";
 93 
 94 ccs.CONST_A_ALPHA = "a";
 95 ccs.CONST_A_RED = "r";
 96 ccs.CONST_A_GREEN = "g";
 97 ccs.CONST_A_BLUE = "b";
 98 ccs.CONST_A_ALPHA_OFFSET = "aM";
 99 ccs.CONST_A_RED_OFFSET = "rM";
100 ccs.CONST_A_GREEN_OFFSET = "gM";
101 ccs.CONST_A_BLUE_OFFSET = "bM";
102 ccs.CONST_A_COLOR_TRANSFORM = "colorTransform";
103 ccs.CONST_A_TWEEN_FRAME = "tweenFrame";
104 
105 ccs.CONST_CONTOUR = "con";
106 ccs.CONST_CONTOUR_VERTEX = "con_vt";
107 
108 ccs.CONST_FL_NAN = "NaN";
109 
110 ccs.CONST_FRAME_DATA = "frame_data";
111 ccs.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
112 ccs.CONST_MOVEMENT_DATA = "mov_data";
113 ccs.CONST_ANIMATION_DATA = "animation_data";
114 ccs.CONST_DISPLAY_DATA = "display_data";
115 ccs.CONST_SKIN_DATA = "skin_data";
116 ccs.CONST_BONE_DATA = "bone_data";
117 ccs.CONST_ARMATURE_DATA = "armature_data";
118 ccs.CONST_CONTOUR_DATA = "contour_data";
119 ccs.CONST_TEXTURE_DATA = "texture_data";
120 ccs.CONST_VERTEX_POINT = "vertex";
121 ccs.CONST_COLOR_INFO = "color";
122 
123 ccs.CONST_CONFIG_FILE_PATH = "config_file_path";
124 ccs.CONST_CONTENT_SCALE = "content_scale";
125 
126 /**
127  * @ignore
128  * @constructor
129  */
130 ccs.DataInfo = function () {
131     this.asyncStruct = null;
132     this.configFileQueue = [];
133     this.contentScale = 1;
134     this.filename = "";
135     this.baseFilePath = "";
136     this.flashToolVersion = 0;
137     this.cocoStudioVersion = 0
138 };
139 
140 /**
141  * ccs.dataReaderHelper is a singleton object for reading CocoStudio data
142  * @class
143  * @name ccs.dataReaderHelper
144  */
145 ccs.dataReaderHelper = /** @lends ccs.dataReaderHelper# */{
146     ConfigType: {
147         DragonBone_XML: 0,
148         CocoStudio_JSON: 1,
149         CocoStudio_Binary: 2
150     },
151 
152     _configFileList: [],
153     _flashToolVersion: ccs.CONST_VERSION_2_0,
154 //    _cocoStudioVersion: ccs.CONST_VERSION_COMBINED,
155     _positionReadScale: 1,
156     _asyncRefCount: 0,
157     _asyncRefTotalCount: 0,
158 
159     _dataQueue: null,
160 
161     //LoadData don't need
162 
163     setPositionReadScale: function (scale) {
164         this._positionReadScale = scale;
165     },
166 
167     getPositionReadScale: function () {
168         return this._positionReadScale;
169     },
170 
171     /**
172      * Add armature data from file.
173      * @param {String} filePath
174      */
175     addDataFromFile: function (filePath) {
176         /*
177          * Check if file is already added to ArmatureDataManager, if then return.
178          */
179         if (this._configFileList.indexOf(filePath) != -1)
180             return;
181         this._configFileList.push(filePath);
182 
183         //! find the base file path
184         var basefilePath = this._initBaseFilePath(filePath);
185 
186         // Read content from file
187         // Here the reader into the next process
188 
189         var str = cc.path.extname(filePath).toLowerCase();
190 
191         var dataInfo = new ccs.DataInfo();
192         dataInfo.filename = filePath;
193         dataInfo.basefilePath = basefilePath;
194         if (str == ".xml")
195             ccs.dataReaderHelper.addDataFromXML(filePath, dataInfo);
196         else if (str == ".json" || str == ".exportjson")
197             ccs.dataReaderHelper.addDataFromJson(filePath, dataInfo);
198         else if(str == ".csb")
199             ccs.dataReaderHelper.addDataFromBinaryCache(filePath, dataInfo);
200     },
201 
202     /**
203      * Adds data from file with Async.
204      * @param {String} imagePath
205      * @param {String} plistPath
206      * @param {String} filePath
207      * @param {function} selector
208      * @param {Object} [target]
209      */
210     addDataFromFileAsync: function (imagePath, plistPath, filePath, selector, target) {
211         /*
212          * Check if file is already added to ArmatureDataManager, if then return.
213          */
214         if (this._configFileList.indexOf(filePath) != -1) {
215             if (target && selector) {
216                 if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0)
217                     this._asyncCallBack(selector,target, 1);
218                 else
219                     this._asyncCallBack(selector, target, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
220             }
221             return;
222         }
223 //        this._configFileList.push(filePath);
224 
225         //! find the base file path
226 //        var basefilePath = this._initBaseFilePath(filePath);
227 
228         this._asyncRefTotalCount++;
229         this._asyncRefCount++;
230         var self = this;
231         var fun = function () {
232             self.addDataFromFile(filePath);
233             self._asyncRefCount--;
234             self._asyncCallBack(selector,target, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
235         };
236         cc.director.getScheduler().scheduleCallbackForTarget(this, fun, 0.1, false);
237     },
238 
239     /**
240      * Removes config file from config file list.
241      * @param {String} configFile
242      */
243     removeConfigFile: function (configFile) {
244 //        cc.arrayRemoveObject(this._configFileList, configFile);
245         var locFileList = this._configFileList;
246         var len = locFileList.length;
247         var it = locFileList[len];
248         for (var i = 0;i<len; i++){
249             if (locFileList[i] == configFile)
250                 it = i;
251         }
252 
253         if (it != locFileList[len])
254             cc.arrayRemoveObject(locFileList, configFile);
255     },
256 
257     /**
258      * Translate XML export from Dragon Bone flash tool to data, and save them. When you add a new xml, the data already saved will be keeped.
259      * @param {Object} skeleton
260      * @param {ccs.DataInfo} dataInfo
261      */
262     addDataFromCache: function (skeleton, dataInfo) {
263         if (!skeleton) {
264             cc.log("XML error  or  XML is empty.");
265             return;
266         }
267         dataInfo.flashToolVersion = parseFloat(skeleton.getAttribute(ccs.CONST_VERSION));
268 
269         /*
270          * Begin decode armature data from xml
271          */
272         var armaturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ARMATURES + " >  " + ccs.CONST_ARMATURE + "");
273         var armatureDataManager = ccs.armatureDataManager, i;
274         for (i = 0; i < armaturesXML.length; i++) {
275             var armatureData = this.decodeArmature(armaturesXML[i], dataInfo);
276             armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
277         }
278 
279         /*
280          * Begin decode animation data from xml
281          */
282         var animationsXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ANIMATIONS + " >  " + ccs.CONST_ANIMATION + "");
283         for (i = 0; i < animationsXML.length; i++) {
284             var animationData = this.decodeAnimation(animationsXML[i], dataInfo);
285             armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
286         }
287 
288         var texturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_TEXTURE_ATLAS + " >  " + ccs.CONST_SUB_TEXTURE + "");
289         for (i = 0; i < texturesXML.length; i++) {
290             var textureData = this.decodeTexture(texturesXML[i], dataInfo);
291             armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
292         }
293     },
294 
295     /**
296      * decode xml armature data.
297      * @param {XMLDocument} armatureXML
298      * @param {ccs.DataInfo} dataInfo
299      * @returns {ccs.ArmatureData}
300      */
301     decodeArmature: function (armatureXML, dataInfo) {
302         var armatureData = new ccs.ArmatureData();
303         armatureData.init();
304         armatureData.name = armatureXML.getAttribute(ccs.CONST_A_NAME);
305 
306         var bonesXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE + " > " + ccs.CONST_BONE);
307 
308         for (var i = 0; i < bonesXML.length; i++) {
309             /*
310              *  If this bone have parent, then get the parent bone xml
311              */
312             var boneXML = bonesXML[i];
313             var parentName = boneXML.getAttribute(ccs.CONST_A_PARENT);
314             var parentXML = null;
315             if (parentName) {
316                 //parentXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE+" > "+ccs.CONST_BONE);
317                 for (var j = 0; j < bonesXML.length; j++) {
318                     parentXML = bonesXML[j];
319                     if (parentName == bonesXML[j].getAttribute(ccs.CONST_A_NAME)) {
320                         //todo
321                         break;
322                     }
323                 }
324             }
325             var boneData = this.decodeBone(boneXML, parentXML, dataInfo);
326             armatureData.addBoneData(boneData);
327         }
328         return armatureData;
329     },
330 
331     /**
332      * decode json armature data.
333      * @param {Object} json
334      * @param {ccs.DataInfo} dataInfo
335      * @returns {ccs.ArmatureData}
336      */
337     decodeArmatureFromJSON: function (json, dataInfo) {
338         var armatureData = new ccs.ArmatureData();
339         armatureData.init();
340 
341         var name = json[ccs.CONST_A_NAME];
342         if (name) {
343             armatureData.name = name;
344         }
345 
346         dataInfo.cocoStudioVersion = armatureData.dataVersion = json[ccs.CONST_VERSION] || 0.1;
347 
348         var boneDataList = json[ccs.CONST_BONE_DATA];
349         for (var i = 0; i < boneDataList.length; i++) {
350             var boneData = this.decodeBoneFromJson(boneDataList[i], dataInfo);
351             armatureData.addBoneData(boneData);
352         }
353         return armatureData;
354     },
355 
356     /**
357      * decode xml bone data.
358      * @param {XMLDocument} boneXML
359      * @param {XMLDocument} parentXML
360      * @param {ccs.DataInfo} dataInfo
361      * @returns {ccs.BoneData}
362      */
363     decodeBone: function (boneXML, parentXML, dataInfo) {
364         var boneData = new ccs.BoneData();
365         boneData.init();
366 
367         boneData.name = boneXML.getAttribute(ccs.CONST_A_NAME);
368         boneData.parentName = boneXML.getAttribute(ccs.CONST_A_PARENT) || "";
369 
370         boneData.zOrder = parseInt(boneXML.getAttribute(ccs.CONST_A_Z)) || 0;
371 
372         var displaysXML = boneXML.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_DISPLAY);
373         for (var i = 0; i < displaysXML.length; i++) {
374             var displayXML = displaysXML[i];
375             var displayData = this.decodeBoneDisplay(displayXML, dataInfo);
376             boneData.addDisplayData(displayData);
377         }
378         return boneData;
379     },
380 
381     /**
382      * decode json bone data.
383      * @param {Object} json json bone data.
384      * @param {ccs.DataInfo} dataInfo
385      * @returns {ccs.BoneData}
386      */
387     decodeBoneFromJson: function (json, dataInfo) {
388         var boneData = new ccs.BoneData();
389         boneData.init();
390 
391         this.decodeNodeFromJson(boneData, json, dataInfo);
392 
393         boneData.name = json[ccs.CONST_A_NAME] || "";
394 
395         boneData.parentName = json[ccs.CONST_A_PARENT] || "";
396         var displayDataList = json[ccs.CONST_DISPLAY_DATA] || [];
397         for (var i = 0; i < displayDataList.length; i++) {
398             var locDisplayData = this.decodeBoneDisplayFromJson(displayDataList[i], dataInfo);
399             boneData.addDisplayData(locDisplayData);
400         }
401         return boneData;
402     },
403 
404     /**
405      * decode xml display data of bone
406      * @param {XMLDocument} displayXML
407      * @param {ccs.DataInfo} dataInfo
408      * @returns {ccs.DisplayData}
409      */
410     decodeBoneDisplay: function (displayXML, dataInfo) {
411         var isArmature = parseFloat(displayXML.getAttribute(ccs.CONST_A_IS_ARMATURE)) || 0;
412         var displayData = null;
413 
414         if (isArmature == 1) {
415             displayData = new ccs.ArmatureDisplayData();
416             displayData.displayType = ccs.DISPLAY_TYPE_ARMATURE;
417         } else {
418             displayData = new ccs.SpriteDisplayData();
419             displayData.displayType = ccs.DISPLAY_TYPE_SPRITE;
420         }
421 
422         var displayName = displayXML.getAttribute(ccs.CONST_A_NAME) || "";
423         if (displayName) {
424             displayData.displayName = displayName;
425         }
426         return displayData;
427     },
428 
429     /**
430      * Decodes json display data of bone.
431      * @param {Object} json
432      * @param {ccs.DataInfo} dataInfo
433      * @returns {ccs.DisplayData}
434      */
435     decodeBoneDisplayFromJson: function (json, dataInfo) {
436         var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DISPLAY_TYPE_SPRITE;
437         var displayData = null;
438 
439         switch (displayType) {
440             case ccs.DISPLAY_TYPE_SPRITE:
441                 displayData = new ccs.SpriteDisplayData();
442 
443                 var name = json[ccs.CONST_A_NAME];
444                 if(name != null){
445                     displayData.displayName =  name;
446                 }
447 
448                 var dicArray = json[ccs.CONST_SKIN_DATA] || [];
449                 var dic = dicArray[0];
450                 if (dic) {
451                     var skinData = displayData.skinData;
452                     skinData.x = dic[ccs.CONST_A_X] * this._positionReadScale;
453                     skinData.y = dic[ccs.CONST_A_Y] * this._positionReadScale;
454                     skinData.scaleX = dic[ccs.CONST_A_SCALE_X] == null ? 1 : dic[ccs.CONST_A_SCALE_X];
455                     skinData.scaleY = dic[ccs.CONST_A_SCALE_Y] == null ? 1 : dic[ccs.CONST_A_SCALE_Y];
456                     skinData.skewX = dic[ccs.CONST_A_SKEW_X] == null ? 1 : dic[ccs.CONST_A_SKEW_X];
457                     skinData.skewY = dic[ccs.CONST_A_SKEW_Y] == null ? 1 : dic[ccs.CONST_A_SKEW_Y];
458 
459                     skinData.x *= dataInfo.contentScale;
460                     skinData.y *= dataInfo.contentScale;
461                 }
462                 break;
463             case ccs.DISPLAY_TYPE_ARMATURE:
464                 displayData = new ccs.ArmatureDisplayData();
465                 var name = json[ccs.CONST_A_NAME];
466                 if(name != null){
467                     displayData.displayName = json[ccs.CONST_A_NAME];
468                 }
469                 break;
470             case ccs.DISPLAY_TYPE_PARTICLE:
471                 displayData = new ccs.ParticleDisplayData();
472                 var plist = json[ccs.CONST_A_PLIST];
473                 if(plist != null){
474                     if(dataInfo.asyncStruct){
475                         displayData.displayName = dataInfo.asyncStruct.basefilePath + plist;
476                     }else{
477                         displayData.displayName = dataInfo.basefilePath + plist;
478                     }
479                 }
480                 break;
481             default:
482                 displayData = new ccs.SpriteDisplayData();
483                 break;
484         }
485         displayData.displayType = displayType;
486         return displayData;
487     },
488 
489     /**
490      * Decodes xml animation data.
491      * @param {XMLDocument} animationXML
492      * @param {ccs.DataInfo} dataInfo
493      * @returns {ccs.AnimationData}
494      */
495     decodeAnimation: function (animationXML, dataInfo) {
496         var aniData = new ccs.AnimationData();
497         var name = animationXML.getAttribute(ccs.CONST_A_NAME);
498         var armatureData = ccs.armatureDataManager.getArmatureData(name);
499         aniData.name = name;
500 
501         var movementsXML = animationXML.querySelectorAll(ccs.CONST_ANIMATION + " > " + ccs.CONST_MOVEMENT);
502         var movementXML = null;
503 
504         for (var i = 0; i < movementsXML.length; i++) {
505             movementXML = movementsXML[i];
506             var movementData = this.decodeMovement(movementXML, armatureData, dataInfo);
507             aniData.addMovement(movementData);
508         }
509         return aniData;
510     },
511 
512     /**
513      * Decodes animation json data.
514      * @param {Object} json
515      * @param {ccs.DataInfo} dataInfo
516      * @returns {ccs.AnimationData}
517      */
518     decodeAnimationFromJson: function (json, dataInfo) {
519         var aniData = new ccs.AnimationData();
520         var name = json[ccs.CONST_A_NAME];
521         if(name){
522             aniData.name = json[ccs.CONST_A_NAME];
523         }
524 
525         var movementDataList = json[ccs.CONST_MOVEMENT_DATA] || [];
526         for (var i = 0; i < movementDataList.length; i++) {
527             var locMovementData = this.decodeMovementFromJson(movementDataList[i], dataInfo);
528             aniData.addMovement(locMovementData);
529         }
530         return aniData;
531     },
532 
533     /**
534      * Decodes xml movement data.
535      * @param {XMLDocument} movementXML
536      * @param {ccs.ArmatureData} armatureData
537      * @param {ccs.DataInfo} dataInfo
538      * @returns {ccs.MovementData}
539      */
540     decodeMovement: function (movementXML, armatureData, dataInfo) {
541         var movementData = new ccs.MovementData();
542         movementData.name = movementXML.getAttribute(ccs.CONST_A_NAME);
543 
544         var duration, durationTo, durationTween, loop, tweenEasing = 0;
545 
546         duration = movementXML.getAttribute(ccs.CONST_A_DURATION);
547         movementData.duration = duration == null ? 0 : parseFloat(duration);
548 
549         durationTo = movementXML.getAttribute(ccs.CONST_A_DURATION_TO);
550         movementData.durationTo = durationTo == null ? 0 : parseFloat(durationTo);
551 
552         durationTween = movementXML.getAttribute(ccs.CONST_A_DURATION_TWEEN);
553         movementData.durationTween = durationTween == null ? 0 : parseFloat(durationTween);
554 
555         loop = movementXML.getAttribute(ccs.CONST_A_LOOP);
556         movementData.loop = loop ? Boolean(parseFloat(loop)) : true;
557 
558         var easing = movementXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
559         if (easing) {
560             if (easing != ccs.CONST_FL_NAN) {
561                 tweenEasing = easing == null ? 0 : parseFloat(easing);
562                 movementData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
563             } else
564                 movementData.tweenEasing = ccs.TweenType.linear;
565         }
566 
567         var movBonesXml = movementXML.querySelectorAll(ccs.CONST_MOVEMENT + " > " + ccs.CONST_BONE);
568         var movBoneXml = null;
569         for (var i = 0; i < movBonesXml.length; i++) {
570             movBoneXml = movBonesXml[i];
571             var boneName = movBoneXml.getAttribute(ccs.CONST_A_NAME);
572 
573             if (movementData.getMovementBoneData(boneName))
574                 continue;
575 
576             var boneData = armatureData.getBoneData(boneName);
577             var parentName = boneData.parentName;
578 
579             var parentXML = null;
580             if (parentName != "") {
581                 for (var j = 0; j < movBonesXml.length; j++) {
582                     parentXML = movBonesXml[j];
583                     if (parentName == parentXML.getAttribute(ccs.CONST_A_NAME))
584                         break;
585                 }
586             }
587             var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData, dataInfo);
588             movementData.addMovementBoneData(moveBoneData);
589         }
590         return movementData;
591     },
592 
593     /**
594      * Decodes json movement data.
595      * @param {Object} json
596      * @param {ccs.DataInfo} dataInfo
597      * @returns {ccs.MovementData}
598      */
599     decodeMovementFromJson: function (json, dataInfo) {
600         var movementData = new ccs.MovementData();
601 
602         movementData.loop = json[ccs.CONST_A_LOOP] == null ? false : json[ccs.CONST_A_LOOP];
603         movementData.durationTween = json[ccs.CONST_A_DURATION_TWEEN] || 0;
604         movementData.durationTo = json[ccs.CONST_A_DURATION_TO] || 0;
605         movementData.duration = json[ccs.CONST_A_DURATION] || 0;
606 
607         if(json[ccs.CONST_A_DURATION] == null){
608             movementData.scale = 1;
609         }else{
610             movementData.scale = json[ccs.CONST_A_MOVEMENT_SCALE] == null ? 1 : json[ccs.CONST_A_MOVEMENT_SCALE];
611         }
612 
613         movementData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] == null ? ccs.TweenType.linear : json[ccs.CONST_A_TWEEN_EASING];
614         var name = json[ccs.CONST_A_NAME];
615         if(name)
616             movementData.name = name;
617 
618         var movementBoneList = json[ccs.CONST_MOVEMENT_BONE_DATA] || [];
619         for (var i = 0; i < movementBoneList.length; i++) {
620             var locMovementBoneData = this.decodeMovementBoneFromJson(movementBoneList[i], dataInfo);
621             movementData.addMovementBoneData(locMovementBoneData);
622         }
623         return movementData;
624     },
625 
626     /**
627      * Decodes xml data of bone's movement.
628      * @param {XMLDocument} movBoneXml
629      * @param {XMLDocument} parentXml
630      * @param {ccs.BoneData} boneData
631      * @param {ccs.DataInfo} dataInfo
632      * @returns {ccs.MovementBoneData}
633      */
634     decodeMovementBone: function (movBoneXml, parentXml, boneData, dataInfo) {
635         var movBoneData = new ccs.MovementBoneData();
636         movBoneData.init();
637 
638         var scale, delay;
639         if (movBoneXml) {
640             scale = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_SCALE)) || 0;
641             movBoneData.scale = scale;
642 
643             delay = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_DELAY)) || 0;
644             if (delay > 0)
645                 delay -= 1;
646             movBoneData.delay = delay;
647         }
648 
649         var length = 0, parentTotalDuration = 0,currentDuration = 0;
650         var parentFrameXML = null,parentXMLList = [];
651 
652         /*
653          *  get the parent frame xml list, we need get the origin data
654          */
655         if (parentXml != null) {
656             var parentFramesXML = parentXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
657             for (var i = 0; i < parentFramesXML.length; i++)
658                 parentXMLList.push(parentFramesXML[i]);
659             length = parentXMLList.length;
660         }
661 
662         movBoneData.name = movBoneXml.getAttribute(ccs.CONST_A_NAME);
663 
664         var framesXML = movBoneXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
665 
666         var j = 0, totalDuration = 0;
667         for (var ii = 0; ii < framesXML.length; ii++) {
668             var frameXML = framesXML[ii];
669             if (parentXml) {
670                 /*
671                  *  in this loop we get the corresponding parent frame xml
672                  */
673                 while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
674                     parentFrameXML = parentXMLList[j];
675                     parentTotalDuration += currentDuration;
676                     currentDuration = parseFloat(parentFrameXML.getAttribute(ccs.CONST_A_DURATION));
677                     j++;
678                 }
679             }
680             var boneFrameData = this.decodeFrame(frameXML, parentFrameXML, boneData, dataInfo);
681             movBoneData.addFrameData(boneFrameData);
682             boneFrameData.frameID = totalDuration;
683             totalDuration += boneFrameData.duration;
684             movBoneData.duration = totalDuration;
685         }
686 
687         //Change rotation range from (-180 -- 180) to (-infinity -- infinity)
688         var frames = movBoneData.frameList, pi = Math.PI;
689         for (var i = frames.length - 1; i >= 0; i--) {
690             if (i > 0) {
691                 var difSkewX = frames[i].skewX - frames[i - 1].skewX;
692                 var difSkewY = frames[i].skewY - frames[i - 1].skewY;
693 
694                 if (difSkewX < -pi || difSkewX > pi) {
695                     frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
696                 }
697 
698                 if (difSkewY < -pi || difSkewY > pi) {
699                     frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
700                 }
701             }
702         }
703 
704         var frameData = new ccs.FrameData();
705         frameData.copy(movBoneData.frameList[movBoneData.frameList.length - 1]);
706         frameData.frameID = movBoneData.duration;
707         movBoneData.addFrameData(frameData);
708         return movBoneData;
709     },
710 
711     /**
712      * Decodes json data of bone's movement.
713      * @param {Object} json
714      * @param {ccs.DataInfo} dataInfo
715      * @returns {ccs.MovementBoneData}
716      */
717     decodeMovementBoneFromJson: function (json, dataInfo) {
718         var movementBoneData = new ccs.MovementBoneData();
719         movementBoneData.init();
720         movementBoneData.delay = json[ccs.CONST_A_MOVEMENT_DELAY] || 0;
721 
722         var name = json[ccs.CONST_A_NAME];
723         if(name)
724             movementBoneData.name = name;
725 
726         var framesData = json[ccs.CONST_FRAME_DATA] || [];
727         var length = framesData.length;
728         for (var i = 0; i < length; i++) {
729             var dic = json[ccs.CONST_FRAME_DATA][i];
730             var frameData = this.decodeFrameFromJson(dic, dataInfo);
731             movementBoneData.addFrameData(frameData);
732 
733             if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED){
734                 frameData.frameID = movementBoneData.duration;
735                 movementBoneData.duration += frameData.duration;
736             }
737         }
738 
739         if (dataInfo.cocoStudioVersion < ccs.VERSION_CHANGE_ROTATION_RANGE) {
740             //! Change rotation range from (-180 -- 180) to (-infinity -- infinity)
741             var frames = movementBoneData.frameList;
742             var pi = Math.PI;
743             for (var i = frames.length - 1; i >= 0; i--) {
744                 if (i > 0) {
745                     var difSkewX = frames[i].skewX - frames[i - 1].skewX;
746                     var difSkewY = frames[i].skewY - frames[i - 1].skewY;
747 
748                     if (difSkewX < -pi || difSkewX > pi) {
749                         frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
750                     }
751 
752                     if (difSkewY < -pi || difSkewY > pi) {
753                         frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
754                     }
755                 }
756             }
757         }
758 
759         if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
760             if (movementBoneData.frameList.length > 0) {
761                 var frameData = new ccs.FrameData();
762                 frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
763                 movementBoneData.addFrameData(frameData);
764                 frameData.frameID = movementBoneData.duration;
765             }
766         }
767         return movementBoneData;
768     },
769 
770     /**
771      * Decodes xml data of frame.
772      * @param {XMLDocument} frameXML
773      * @param {XMLDocument} parentFrameXml
774      * @param {ccs.BoneData} boneData
775      * @param {ccs.DataInfo} dataInfo
776      * @returns {ccs.FrameData}
777      */
778     decodeFrame: function (frameXML, parentFrameXml, boneData, dataInfo) {
779         var x = 0, y = 0, scale_x = 0, scale_y = 0, skew_x = 0, skew_y = 0, tweenRotate = 0;
780         var duration = 0, displayIndex = 0, zOrder = 0, tweenEasing = 0, blendType = 0;
781 
782         var frameData = new ccs.FrameData();
783         frameData.strMovement = frameXML.getAttribute(ccs.CONST_A_MOVEMENT) || "";
784         frameData.movement = frameData.strMovement;
785         frameData.strEvent = frameXML.getAttribute(ccs.CONST_A_EVENT) || "";
786         frameData.event = frameData.strEvent;
787         frameData.strSound = frameXML.getAttribute(ccs.CONST_A_SOUND) || "";
788         frameData.sound = frameData.strSound;
789         frameData.strSoundEffect = frameXML.getAttribute(ccs.CONST_A_SOUND_EFFECT) || "";
790         frameData.soundEffect = frameData.strSoundEffect;
791 
792         var isTween = frameXML.getAttribute(ccs.CONST_A_TWEEN_FRAME);
793         frameData.isTween = !(isTween != undefined && isTween == "false");
794 
795         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
796             x = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X);
797             if(x){
798                 frameData.x = parseFloat(x);
799                 frameData.x *= this._positionReadScale;
800             }
801             y = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y);
802             if(y){
803                 frameData.y = -parseFloat(y);
804                 frameData.y *= this._positionReadScale;
805             }
806         } else {
807             x = frameXML.getAttribute(ccs.CONST_A_X);
808             if(x) {
809                 frameData.x = parseFloat(x);
810                 frameData.x *= this._positionReadScale;
811             }
812             y = frameXML.getAttribute(ccs.CONST_A_Y);
813             if(y) {
814                 frameData.y = -parseFloat(y);
815                 frameData.y *= this._positionReadScale;
816             }
817         }
818 
819         scale_x = frameXML.getAttribute(ccs.CONST_A_SCALE_X);
820         if( scale_x != null )
821             frameData.scaleX = parseFloat(scale_x);
822         scale_y = frameXML.getAttribute(ccs.CONST_A_SCALE_Y);
823         if( scale_y != null )
824             frameData.scaleY = parseFloat(scale_y);
825         skew_x = frameXML.getAttribute(ccs.CONST_A_SKEW_X);
826         if( skew_x != null )
827             frameData.skewX = cc.degreesToRadians(parseFloat(skew_x));
828         skew_y = frameXML.getAttribute(ccs.CONST_A_SKEW_Y);
829         if( skew_y != null )
830             frameData.skewY = cc.degreesToRadians(-parseFloat(skew_y));
831 
832         duration = frameXML.getAttribute(ccs.CONST_A_DURATION);
833         if( duration != null )
834             frameData.duration = parseFloat(duration);
835         displayIndex = frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX);
836         if( displayIndex != null )
837             frameData.displayIndex = parseFloat(displayIndex);
838         zOrder = frameXML.getAttribute(ccs.CONST_A_Z);
839         if( zOrder != null )
840             frameData.zOrder = parseInt(zOrder);
841         tweenRotate = frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATE);
842         if( tweenRotate != null )
843             frameData.tweenRotate = parseFloat(tweenRotate);
844 
845         blendType = frameXML.getAttribute(ccs.CONST_A_BLEND_TYPE);
846         if ( blendType != null ) {
847             var blendFunc = frameData.blendFunc;
848             switch (blendType) {
849                 case ccs.BLEND_TYPE_NORMAL:
850                     blendFunc.src = cc.BLEND_SRC;
851                     blendFunc.dst = cc.BLEND_DST;
852                     break;
853                 case ccs.BLEND_TYPE_ADD:
854                     blendFunc.src = cc.SRC_ALPHA;
855                     blendFunc.dst = cc.ONE;
856                     break;
857                 case ccs.BLEND_TYPE_MULTIPLY:
858                     blendFunc.src = cc.DST_COLOR;
859                     blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
860                     break;
861                 case ccs.BLEND_TYPE_SCREEN:
862                     blendFunc.src = cc.ONE;
863                     blendFunc.dst = cc.ONE_MINUS_DST_COLOR;
864                     break;
865                 default:
866                     frameData.blendFunc.src = cc.BLEND_SRC;
867                     frameData.blendFunc.dst = cc.BLEND_DST;
868                     break;
869             }
870         }
871 
872         var colorTransformXML = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
873         if (colorTransformXML && colorTransformXML.length > 0) {
874             colorTransformXML = colorTransformXML[0];
875             var alpha, red, green, blue;
876             var alphaOffset, redOffset, greenOffset, blueOffset;
877 
878             alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || 0;
879             red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || 0;
880             green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || 0;
881             blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || 0;
882 
883             alphaOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET)) || 0;
884             redOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET)) || 0;
885             greenOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET)) || 0;
886             blueOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET)) || 0;
887 
888             frameData.a = 2.55 * alphaOffset + alpha;
889             frameData.r = 2.55 * redOffset + red;
890             frameData.g = 2.55 * greenOffset + green;
891             frameData.b = 2.55 * blueOffset + blue;
892 
893             frameData.isUseColorInfo = true;
894         }
895 
896         var _easing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
897         if(_easing != null) {
898             if(_easing != ccs.CONST_FL_NAN){
899                 tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
900                 if( tweenEasing )
901                     frameData.tweenEasing = (tweenEasing == 2) ? ccs.TweenType.sineEaseInOut : tweenEasing;
902             } else
903                 frameData.tweenEasing = ccs.TweenType.linear;
904         }
905 
906         if (parentFrameXml) {
907             //*  recalculate frame data from parent frame data, use for translate matrix
908             var helpNode = new ccs.BaseData();
909             if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
910                 helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X));
911                 helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y));
912             } else {
913                 helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X));
914                 helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y));
915             }
916             helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X));
917             helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y));
918 
919             helpNode.y = -helpNode.y;
920             helpNode.skewX = cc.degreesToRadians(helpNode.skewX);
921             helpNode.skewY = cc.degreesToRadians(-helpNode.skewY);
922             ccs.TransformHelp.transformFromParent(frameData, helpNode);
923         }
924         return frameData;
925     },
926 
927     /**
928      * Decodes json data of frame.
929      * @param {Object} json
930      * @param {ccs.DataInfo} dataInfo
931      * @returns {ccs.FrameData}
932      */
933     decodeFrameFromJson: function (json, dataInfo) {
934         var frameData = new ccs.FrameData();
935 
936         this.decodeNodeFromJson(frameData, json, dataInfo);
937 
938         frameData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.linear;
939         frameData.displayIndex = json[ccs.CONST_A_DISPLAY_INDEX];
940         var bd_src = json[ccs.CONST_A_BLEND_SRC] == null ? cc.BLEND_SRC : json[ccs.CONST_A_BLEND_SRC];
941         var bd_dst = json[ccs.CONST_A_BLEND_DST] == null ? cc.BLEND_DST : json[ccs.CONST_A_BLEND_DST];
942         frameData.blendFunc.src = bd_src;
943         frameData.blendFunc.dst = bd_dst;
944         frameData.isTween = json[ccs.CONST_A_TWEEN_FRAME] == null ? true : json[ccs.CONST_A_TWEEN_FRAME];
945 
946         var event = json[ccs.CONST_A_EVENT];
947         if(event != null){
948             frameData.strEvent = event;
949             frameData.event = event;
950         }
951 
952         if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED)
953             frameData.duration = json[ccs.CONST_A_DURATION] == null ? 1 : json[ccs.CONST_A_DURATION];
954         else
955             frameData.frameID = json[ccs.CONST_A_FRAME_INDEX];
956 
957         var twEPs = json[ccs.CONST_A_EASING_PARAM] || [];
958         for (var i = 0; i < twEPs.length; i++) {
959             frameData.easingParams[i] = twEPs[i];
960         }
961 
962         return frameData;
963     },
964 
965     /**
966      * Decodes xml data of texture
967      * @param {XMLDocument} textureXML
968      * @param {ccs.DataInfo} dataInfo
969      * @returns {ccs.TextureData}
970      */
971     decodeTexture: function (textureXML, dataInfo) {
972         var textureData = new ccs.TextureData();
973         textureData.init();
974 
975         if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
976             textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
977         }
978 
979         var px, py;
980 
981         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
982             px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
983             py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
984         } else {
985             px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
986             py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
987         }
988 
989         var width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
990         var height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
991 
992         var anchorPointX = px / width;
993         var anchorPointY = (height - py) / height;
994 
995         textureData.pivotX = anchorPointX;
996         textureData.pivotY = anchorPointY;
997 
998         var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
999         for (var i = 0; i < contoursXML.length; i++) {
1000             textureData.addContourData(this.decodeContour(contoursXML[i], dataInfo));
1001         }
1002         return textureData;
1003     },
1004 
1005     /**
1006      * Decodes json data of Texture.
1007      * @param json
1008      * @returns {ccs.TextureData}
1009      */
1010     decodeTextureFromJson: function (json) {
1011         var textureData = new ccs.TextureData();
1012         textureData.init();
1013 
1014         var name = json[ccs.CONST_A_NAME];
1015         if(name != null)
1016             textureData.name = name;
1017 
1018         textureData.width = json[ccs.CONST_A_WIDTH] || 0;
1019         textureData.height = json[ccs.CONST_A_HEIGHT] || 0;
1020         textureData.pivotX = json[ccs.CONST_A_PIVOT_X] || 0;
1021         textureData.pivotY = json[ccs.CONST_A_PIVOT_Y] || 0;
1022 
1023         var contourDataList = json[ccs.CONST_CONTOUR_DATA] || [];
1024         for (var i = 0; i < contourDataList.length; i++) {
1025             textureData.contourDataList.push(this.decodeContourFromJson(contourDataList[i]));
1026         }
1027         return textureData;
1028     },
1029 
1030     /**
1031      * Decodes xml data of contour.
1032      * @param {XMLDocument} contourXML
1033      * @param {ccs.DataInfo} dataInfo
1034      * @returns {ccs.ContourData}
1035      */
1036     decodeContour: function (contourXML, dataInfo) {
1037         var contourData = new ccs.ContourData();
1038         contourData.init();
1039 
1040         var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
1041         var vertexDataXML;
1042         for (var i = 0; i < vertexDatasXML.length; i++) {
1043             vertexDataXML = vertexDatasXML[i];
1044             var vertex = cc.p(0, 0);
1045             vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
1046             vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
1047 
1048             vertex.y = - vertex.y;
1049             contourData.vertexList.push(vertex);
1050         }
1051         return contourData;
1052     },
1053 
1054     /**
1055      * Decodes json data of contour.
1056      * @param {Object} json
1057      * @returns {ccs.ContourData}
1058      */
1059     decodeContourFromJson: function (json) {
1060         var contourData = new ccs.ContourData();
1061         contourData.init();
1062 
1063         var vertexPointList = json[ccs.CONST_VERTEX_POINT] || [];
1064         var len = vertexPointList.length;
1065         for (var i = 0; i < len; i++) {
1066             var dic = vertexPointList[i];
1067             var vertex = cc.p(0, 0);
1068             vertex.x = dic[ccs.CONST_A_X] || 0;
1069             vertex.y = dic[ccs.CONST_A_Y] || 0;
1070             contourData.vertexList.push(vertex);
1071         }
1072         return contourData;
1073     },
1074 
1075     /**
1076      * Adds json armature data to armature data manager.
1077      * @param {Object} dic json armature data
1078      * @param {ccs.DataInfo} dataInfo
1079      */
1080     addDataFromJsonCache: function (dic, dataInfo) {
1081         dataInfo.contentScale = dic[ccs.CONST_CONTENT_SCALE] == null ? 1 : dic[ccs.CONST_CONTENT_SCALE];
1082 
1083         // Decode armatures
1084         var armatureDataArr = dic[ccs.CONST_ARMATURE_DATA] || [], i;
1085         var armatureData;
1086         for (i = 0; i < armatureDataArr.length; i++) {
1087             armatureData = this.decodeArmatureFromJSON(armatureDataArr[i], dataInfo);
1088             ccs.armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
1089         }
1090 
1091         // Decode animations
1092         var animationDataArr = dic[ccs.CONST_ANIMATION_DATA] || [];
1093         var animationData;
1094         for (i = 0; i < animationDataArr.length; i++) {
1095             animationData = this.decodeAnimationFromJson(animationDataArr[i], dataInfo);
1096             ccs.armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
1097         }
1098 
1099         // Decode textures
1100         var textureDataArr = dic[ccs.CONST_TEXTURE_DATA] || [];
1101         var textureData;
1102         for (i = 0; i < textureDataArr.length; i++) {
1103             textureData = this.decodeTextureFromJson(textureDataArr[i], dataInfo);
1104             ccs.armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
1105         }
1106 
1107         // Auto load sprite file
1108         var autoLoad = dataInfo.asyncStruct == null ? ccs.armatureDataManager.isAutoLoadSpriteFile() : dataInfo.asyncStruct.autoLoadSpriteFile;
1109 //        if (isLoadSpriteFrame) {
1110         if (autoLoad) {
1111             var configFiles = dic[ccs.CONST_CONFIG_FILE_PATH] || [];
1112             var locFilePath, locPos, locPlistPath, locImagePath;
1113             for (i = 0; i < configFiles.length; i++) {
1114                 locFilePath = configFiles[i];
1115                 locPos = locFilePath.lastIndexOf(".");
1116                 locFilePath = locFilePath.substring(0, locPos);
1117                 locPlistPath = dataInfo.basefilePath + locFilePath + ".plist";
1118                 locImagePath = dataInfo.basefilePath + locFilePath + ".png";
1119                 ccs.armatureDataManager.addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
1120             }
1121         }
1122 
1123         armatureData = null;
1124         animationData = null;
1125     },
1126 
1127     /**
1128      * Decodes json data of node.
1129      * @param node
1130      * @param json
1131      * @param dataInfo
1132      */
1133     decodeNodeFromJson: function (node, json, dataInfo) {
1134         node.x = json[ccs.CONST_A_X] * this._positionReadScale;
1135         node.y = json[ccs.CONST_A_Y] * this._positionReadScale;
1136 
1137         node.x *= dataInfo.contentScale;
1138         node.y *= dataInfo.contentScale;
1139 
1140         node.zOrder = json[ccs.CONST_A_Z];
1141 
1142         node.skewX = json[ccs.CONST_A_SKEW_X] || 0;
1143         node.skewY = json[ccs.CONST_A_SKEW_Y] || 0;
1144         node.scaleX = json[ccs.CONST_A_SCALE_X] == null ? 1 : json[ccs.CONST_A_SCALE_X];
1145         node.scaleY = json[ccs.CONST_A_SCALE_Y] == null ? 1 : json[ccs.CONST_A_SCALE_Y];
1146 
1147         var colorDic;
1148         if (dataInfo.cocoStudioVersion < ccs.VERSION_COLOR_READING) {
1149             colorDic = json[0];
1150             if (colorDic){
1151                 node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
1152                 node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
1153                 node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
1154                 node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
1155                 node.isUseColorInfo = true;
1156             }
1157         } else {
1158             colorDic = json[ccs.CONST_COLOR_INFO] || null;
1159             if (colorDic){
1160                 node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
1161                 node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
1162                 node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
1163                 node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
1164                 node.isUseColorInfo = true;
1165             }
1166         }
1167     },
1168 
1169     clear: function () {
1170         this._configFileList = [];
1171         this._asyncRefCount = 0;
1172         this._asyncRefTotalCount = 0;
1173     },
1174 
1175     _asyncCallBack: function (selector, target, percent) {
1176         if(selector && cc.isFunction(selector))
1177             selector.call(target, percent);
1178         if(target && selector && typeof selector === 'string')
1179             target[selector](percent);
1180     },
1181     /**
1182      * find the base file path
1183      * @param filePath
1184      * @returns {String}
1185      * @private
1186      */
1187     _initBaseFilePath: function (filePath) {
1188         var path = filePath;
1189         var pos = path.lastIndexOf("/");
1190         if (pos > -1)
1191             path = path.substr(0, pos + 1);
1192         else
1193             path = "";
1194         return path;
1195     },
1196 
1197     /**
1198      * Adds xml armature data to armature data manager.
1199      * @param {XMLDocument} xml
1200      * @param {ccs.DataInfo} dataInfo
1201      */
1202     addDataFromXML: function (xml, dataInfo) {
1203         /*
1204          *  Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS
1205          */
1206         var xmlStr = cc.loader.getRes(xml);
1207         if (!xmlStr) throw "Please load the resource first : " + xml;
1208         var skeletonXML = cc.saxParser.parse(xmlStr);
1209         var skeleton = skeletonXML.documentElement;
1210         if (skeleton)
1211             this.addDataFromCache(skeleton, dataInfo);
1212     },
1213 
1214     /**
1215      * Adds json armature data to armature data manager.
1216      * @param {String} filePath
1217      * @param {ccs.DataInfo} dataInfo
1218      */
1219     addDataFromJson: function (filePath, dataInfo) {
1220         var fileContent = cc.loader.getRes(filePath);
1221         this.addDataFromJsonCache(fileContent, dataInfo);
1222     }
1223 };