1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * @ignore
 27  */
 28 ccs.CONST_VERSION = "version";
 29 ccs.CONST_VERSION_2_0 = 2.0;
 30 ccs.CONST_VERSION_COMBINED = 0.3;
 31 
 32 ccs.CONST_SKELETON = "skeleton";
 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_A_NAME = "name";
 47 ccs.CONST_A_DURATION = "dr";
 48 ccs.CONST_A_FRAME_INDEX = "fi";
 49 ccs.CONST_A_DURATION_TO = "to";
 50 ccs.CONST_A_DURATION_TWEEN = "drTW";
 51 ccs.CONST_A_LOOP = "lp";
 52 ccs.CONST_A_MOVEMENT_SCALE = "sc";
 53 ccs.CONST_A_MOVEMENT_DELAY = "dl";
 54 ccs.CONST_A_DISPLAY_INDEX = "dI";
 55 
 56 ccs.CONST_A_VERT = "vert";
 57 ccs.CONST_A_FRAG = "frag";
 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_TWEEN_ROTATION = "twR";
 71 ccs.CONST_A_EASING_PARAM = "twEP";
 72 ccs.CONST_A_IS_ARMATURE = "isArmature";
 73 ccs.CONST_A_DISPLAY_TYPE = "displayType";
 74 ccs.CONST_A_MOVEMENT = "mov";
 75 ccs.CONST_A_BLEND_TYPE = "bd";
 76 ccs.CONST_A_BLEND_SRC = "bd_src";
 77 ccs.CONST_A_BLEND_DST = "bd_dst";
 78 
 79 ccs.CONST_A_X = "x";
 80 ccs.CONST_A_Y = "y";
 81 
 82 ccs.CONST_A_COCOS2DX_X = "cocos2d_x";
 83 ccs.CONST_A_COCOS2DX_Y = "cocos2d_y";
 84 
 85 ccs.CONST_A_WIDTH = "width";
 86 ccs.CONST_A_HEIGHT = "height";
 87 ccs.CONST_A_PIVOT_X = "pX";
 88 ccs.CONST_A_PIVOT_Y = "pY";
 89 
 90 ccs.CONST_A_COCOS2D_PIVOT_X = "cocos2d_pX";
 91 ccs.CONST_A_COCOS2D_PIVOT_Y = "cocos2d_pY";
 92 
 93 ccs.CONST_A_ALPHA = "a";
 94 ccs.CONST_A_RED = "r";
 95 ccs.CONST_A_GREEN = "g";
 96 ccs.CONST_A_BLUE = "b";
 97 ccs.CONST_A_ALPHA_OFFSET = "aM";
 98 ccs.CONST_A_RED_OFFSET = "rM";
 99 ccs.CONST_A_GREEN_OFFSET = "gM";
100 ccs.CONST_A_BLUE_OFFSET = "bM";
101 ccs.CONST_A_COLOR_TRANSFORM = "colorTransform";
102 ccs.CONST_A_TWEEN_FRAME = "tweenFrame";
103 ccs.CONST_A_ROTATION = "rotation";
104 ccs.CONST_A_USE_COLOR_INFO = "uci";
105 
106 ccs.CONST_CONTOUR = "con";
107 ccs.CONST_CONTOUR_VERTEX = "con_vt";
108 
109 ccs.CONST_MOVEMENT_EVENT_FRAME = "movementEventFrame";
110 ccs.CONST_SOUND_FRAME = "soundFrame";
111 
112 ccs.CONST_FL_NAN = "NaN";
113 
114 ccs.CONST_FRAME_DATA = "frame_data";
115 ccs.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
116 ccs.CONST_MOVEMENT_FRAME_DATA = "mov_frame_data";
117 ccs.CONST_MOVEMENT_DATA = "mov_data";
118 ccs.CONST_ANIMATION_DATA = "animation_data";
119 ccs.CONST_DISPLAY_DATA = "display_data";
120 ccs.CONST_SKIN_DATA = "skin_data";
121 ccs.CONST_BONE_DATA = "bone_data";
122 ccs.CONST_ARMATURE_DATA = "armature_data";
123 ccs.CONST_CONTOUR_DATA = "contour_data";
124 ccs.CONST_TEXTURE_DATA = "texture_data";
125 ccs.CONST_VERTEX_POINT = "vertex";
126 ccs.CONST_COLOR_INFO = "color";
127 
128 ccs.CONST_CONFIG_FILE_PATH = "config_file_path";
129 ccs.CONST_CONTENT_SCALE = "content_scale";
130 
131 /**
132  * @ignore
133  * @constructor
134  */
135 ccs.DataInfo = function () {
136     this.asyncStruct = null;
137     this.configFileQueue = [];
138     this.contentScale = 1;
139     this.filename = "";
140     this.baseFilePath = "";
141     this.flashToolVersion = 0;
142     this.cocoStudioVersion = 0
143 };
144 
145 /**
146  * @namespace CocoStudio data reader helper
147  */
148 ccs.dataReaderHelper = /** @lends ccs.dataReaderHelper# */{
149     _configFileList: [],
150     _flashToolVersion: ccs.CONST_VERSION_2_0,
151     _cocoStudioVersion: ccs.CONST_VERSION_COMBINED,
152     _positionReadScale: 1,
153     _asyncRefCount: 0,
154     _asyncRefTotalCount: 0,
155 
156     setPositionReadScale: function (scale) {
157         this._positionReadScale = scale;
158     },
159 
160     getPositionReadScale: function () {
161         return this._positionReadScale;
162     },
163 
164     clear: function () {
165         this._configFileList = [];
166         this._asyncRefCount = 0;
167         this._asyncRefTotalCount = 0;
168     },
169 
170     addDataFromFile: function (filePath, isLoadSpriteFrame) {
171         if (this._configFileList.indexOf(filePath) != -1) {
172             return;
173         }
174         this._configFileList.push(filePath);
175 
176         this._initBaseFilePath(filePath);
177 
178         var str = cc.path.extname(filePath).toLowerCase();
179 
180         var dataInfo = new ccs.DataInfo();
181         dataInfo.filename = filePath;
182         dataInfo.basefilePath = this._initBaseFilePath(filePath);
183         if (str == ".xml") {
184             this.addDataFromXML(filePath, dataInfo);
185         }
186         else if (str == ".json" || str == ".exportjson") {
187             this.addDataFromJson(filePath, dataInfo, isLoadSpriteFrame);
188         }
189     },
190 
191     addDataFromFileAsync: function (filePath, target, selector, isLoadSpriteFrame) {
192         if (this._configFileList.indexOf(filePath) != -1) {
193             if (target && selector) {
194                 if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0)
195                     this._asyncCallBack(target, selector, 1);
196                 else
197                     this._asyncCallBack(target, selector, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
198             }
199             return;
200         }
201         this._asyncRefTotalCount++;
202         this._asyncRefCount++;
203         var self = this;
204         var fun = function () {
205             self.addDataFromFile(filePath, isLoadSpriteFrame);
206             self._asyncRefCount--;
207             self._asyncCallBack(target, selector, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
208         };
209         cc.director.getScheduler().scheduleCallbackForTarget(this, fun, 0.1, false);
210     },
211 
212     _asyncCallBack: function (target, selector, percent) {
213         if (target && (typeof(selector) == "string")) {
214             target[selector](percent);
215         } else if (target && (typeof(selector) == "function")) {
216             selector.call(target, percent);
217         }
218     },
219     /**
220      * find the base file path
221      * @param filePath
222      * @returns {String}
223      * @private
224      */
225     _initBaseFilePath: function (filePath) {
226         var path = filePath;
227         var pos = path.lastIndexOf("/");
228         if (pos > -1)
229             path = path.substr(0, pos + 1);
230         else
231             path = "";
232         return path;
233     },
234 
235     addDataFromXML: function (xml, dataInfo) {
236         /*
237          *  Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS
238          */
239         var xmlStr = cc.loader.getRes(xml);
240         if (!xmlStr) throw "Please load the resource first : " + xml;
241         var skeletonXML = cc.saxParser.parse(xmlStr);
242         var skeleton = skeletonXML.documentElement;
243         if (skeleton) {
244             this.addDataFromCache(skeleton, dataInfo);
245         }
246     },
247 
248     addDataFromCache: function (skeleton, dataInfo) {
249         if (!skeleton) {
250             cc.log("XML error  or  XML is empty.");
251             return;
252         }
253         dataInfo.flashToolVersion = parseFloat(skeleton.getAttribute(ccs.CONST_VERSION));
254         var armaturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ARMATURES + " >  " + ccs.CONST_ARMATURE + "");
255         var armatureDataManager = ccs.armatureDataManager;
256         for (var i = 0; i < armaturesXML.length; i++) {
257             var armatureData = this.decodeArmature(armaturesXML[i], dataInfo);
258             armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
259         }
260 
261         var animationsXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ANIMATIONS + " >  " + ccs.CONST_ANIMATION + "");
262         for (var i = 0; i < animationsXML.length; i++) {
263             var animationData = this.decodeAnimation(animationsXML[i], dataInfo);
264             armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
265         }
266 
267         var texturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_TEXTURE_ATLAS + " >  " + ccs.CONST_SUB_TEXTURE + "");
268         for (var i = 0; i < texturesXML.length; i++) {
269             var textureData = this.decodeTexture(texturesXML[i], dataInfo);
270             armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
271         }
272         skeleton = null;
273     },
274 
275     decodeArmature: function (armatureXML, dataInfo) {
276         var name = armatureXML.getAttribute(ccs.CONST_A_NAME);
277         var armatureData = new ccs.ArmatureData();
278         armatureData.name = name;
279 
280         var bonesXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE + " > " + ccs.CONST_BONE);
281 
282         for (var i = 0; i < bonesXML.length; i++) {
283             var boneXML = bonesXML[i];
284             var parentName = boneXML.getAttribute(ccs.CONST_A_PARENT);
285             var parentXML = null;
286             if (parentName) {
287                 //parentXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE+" > "+ccs.CONST_BONE);
288                 for (var j = 0; j < bonesXML.length; j++) {
289                     parentXML = bonesXML[j];
290                     if (parentName == bonesXML[j].getAttribute(ccs.CONST_A_NAME)) {
291                         //todo
292                         break;
293                     }
294                 }
295             }
296             var boneData = this.decodeBone(boneXML, parentXML, dataInfo);
297             armatureData.addBoneData(boneData);
298         }
299         return armatureData;
300     },
301 
302     decodeBone: function (boneXML, parentXML, dataInfo) {
303 
304         var name = boneXML.getAttribute(ccs.CONST_A_NAME);
305         if (name == "") {
306             return;
307         }
308         var boneData = new ccs.BoneData();
309         boneData.name = name;
310         boneData.parentName = boneXML.getAttribute(ccs.CONST_A_PARENT) || "";
311         boneData.zOrder = parseInt(boneXML.getAttribute(ccs.CONST_A_Z)) || 0;
312 
313         var displaysXML = boneXML.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_DISPLAY);
314 
315         var displayXML;
316         for (var i = 0; i < displaysXML.length; i++) {
317             displayXML = displaysXML[i];
318             var displayData = this.decodeBoneDisplay(displayXML, dataInfo);
319             boneData.addDisplayData(displayData);
320         }
321         return boneData;
322     },
323     decodeBoneDisplay: function (displayXML, dataInfo) {
324         var isArmature = parseFloat(displayXML.getAttribute(ccs.CONST_A_IS_ARMATURE)) || 0;
325         var displayData = null;
326 
327         if (isArmature == 1) {
328             displayData = new ccs.ArmatureDisplayData();
329             displayData.displayType = ccs.DISPLAY_TYPE_ARMATURE;
330         }
331         else {
332             displayData = new ccs.SpriteDisplayData();
333             displayData.displayType = ccs.DISPLAY_TYPE_SPRITE;
334         }
335         var displayName = displayXML.getAttribute(ccs.CONST_A_NAME) || "";
336         if (displayName) {
337             displayData.displayName = displayName;
338         }
339         return displayData;
340     },
341 
342 
343     decodeAnimation: function (animationXML, dataInfo) {
344         var name = animationXML.getAttribute(ccs.CONST_A_NAME);
345         var aniData = new ccs.AnimationData();
346         var armatureData = ccs.armatureDataManager.getArmatureData(name);
347         aniData.name = name;
348 
349         var movementsXML = animationXML.querySelectorAll(ccs.CONST_ANIMATION + " > " + ccs.CONST_MOVEMENT);
350         var movementXML = null;
351         for (var i = 0; i < movementsXML.length; i++) {
352             movementXML = movementsXML[i];
353             var movementData = this.decodeMovement(movementXML, armatureData, dataInfo);
354             aniData.addMovement(movementData);
355         }
356         return aniData;
357     },
358 
359     decodeMovement: function (movementXML, armatureData, dataInfo) {
360         var movName = movementXML.getAttribute(ccs.CONST_A_NAME);
361         var movementData = new ccs.MovementData();
362         movementData.name = movName;
363         var duration, durationTo, durationTween, loop = 0, tweenEasing = 0;
364 
365         duration = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION)) || 0;
366         movementData.duration = duration;
367 
368         durationTo = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION_TO)) || 0;
369         movementData.durationTo = durationTo;
370 
371         durationTween = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION_TWEEN)) || 0;
372         movementData.durationTween = durationTween;
373 
374         loop = movementXML.getAttribute(ccs.CONST_A_LOOP);
375         movementData.loop = loop ? Boolean(parseFloat(loop)) : true;
376 
377         var easing = movementXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
378         if (easing) {
379             if (easing != ccs.CONST_FL_NAN) {
380                 tweenEasing = parseFloat(easing) || 0;
381                 movementData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
382             } else {
383                 movementData.tweenEasing = ccs.TweenType.linear;
384             }
385         }
386 
387         var movBonesXml = movementXML.querySelectorAll(ccs.CONST_MOVEMENT + " > " + ccs.CONST_BONE);
388         var movBoneXml = null;
389         for (var i = 0; i < movBonesXml.length; i++) {
390             movBoneXml = movBonesXml[i];
391             var boneName = movBoneXml.getAttribute(ccs.CONST_A_NAME);
392 
393             if (movementData.getMovementBoneData(boneName)) {
394                 continue;
395             }
396 
397             var boneData = armatureData.getBoneData(boneName);
398             var parentName = boneData.parentName;
399 
400             var parentXML = null;
401             if (parentName != "") {
402                 for (var j = 0; j < movBonesXml.length; j++) {
403                     parentXML = movBonesXml[j];
404                     if (parentName == parentXML.getAttribute(ccs.CONST_A_NAME)) {
405                         break;
406                     }
407                 }
408             }
409             var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData, dataInfo);
410             movementData.addMovementBoneData(moveBoneData);
411         }
412         return movementData;
413     },
414 
415     decodeMovementBone: function (movBoneXml, parentXml, boneData, dataInfo) {
416         var movBoneData = new ccs.MovementBoneData();
417         var scale, delay;
418 
419         if (movBoneXml) {
420             scale = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_SCALE)) || 0;
421             movBoneData.scale = scale;
422 
423             delay = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_DELAY)) || 0;
424             if (delay > 0) {
425                 delay -= 1;
426             }
427             movBoneData.delay = delay;
428         }
429 
430         var length = 0;
431         var parentTotalDuration = 0;
432         var currentDuration = 0;
433         var parentFrameXML = null;
434         var parentXMLList = [];
435 
436         //*  get the parent frame xml list, we need get the origin data
437         if (parentXml != null) {
438             var parentFramesXML = parentXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
439             for (var i = 0; i < parentFramesXML.length; i++) {
440                 parentXMLList.push(parentFramesXML[i]);
441             }
442             length = parentXMLList.length;
443         }
444 
445 
446         var totalDuration = 0;
447 
448         var name = movBoneXml.getAttribute(ccs.CONST_A_NAME);
449         movBoneData.name = name;
450         var framesXML = movBoneXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
451         var j = 0;
452         for (var ii = 0; ii < framesXML.length; ii++) {
453             var frameXML = framesXML[ii];
454             if (parentXml) {
455                 //*  in this loop we get the corresponding parent frame xml
456                 while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
457                     parentFrameXML = parentXMLList[j];
458                     parentTotalDuration += currentDuration;
459                     currentDuration = parseFloat(parentFrameXML.getAttribute(ccs.CONST_A_DURATION));
460                     j++;
461                 }
462             }
463             var frameData = this.decodeFrame(frameXML, parentFrameXML, boneData, dataInfo);
464             movBoneData.addFrameData(frameData);
465             frameData.frameID = totalDuration;
466             totalDuration += frameData.duration;
467             movBoneData.duration = totalDuration;
468         }
469 
470         //Change rotation range from (-180 -- 180) to (-infinity -- infinity)
471         var frames = movBoneData.frameList;
472         var pi = Math.PI;
473         for (var i = frames.length - 1; i >= 0; i--) {
474             if (i > 0) {
475                 var difSkewX = frames[i].skewX - frames[i - 1].skewX;
476                 var difSkewY = frames[i].skewY - frames[i - 1].skewY;
477 
478                 if (difSkewX < -pi || difSkewX > pi) {
479                     frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
480                 }
481 
482                 if (difSkewY < -pi || difSkewY > pi) {
483                     frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
484                 }
485             }
486         }
487 
488         if (movBoneData.frameList.length > 0) {
489             var frameData = new ccs.FrameData();
490             frameData.copy(movBoneData.frameList[movBoneData.frameList.length - 1]);
491             frameData.frameID = movBoneData.duration;
492             movBoneData.addFrameData(frameData);
493         }
494         return movBoneData;
495     },
496     decodeFrame: function (frameXML, parentFrameXml, boneData, dataInfo) {
497         var frameData = new ccs.FrameData();
498         frameData.movement = frameXML.getAttribute(ccs.CONST_A_MOVEMENT) || "";
499         frameData.event = frameXML.getAttribute(ccs.CONST_A_EVENT) || "";
500         frameData.blendType = parseInt(frameXML.getAttribute(ccs.CONST_A_BLEND_TYPE)) || ccs.BLEND_TYPE_NORMAL;
501 
502         var blendFunc = frameData.blendFunc;
503         switch (frameData.blendType) {
504             case ccs.BLEND_TYPE_NORMAL:
505                 blendFunc.src = cc.BLEND_SRC;
506                 blendFunc.dst = cc.BLEND_DST;
507                 break;
508             case ccs.BLEND_TYPE_ADD:
509                 blendFunc.src = cc.SRC_ALPHA;
510                 blendFunc.dst = cc.ONE;
511                 break;
512             case ccs.BLEND_TYPE_MULTIPLY:
513                 blendFunc.src = cc.ONE_MINUS_SRC_ALPHA;
514                 blendFunc.dst = cc.ONE_MINUS_DST_COLOR;
515                 break;
516             case ccs.BLEND_TYPE_SCREEN:
517                 blendFunc.src = cc.ONE;
518                 blendFunc.dst = cc.ONE_MINUS_DST_COLOR;
519                 break;
520             default:
521                 break;
522         }
523 
524         frameData.sound = frameXML.getAttribute(ccs.CONST_A_SOUND) || "";
525         frameData.soundEffect = frameXML.getAttribute(ccs.CONST_A_SOUND_EFFECT) || "";
526 
527         var isTween = frameXML.getAttribute(ccs.CONST_A_TWEEN_FRAME) || true;
528         frameData.isTween = Boolean(isTween);
529 
530         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
531             frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
532             frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
533         }
534         else {
535             frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_X)) || 0;
536             frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_Y)) || 0;
537         }
538         frameData.x *= this._positionReadScale;
539         frameData.y *= this._positionReadScale;
540         frameData.scaleX = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_X)) || 0;
541         frameData.scaleY = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_Y)) || 0;
542         frameData.skewX = cc.DEGREES_TO_RADIANS(parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_X)) || 0);
543         frameData.skewY = cc.DEGREES_TO_RADIANS(-parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_Y)) || 0);
544         frameData.duration = parseFloat(frameXML.getAttribute(ccs.CONST_A_DURATION)) || 0;
545         frameData.displayIndex = parseFloat(frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX)) || 0;
546         frameData.zOrder = parseFloat(frameXML.getAttribute(ccs.CONST_A_Z)) || 0;
547         frameData.tweenRotate = parseFloat(frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATION)) || 0;
548 
549         var colorTransformXMLList = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
550         if (colorTransformXMLList.length > 0) {
551             var colorTransformXML = colorTransformXMLList[0];
552             var alpha = 0, red = 0, green = 0, blue = 0;
553             var alphaOffset = 0, redOffset = 0, greenOffset = 0, blueOffset = 100;
554 
555             alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || alpha;
556             red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || red;
557             green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || green;
558             blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || blue;
559 
560             var str_alphaOffset = colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET);
561             if (str_alphaOffset) {
562                 alphaOffset = parseFloat(str_alphaOffset);
563             }
564             var str_redOffset = colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET);
565             if (str_redOffset) {
566                 redOffset = parseFloat(str_redOffset);
567             }
568             var str_greenOffset = colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET);
569             if (str_redOffset) {
570                 greenOffset = parseFloat(str_greenOffset);
571             }
572             var str_blueOffset = colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET);
573             if (str_blueOffset) {
574                 blueOffset = parseFloat(str_blueOffset);
575             }
576 
577             frameData.a = 2.55 * alphaOffset + alpha;
578             frameData.r = 2.55 * redOffset + red;
579             frameData.g = 2.55 * greenOffset + green;
580             frameData.b = 2.55 * blueOffset + blue;
581 
582             frameData.isUseColorInfo = true;
583         }
584         if (frameData.displayIndex == -1) {
585             frameData.a = 0;
586         }
587 
588         var tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
589         if (tweenEasing) {
590             if (tweenEasing != ccs.CONST_FL_NAN) {
591                 frameData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
592             } else {
593                 frameData.tweenEasing = ccs.TweenType.linear;
594             }
595         }
596 
597         if (parentFrameXml) {
598             //*  recalculate frame data from parent frame data, use for translate matrix
599             var helpNode = new ccs.BaseData();
600             if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
601                 helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
602                 helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
603             }
604             else {
605                 helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X)) || 0;
606                 helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y)) || 0;
607             }
608             helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X)) || 0;
609             helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y)) || 0;
610 
611             helpNode.y = -helpNode.y;
612             helpNode.skewX = cc.DEGREES_TO_RADIANS(helpNode.skewX);
613             helpNode.skewY = cc.DEGREES_TO_RADIANS(-helpNode.skewY);
614             ccs.TransformHelp.transformFromParent(frameData, helpNode);
615         }
616         return frameData;
617     },
618 
619     decodeTexture: function (textureXML, dataInfo) {
620         var textureData = new ccs.TextureData();
621         if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
622             textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
623         }
624         var px, py, width, height = 0;
625         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
626             px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
627             py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
628         }
629         else {
630             px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
631             py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
632         }
633         width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
634         height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
635 
636         var anchorPointX = px / width;
637         var anchorPointY = (height - py) / height;
638 
639         textureData.pivotX = anchorPointX;
640         textureData.pivotY = anchorPointY;
641 
642         var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
643         for (var i = 0; i < contoursXML.length; i++) {
644             this.decodeContour(contoursXML[i], dataInfo);
645         }
646         return textureData;
647     },
648 
649     decodeContour: function (contourXML, dataInfo) {
650         var contourData = new ccs.ContourData();
651         var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
652         var vertexDataXML;
653         for (var i = 0; i < vertexDatasXML.length; i++) {
654             vertexDataXML = vertexDatasXML[i];
655             var vertex = cc.p(0, 0);
656             vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
657             vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
658             //vertex.y = - vertex.y;//todo
659             contourData.vertexList.push(vertex);
660         }
661         return contourData;
662 
663     },
664 
665     addDataFromJson: function (filePath, dataInfo, isLoadSpriteFrame) {
666         var fileContent = cc.loader.getRes(filePath);
667         this.addDataFromJsonCache(fileContent, dataInfo, isLoadSpriteFrame);
668     },
669     addDataFromJsonCache: function (dic, dataInfo, isLoadSpriteFrame) {
670         dataInfo.contentScale = dic[ccs.CONST_CONTENT_SCALE] || 1;
671         var armatureDataArr = dic[ccs.CONST_ARMATURE_DATA] || [];
672         var armatureData;
673         for (var i = 0; i < armatureDataArr.length; i++) {
674             armatureData = this.decodeArmatureFromJSON(armatureDataArr[i], dataInfo);
675             ccs.armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
676         }
677 
678         var animationDataArr = dic[ccs.CONST_ANIMATION_DATA] || [];
679         var animationData;
680         for (var i = 0; i < animationDataArr.length; i++) {
681             animationData = this.decodeAnimationFromJson(animationDataArr[i], dataInfo);
682             ccs.armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
683         }
684 
685         var textureDataArr = dic[ccs.CONST_TEXTURE_DATA] || [];
686         var textureData;
687         for (var i = 0; i < textureDataArr.length; i++) {
688             textureData = this.decodeTextureFromJson(textureDataArr[i], dataInfo);
689             ccs.armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
690         }
691 
692         if (isLoadSpriteFrame) {
693             var configFiles = dic[ccs.CONST_CONFIG_FILE_PATH] || [];
694             var locFilePath, locPos, locPlistPath, locImagePath;
695             for (var i = 0; i < configFiles.length; i++) {
696                 locFilePath = configFiles[i];
697                 locPos = locFilePath.lastIndexOf(".");
698                 locFilePath = locFilePath.substring(0, locPos);
699                 locPlistPath = dataInfo.basefilePath + locFilePath + ".plist";
700                 locImagePath = dataInfo.basefilePath + locFilePath + ".png";
701                 ccs.armatureDataManager.addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
702             }
703         }
704 
705         armatureData = null;
706         animationData = null;
707     },
708 
709     decodeArmatureFromJSON: function (json, dataInfo) {
710         var armatureData = new ccs.ArmatureData();
711 
712         var name = json[ccs.CONST_A_NAME];
713         if (name) {
714             armatureData.name = name;
715         }
716 
717         dataInfo.cocoStudioVersion = armatureData.dataVersion = json[ccs.CONST_VERSION] || 0.1;
718 
719         var boneDataList = json[ccs.CONST_BONE_DATA];
720         for (var i = 0; i < boneDataList.length; i++) {
721             armatureData.addBoneData(this.decodeBoneFromJson(boneDataList[i], dataInfo));
722         }
723         return armatureData;
724     },
725 
726     decodeBoneFromJson: function (json, dataInfo) {
727         var boneData = new ccs.BoneData();
728         this.decodeNodeFromJson(boneData, json, dataInfo);
729         boneData.name = json[ccs.CONST_A_NAME] || "";
730         boneData.parentName = json[ccs.CONST_A_PARENT] || "";
731         var displayDataList = json[ccs.CONST_DISPLAY_DATA] || [];
732         for (var i = 0; i < displayDataList.length; i++) {
733             var locDisplayData = this.decodeBoneDisplayFromJson(displayDataList[i], dataInfo);
734             boneData.addDisplayData(locDisplayData);
735         }
736         return boneData;
737     },
738 
739     decodeBoneDisplayFromJson: function (json, dataInfo) {
740         var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DISPLAY_TYPE_SPRITE;
741         var displayData = null;
742         switch (displayType) {
743             case ccs.DISPLAY_TYPE_SPRITE:
744                 displayData = new ccs.SpriteDisplayData();
745                 displayData.displayName = json[ccs.CONST_A_NAME] || "";
746 
747                 var dicArray = json[ccs.CONST_SKIN_DATA] || [];
748                 var dic = dicArray[0];
749                 if (dic) {
750                     var skinData = displayData.skinData;
751                     skinData.x = (dic[ccs.CONST_A_X] || 0) * this._positionReadScale;
752                     skinData.y = (dic[ccs.CONST_A_Y] || 0) * this._positionReadScale;
753                     if (dic[ccs.CONST_A_SCALE_X] !== undefined) {
754                         skinData.scaleX = dic[ccs.CONST_A_SCALE_X];
755                     }
756                     if (dic[ccs.CONST_A_SCALE_Y] !== undefined) {
757                         skinData.scaleY = dic[ccs.CONST_A_SCALE_Y];
758                     }
759                     skinData.skewX = dic[ccs.CONST_A_SKEW_X] || 0;
760                     skinData.skewY = dic[ccs.CONST_A_SKEW_Y] || 0;
761 
762                     skinData.x *= dataInfo.contentScale;
763                     skinData.y *= dataInfo.contentScale;
764                     dic = null;
765                 }
766                 break;
767             case ccs.DISPLAY_TYPE_ARMATURE:
768                 displayData = new ccs.ArmatureDisplayData();
769                 displayData.displayName = json[ccs.CONST_A_NAME] || "";
770                 break;
771             case ccs.DISPLAY_TYPE_PARTICLE:
772                 displayData = new ccs.ParticleDisplayData();
773                 displayData.displayName = dataInfo.basefilePath + json[ccs.CONST_A_PLIST] || "";
774                 break;
775             default:
776                 displayData = new ccs.SpriteDisplayData();
777                 break;
778         }
779 
780         displayData.displayType = displayType;
781 
782         return displayData;
783     },
784 
785     decodeAnimationFromJson: function (json, dataInfo) {
786         var aniData = new ccs.AnimationData();
787         aniData.name = json[ccs.CONST_A_NAME] || "";
788         var movementDataList = json[ccs.CONST_MOVEMENT_DATA] || [];
789         for (var i = 0; i < movementDataList.length; i++) {
790             var locMovementData = this.decodeMovementFromJson(movementDataList[i], dataInfo);
791             aniData.addMovement(locMovementData);
792         }
793         return aniData;
794     },
795 
796     decodeMovementFromJson: function (json, dataInfo) {
797         var movementData = new ccs.MovementData();
798 
799         movementData.loop = json[ccs.CONST_A_LOOP] || false;
800         movementData.durationTween = json[ccs.CONST_A_DURATION_TWEEN] || 0;
801         movementData.durationTo = json[ccs.CONST_A_DURATION_TO] || 0;
802         movementData.duration = json[ccs.CONST_A_DURATION] || 0;
803         if (json[ccs.CONST_A_MOVEMENT_SCALE] !== undefined) {
804             movementData.scale = json[ccs.CONST_A_MOVEMENT_SCALE]
805         }
806         movementData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.linear;
807         movementData.name = json[ccs.CONST_A_NAME] || "";
808 
809         var movementBoneList = json[ccs.CONST_MOVEMENT_BONE_DATA] || [];
810         for (var i = 0; i < movementBoneList.length; i++) {
811             var locMovementBoneData = this.decodeMovementBoneFromJson(movementBoneList[i], dataInfo);
812             movementData.addMovementBoneData(locMovementBoneData);
813         }
814         return movementData;
815     },
816 
817     decodeMovementBoneFromJson: function (json, dataInfo) {
818         var movementBoneData = new ccs.MovementBoneData();
819         movementBoneData.delay = json[ccs.CONST_A_MOVEMENT_DELAY] || 0;
820         if (json[ccs.CONST_A_MOVEMENT_SCALE] !== undefined) {
821             movementBoneData.scale = json[ccs.CONST_A_MOVEMENT_SCALE];
822         }
823 
824         movementBoneData.name = json[ccs.CONST_A_NAME] || "";
825         var frameDataList = json[ccs.CONST_FRAME_DATA] || [];
826         for (var i = 0; i < frameDataList.length; i++) {
827             var frameData = this.decodeFrameFromJson(frameDataList[i], dataInfo);
828             movementBoneData.addFrameData(frameData);
829             if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
830                 frameData.frameID = movementBoneData.duration;
831                 movementBoneData.duration += frameData.duration;
832             }
833         }
834 
835         if (dataInfo.cocoStudioVersion < ccs.VERSION_CHANGE_ROTATION_RANGE) {
836             //! Change rotation range from (-180 -- 180) to (-infinity -- infinity)
837             var frames = movementBoneData.frameList;
838             var pi = Math.PI;
839             for (var i = frames.length - 1; i >= 0; i--) {
840                 if (i > 0) {
841                     var difSkewX = frames[i].skewX - frames[i - 1].skewX;
842                     var difSkewY = frames[i].skewY - frames[i - 1].skewY;
843 
844                     if (difSkewX < -pi || difSkewX > pi) {
845                         frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
846                     }
847 
848                     if (difSkewY < -pi || difSkewY > pi) {
849                         frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
850                     }
851                 }
852             }
853         }
854 
855         if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
856             if (movementBoneData.frameList.length > 0) {
857                 var frameData = new ccs.FrameData();
858                 frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
859                 movementBoneData.addFrameData(frameData);
860                 frameData.frameID = movementBoneData.duration;
861             }
862         }
863         return movementBoneData;
864     },
865 
866     decodeFrameFromJson: function (json, dataInfo) {
867         var frameData = new ccs.FrameData();
868         this.decodeNodeFromJson(frameData, json, dataInfo);
869         frameData.duration = json[ccs.CONST_A_DURATION] || 0;
870         frameData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.linear;
871         frameData.displayIndex = json[ccs.CONST_A_DISPLAY_INDEX] || 0;
872 
873         var bd_src = json[ccs.CONST_A_BLEND_SRC] || cc.BLEND_SRC;
874         var bd_dst = json[ccs.CONST_A_BLEND_DST] || cc.BLEND_DST;
875         frameData.blendFunc.src = bd_src;
876         frameData.blendFunc.dst = bd_dst;
877 
878         frameData.event = json[ccs.CONST_A_EVENT] || null;
879         if (json[ccs.CONST_A_TWEEN_FRAME] !== undefined) {
880             frameData.isTween = json[ccs.CONST_A_TWEEN_FRAME]
881         }
882         if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED)
883             frameData.duration = json[ccs.CONST_A_DURATION] || 0;
884         else
885             frameData.frameID = json[ccs.CONST_A_FRAME_INDEX] || 0;
886 
887         var twEPs = json[ccs.CONST_A_EASING_PARAM] || [];
888         for (var i = 0; i < twEPs.length; i++) {
889             var twEP = twEPs[i];
890             frameData.easingParams[i] = twEP;
891         }
892 
893         return frameData;
894     },
895 
896     decodeTextureFromJson: function (json) {
897         var textureData = new ccs.TextureData();
898         textureData.name = json[ccs.CONST_A_NAME] || "";
899         textureData.width = json[ccs.CONST_A_WIDTH] || 0;
900         textureData.height = json[ccs.CONST_A_HEIGHT] || 0;
901         textureData.pivotX = json[ccs.CONST_A_PIVOT_X] || 0;
902         textureData.pivotY = json[ccs.CONST_A_PIVOT_Y] || 0;
903 
904         var contourDataList = json[ccs.CONST_CONTOUR_DATA] || [];
905         for (var i = 0; i < contourDataList.length; i++) {
906             var locContourData = this.decodeContourFromJson(contourDataList[i]);
907             textureData.contourDataList.push(locContourData);
908         }
909         return textureData;
910     },
911 
912     decodeContourFromJson: function (json) {
913         var contourData = new ccs.ContourData();
914         var vertexPointList = json[ccs.CONST_VERTEX_POINT] || [];
915         for (var i = 0; i < vertexPointList.length; i++) {
916             var dic = vertexPointList[i];
917             var vertex = cc.p(0, 0);
918             vertex.x = dic[ccs.CONST_A_X] || 0;
919             vertex.y = dic[ccs.CONST_A_Y] || 0;
920             contourData.vertexList.push(vertex);
921         }
922         return contourData;
923     },
924 
925     decodeNodeFromJson: function (node, json, dataInfo) {
926         node.x = json[ccs.CONST_A_X] || 0;
927         node.y = json[ccs.CONST_A_Y] || 0;
928 
929         node.x *= dataInfo.contentScale;
930         node.y *= dataInfo.contentScale;
931 
932         node.zOrder = json[ccs.CONST_A_Z] || 0;
933 
934         node.skewX = json[ccs.CONST_A_SKEW_X] || 0;
935         node.skewY = json[ccs.CONST_A_SKEW_Y] || 0;
936         if (json[ccs.CONST_A_SCALE_X] !== undefined) {
937             node.scaleX = json[ccs.CONST_A_SCALE_X];
938         }
939         if (json[ccs.CONST_A_SCALE_Y] !== undefined) {
940             node.scaleY = json[ccs.CONST_A_SCALE_Y];
941         }
942 
943         var colorDic = json[ccs.CONST_COLOR_INFO] || null;
944         if (colorDic) {
945             //compatible old version
946             if (dataInfo.cocoStudioVersion < ccs.VERSION_COLOR_READING) {
947                 colorDic = colorDic[0];
948             }
949             node.a = colorDic[ccs.CONST_A_ALPHA];
950             node.r = colorDic[ccs.CONST_A_RED];
951             node.g = colorDic[ccs.CONST_A_GREEN];
952             node.b = colorDic[ccs.CONST_A_BLUE];
953             node.isUseColorInfo = true;
954             delete colorDic;
955         }
956     },
957 
958     removeConfigFile: function (configFile) {
959         cc.arrayRemoveObject(this._configFileList, configFile);
960     }
961 };