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 ccs.CONST_VERSION = "version";
 26 ccs.CONST_VERSION_2_0 = 2.0;
 27 ccs.CONST_VERSION_COMBINED = 0.3;
 28 
 29 ccs.CONST_SKELETON = "skeleton";
 30 ccs.CONST_ARMATURES = "armatures";
 31 ccs.CONST_ARMATURE = "armature";
 32 ccs.CONST_BONE = "b";
 33 ccs.CONST_DISPLAY = "d";
 34 
 35 ccs.CONST_ANIMATIONS = "animations";
 36 ccs.CONST_ANIMATION = "animation";
 37 ccs.CONST_MOVEMENT = "mov";
 38 ccs.CONST_FRAME = "f";
 39 
 40 ccs.CONST_TEXTURE_ATLAS = "TextureAtlas";
 41 ccs.CONST_SUB_TEXTURE = "SubTexture";
 42 
 43 ccs.CONST_A_NAME = "name";
 44 ccs.CONST_A_DURATION = "dr";
 45 ccs.CONST_A_FRAME_INDEX = "fi";
 46 ccs.CONST_A_DURATION_TO = "to";
 47 ccs.CONST_A_DURATION_TWEEN = "drTW";
 48 ccs.CONST_A_LOOP = "lp";
 49 ccs.CONST_A_MOVEMENT_SCALE = "sc";
 50 ccs.CONST_A_MOVEMENT_DELAY = "dl";
 51 ccs.CONST_A_DISPLAY_INDEX = "dI";
 52 
 53 ccs.CONST_A_VERT = "vert";
 54 ccs.CONST_A_FRAG = "frag";
 55 ccs.CONST_A_PLIST = "plist";
 56 
 57 ccs.CONST_A_PARENT = "parent";
 58 ccs.CONST_A_SKEW_X = "kX";
 59 ccs.CONST_A_SKEW_Y = "kY";
 60 ccs.CONST_A_SCALE_X = "cX";
 61 ccs.CONST_A_SCALE_Y = "cY";
 62 ccs.CONST_A_Z = "z";
 63 ccs.CONST_A_EVENT = "evt";
 64 ccs.CONST_A_SOUND = "sd";
 65 ccs.CONST_A_SOUND_EFFECT = "sdE";
 66 ccs.CONST_A_TWEEN_EASING = "twE";
 67 ccs.CONST_A_TWEEN_ROTATION = "twR";
 68 ccs.CONST_A_EASING_PARAM = "twEP";
 69 ccs.CONST_A_IS_ARMATURE = "isArmature";
 70 ccs.CONST_A_DISPLAY_TYPE = "displayType";
 71 ccs.CONST_A_MOVEMENT = "mov";
 72 ccs.CONST_A_BLEND_TYPE = "bd";
 73 ccs.CONST_A_BLEND_SRC = "bd_src";
 74 ccs.CONST_A_BLEND_DST = "bd_dst";
 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_ALPHA = "a";
 91 ccs.CONST_A_RED = "r";
 92 ccs.CONST_A_GREEN = "g";
 93 ccs.CONST_A_BLUE = "b";
 94 ccs.CONST_A_ALPHA_OFFSET = "aM";
 95 ccs.CONST_A_RED_OFFSET = "rM";
 96 ccs.CONST_A_GREEN_OFFSET = "gM";
 97 ccs.CONST_A_BLUE_OFFSET = "bM";
 98 ccs.CONST_A_COLOR_TRANSFORM = "colorTransform";
 99 ccs.CONST_A_TWEEN_FRAME = "tweenFrame";
100 ccs.CONST_A_ROTATION = "rotation";
101 ccs.CONST_A_USE_COLOR_INFO = "uci";
102 
103 ccs.CONST_CONTOUR = "con";
104 ccs.CONST_CONTOUR_VERTEX = "con_vt";
105 
106 ccs.CONST_MOVEMENT_EVENT_FRAME = "movementEventFrame";
107 ccs.CONST_SOUND_FRAME = "soundFrame";
108 
109 ccs.CONST_FL_NAN = "NaN";
110 
111 ccs.CONST_FRAME_DATA = "frame_data";
112 ccs.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
113 ccs.CONST_MOVEMENT_FRAME_DATA = "mov_frame_data";
114 ccs.CONST_MOVEMENT_DATA = "mov_data";
115 ccs.CONST_ANIMATION_DATA = "animation_data";
116 ccs.CONST_DISPLAY_DATA = "display_data";
117 ccs.CONST_SKIN_DATA = "skin_data";
118 ccs.CONST_BONE_DATA = "bone_data";
119 ccs.CONST_ARMATURE_DATA = "armature_data";
120 ccs.CONST_CONTOUR_DATA = "contour_data";
121 ccs.CONST_TEXTURE_DATA = "texture_data";
122 ccs.CONST_VERTEX_POINT = "vertex";
123 ccs.CONST_COLOR_INFO = "color";
124 
125 ccs.CONST_CONFIG_FILE_PATH = "config_file_path";
126 ccs.CONST_CONTENT_SCALE = "content_scale";
127 
128 ccs.DataReaderHelper = ccs.DataReaderHelper || ccs.Class.extend({});
129 ccs.DataReaderHelper._configFileList = [];
130 ccs.DataReaderHelper._flashToolVersion = ccs.CONST_VERSION_2_0;
131 ccs.DataReaderHelper._cocoStudioVersion = ccs.CONST_VERSION_COMBINED;
132 ccs.DataReaderHelper._positionReadScale = 1;
133 ccs.DataReaderHelper._asyncRefCount = 0;
134 ccs.DataReaderHelper._asyncRefTotalCount = 0;
135 
136 ccs.DataInfo = function () {
137     this.asyncStruct = null;
138     this.configFileQueue = [];
139     this.contentScale = 1;
140     this.filename = "";
141     this.baseFilePath = "";
142     this.flashToolVersion = 0;
143     this.cocoStudioVersion = 0
144 };
145 
146 ccs.DataReaderHelper.setPositionReadScale = function (scale) {
147     this._positionReadScale = scale;
148 };
149 
150 ccs.DataReaderHelper.getPositionReadScale = function () {
151     return this._positionReadScale;
152 };
153 
154 ccs.DataReaderHelper.purge = function () {
155     this._configFileList = [];
156     this._asyncRefCount = 0;
157     this._asyncRefTotalCount = 0;
158 };
159 
160 ccs.DataReaderHelper.addDataFromFile = function (filePath,isLoadSpriteFrame) {
161     var fileUtils = cc.FileUtils.getInstance();
162     var fullFilePath = fileUtils.fullPathForFilename(filePath);
163 
164     if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) {
165         return;
166     }
167     this._configFileList.push(fullFilePath);
168 
169     this._initBaseFilePath(filePath);
170 
171     var startPos = fullFilePath.lastIndexOf(".");
172     var str = fullFilePath.substring(startPos, fullFilePath.length);
173 
174     var  dataInfo = new ccs.DataInfo();
175     dataInfo.filename = filePath;
176     dataInfo.basefilePath = this._initBaseFilePath(filePath);
177     if (str == ".xml") {
178         this.addDataFromXML(fullFilePath,dataInfo);
179     }
180     else if (str == ".json" || str == ".ExportJson") {
181         this.addDataFromJson(filePath,dataInfo,isLoadSpriteFrame);
182     }
183 };
184 
185 ccs.DataReaderHelper.addDataFromFileAsync = function (filePath,target,selector,isLoadSpriteFrame) {
186     var fileUtils = cc.FileUtils.getInstance();
187     var fullFilePath = fileUtils.fullPathForFilename(filePath);
188 
189     if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) {
190         if (target && selector) {
191             if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0)
192                 this._asyncCallBack(target, selector, 1);
193             else
194                 this._asyncCallBack(target, selector, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
195         }
196         return;
197     }
198     this._asyncRefTotalCount++;
199     this._asyncRefCount++;
200     var self = this;
201     var fun = function () {
202         self.addDataFromFile(filePath,isLoadSpriteFrame);
203         self._asyncRefCount--;
204         self._asyncCallBack(target, selector, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
205     };
206     cc.Director.getInstance().getScheduler().scheduleCallbackForTarget(this, fun, 0.1, false);
207 };
208 
209 ccs.DataReaderHelper._asyncCallBack=function (target, selector,percent) {
210     if (target && (typeof(selector) == "string")) {
211         target[selector](percent);
212     } else if (target && (typeof(selector) == "function")) {
213         selector.call(target,percent);
214     }
215 };
216 /**
217  * find the base file path
218  * @param filePath
219  * @returns {String}
220  * @private
221  */
222 ccs.DataReaderHelper._initBaseFilePath = function(filePath){
223     var path = filePath;
224     var pos = path.lastIndexOf("/");
225     if(pos>-1)
226         path = path.substr(0, pos + 1);
227     else
228         path = "";
229     return path;
230 };
231 
232 ccs.DataReaderHelper.addDataFromXML = function (xml,dataInfo) {
233     /*
234      *  Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS
235      */
236     var skeletonXML = cc.SAXParser.getInstance().tmxParse(xml);
237     var skeleton = skeletonXML.documentElement;
238     if (skeleton) {
239         this.addDataFromCache(skeleton,dataInfo);
240     }
241 };
242 
243 ccs.DataReaderHelper.addDataFromCache = function (skeleton,dataInfo) {
244     if (!skeleton) {
245         cc.log("XML error  or  XML is empty.");
246         return;
247     }
248     dataInfo.flashToolVersion = parseFloat(skeleton.getAttribute(ccs.CONST_VERSION));
249     var armaturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ARMATURES + " >  " + ccs.CONST_ARMATURE + "");
250     var armatureDataManager = ccs.ArmatureDataManager.getInstance();
251     for (var i = 0; i < armaturesXML.length; i++) {
252         var armatureData = this.decodeArmature(armaturesXML[i], dataInfo);
253         armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
254     }
255 
256     var animationsXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ANIMATIONS + " >  " + ccs.CONST_ANIMATION + "");
257     for (var i = 0; i < animationsXML.length; i++) {
258         var animationData = this.decodeAnimation(animationsXML[i] , dataInfo);
259         armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
260     }
261 
262     var texturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_TEXTURE_ATLAS + " >  " + ccs.CONST_SUB_TEXTURE + "");
263     for (var i = 0; i < texturesXML.length; i++) {
264         var textureData = this.decodeTexture(texturesXML[i], dataInfo);
265         armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
266     }
267     skeleton = null;
268 };
269 
270 ccs.DataReaderHelper.decodeArmature = function (armatureXML , dataInfo) {
271     var name = armatureXML.getAttribute(ccs.CONST_A_NAME);
272     var armatureData = new ccs.ArmatureData();
273     armatureData.name = name;
274 
275     var bonesXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE + " > " + ccs.CONST_BONE);
276 
277     for (var i = 0; i < bonesXML.length; i++) {
278         var boneXML = bonesXML[i];
279         var parentName = boneXML.getAttribute(ccs.CONST_A_PARENT);
280         var parentXML = null;
281         if (parentName) {
282             //parentXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE+" > "+ccs.CONST_BONE);
283             for (var j = 0; j < bonesXML.length; j++) {
284                 parentXML = bonesXML[j];
285                 if (parentName == bonesXML[j].getAttribute(ccs.CONST_A_NAME)) {
286                     //todo
287                     break;
288                 }
289             }
290         }
291         var boneData = this.decodeBone(boneXML, parentXML ,dataInfo);
292         armatureData.addBoneData(boneData);
293     }
294     return armatureData;
295 };
296 
297 ccs.DataReaderHelper.decodeBone = function (boneXML, parentXML , dataInfo) {
298 
299     var name = boneXML.getAttribute(ccs.CONST_A_NAME);
300     if (name == "") {
301         return;
302     }
303     var boneData = new ccs.BoneData();
304     boneData.name = name;
305     boneData.parentName = boneXML.getAttribute(ccs.CONST_A_PARENT) || "";
306     boneData.zOrder = parseInt(boneXML.getAttribute(ccs.CONST_A_Z)) || 0;
307 
308     var displaysXML = boneXML.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_DISPLAY);
309 
310     var displayXML;
311     for (var i = 0; i < displaysXML.length; i++) {
312         displayXML = displaysXML[i];
313         var displayData = this.decodeBoneDisplay(displayXML, dataInfo);
314         boneData.addDisplayData(displayData);
315     }
316     return boneData;
317 };
318 
319 ccs.DataReaderHelper.decodeBoneDisplay = function (displayXML, dataInfo) {
320     var isArmature = parseFloat(displayXML.getAttribute(ccs.CONST_A_IS_ARMATURE)) || 0;
321     var displayData = null;
322 
323     if (isArmature == 1) {
324         displayData = new ccs.ArmatureDisplayData();
325         displayData.displayType = ccs.DisplayType.armature;
326     }
327     else {
328         displayData = new ccs.SpriteDisplayData();
329         displayData.displayType = ccs.DisplayType.sprite;
330     }
331     var displayName = displayXML.getAttribute(ccs.CONST_A_NAME) || "";
332     if (displayName) {
333         displayData.displayName = displayName;
334     }
335     return displayData;
336 };
337 
338 
339 ccs.DataReaderHelper.decodeAnimation = function (animationXML, dataInfo) {
340     var name = animationXML.getAttribute(ccs.CONST_A_NAME);
341     var aniData = new ccs.AnimationData();
342     var armatureData = ccs.ArmatureDataManager.getInstance().getArmatureData(name);
343     aniData.name = name;
344 
345     var movementsXML = animationXML.querySelectorAll(ccs.CONST_ANIMATION + " > " + ccs.CONST_MOVEMENT);
346     var movementXML = null;
347     for (var i = 0; i < movementsXML.length; i++) {
348         movementXML = movementsXML[i];
349         var movementData = this.decodeMovement(movementXML, armatureData, dataInfo);
350         aniData.addMovement(movementData);
351     }
352     return aniData;
353 };
354 
355 ccs.DataReaderHelper.decodeMovement = function (movementXML, armatureData, dataInfo) {
356     var movName = movementXML.getAttribute(ccs.CONST_A_NAME);
357     var movementData = new ccs.MovementData();
358     movementData.name = movName;
359     var duration, durationTo, durationTween, loop = 0, tweenEasing = 0;
360 
361     duration = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION)) || 0;
362     movementData.duration = duration;
363 
364     durationTo = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION_TO)) || 0;
365     movementData.durationTo = durationTo;
366 
367     durationTween = parseFloat(movementXML.getAttribute(ccs.CONST_A_DURATION_TWEEN)) || 0;
368     movementData.durationTween = durationTween;
369 
370     loop = movementXML.getAttribute(ccs.CONST_A_LOOP);
371     movementData.loop = loop ? Boolean(parseFloat(loop)):true;
372 
373     var easing = movementXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
374     if (easing) {
375         if (easing != ccs.CONST_FL_NAN) {
376             tweenEasing = parseFloat(easing) || 0;
377             movementData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
378         } else {
379             movementData.tweenEasing = ccs.TweenType.linear;
380         }
381     }
382 
383     var movBonesXml = movementXML.querySelectorAll(ccs.CONST_MOVEMENT + " > " + ccs.CONST_BONE);
384     var movBoneXml = null;
385     for (var i = 0; i < movBonesXml.length; i++) {
386         movBoneXml = movBonesXml[i];
387         var boneName = movBoneXml.getAttribute(ccs.CONST_A_NAME);
388 
389         if (movementData.getMovementBoneData(boneName)) {
390             continue;
391         }
392 
393         var boneData = armatureData.getBoneData(boneName);
394         var parentName = boneData.parentName;
395 
396         var parentXML = null;
397         if (parentName != "") {
398             for (var j = 0; j < movBonesXml.length; j++) {
399                 parentXML = movBonesXml[j];
400                 if (parentName == parentXML.getAttribute(ccs.CONST_A_NAME)) {
401                     break;
402                 }
403             }
404         }
405         var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData, dataInfo);
406         movementData.addMovementBoneData(moveBoneData);
407     }
408     return movementData;
409 };
410 
411 ccs.DataReaderHelper.decodeMovementBone = function (movBoneXml, parentXml, boneData, dataInfo) {
412     var movBoneData = new ccs.MovementBoneData();
413     var scale, delay;
414 
415     if (movBoneXml) {
416         scale = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_SCALE)) || 0;
417         movBoneData.scale = scale;
418 
419         delay = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_DELAY)) || 0;
420         if (delay > 0) {
421             delay -= 1;
422         }
423         movBoneData.delay = delay;
424     }
425 
426     var length = 0;
427     var parentTotalDuration = 0;
428     var currentDuration = 0;
429     var parentFrameXML = null;
430     var parentXMLList = [];
431 
432     //*  get the parent frame xml list, we need get the origin data
433     if (parentXml != null) {
434         var parentFramesXML = parentXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
435         for (var i = 0; i < parentFramesXML.length; i++) {
436             parentXMLList.push(parentFramesXML[i]);
437         }
438         length = parentXMLList.length;
439     }
440 
441 
442     var totalDuration = 0;
443 
444     var name = movBoneXml.getAttribute(ccs.CONST_A_NAME);
445     movBoneData.name = name;
446     var framesXML = movBoneXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
447     var j = 0;
448     for (var ii = 0; ii < framesXML.length; ii++) {
449         var frameXML = framesXML[ii];
450         if (parentXml) {
451             //*  in this loop we get the corresponding parent frame xml
452             while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
453                 parentFrameXML = parentXMLList[j];
454                 parentTotalDuration += currentDuration;
455                 currentDuration = parseFloat(parentFrameXML.getAttribute(ccs.CONST_A_DURATION));
456                 j++;
457             }
458         }
459         var frameData = this.decodeFrame(frameXML, parentFrameXML, boneData, dataInfo);
460         movBoneData.addFrameData(frameData);
461         frameData.frameID = totalDuration;
462         totalDuration += frameData.duration;
463         movBoneData.duration = totalDuration;
464     }
465 
466     //Change rotation range from (-180 -- 180) to (-infinity -- infinity)
467     var frames = movBoneData.frameList;
468     var pi = Math.PI;
469     for (var i = frames.length - 1; i >= 0; i--) {
470         if (i > 0) {
471             var difSkewX = frames[i].skewX - frames[i - 1].skewX;
472             var difSkewY = frames[i].skewY - frames[i - 1].skewY;
473 
474             if (difSkewX < -pi || difSkewX > pi) {
475                 frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
476             }
477 
478             if (difSkewY < -pi || difSkewY > pi) {
479                 frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
480             }
481         }
482     }
483 
484     if(movBoneData.frameList.length>0){
485         var frameData = new ccs.FrameData();
486         frameData.copy(movBoneData.frameList[movBoneData.frameList.length-1]);
487         frameData.frameID = movBoneData.duration;
488         movBoneData.addFrameData(frameData);
489     }
490     return movBoneData;
491 };
492 
493 ccs.DataReaderHelper.decodeFrame = function (frameXML, parentFrameXml, boneData, dataInfo) {
494     var frameData = new ccs.FrameData();
495     frameData.movement = frameXML.getAttribute(ccs.CONST_A_MOVEMENT) || "";
496     frameData.event = frameXML.getAttribute(ccs.CONST_A_EVENT) || "";
497     frameData.blendType = parseInt(frameXML.getAttribute(ccs.CONST_A_BLEND_TYPE)) || ccs.BlendType.normal;
498 
499     var blendFunc = frameData.blendFunc;
500     switch (frameData.blendType) {
501         case ccs.BlendType.normal:
502             blendFunc.src = cc.BLEND_SRC;
503             blendFunc.dst = cc.BLEND_DST;
504             break;
505         case ccs.BlendType.add:
506             blendFunc.src = gl.SRC_ALPHA;
507             blendFunc.dst = gl.ONE;
508             break;
509         case ccs.BlendType.multiply:
510             blendFunc.src = gl.ONE_MINUS_SRC_ALPHA;
511             blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
512             break;
513         case ccs.BlendType.screen:
514             blendFunc.src = gl.ONE;
515             blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
516             break;
517         default:
518             break;
519     }
520 
521     frameData.sound = frameXML.getAttribute(ccs.CONST_A_SOUND) || "";
522     frameData.soundEffect = frameXML.getAttribute(ccs.CONST_A_SOUND_EFFECT) || "";
523 
524     var isTween = frameXML.getAttribute(ccs.CONST_A_TWEEN_FRAME);
525     if(isTween == null)
526         isTween = true;
527     frameData.isTween = Boolean(isTween);
528 
529     if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
530         frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
531         frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
532     }
533     else {
534         frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_X)) || 0;
535         frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_Y)) || 0;
536     }
537     frameData.x *= this._positionReadScale;
538     frameData.y *= this._positionReadScale;
539     frameData.scaleX = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_X)) || 0;
540     frameData.scaleY = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_Y)) || 0;
541     frameData.skewX = cc.DEGREES_TO_RADIANS(parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_X)) || 0);
542     frameData.skewY = cc.DEGREES_TO_RADIANS(-parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_Y)) || 0);
543     frameData.duration = parseFloat(frameXML.getAttribute(ccs.CONST_A_DURATION)) || 0;
544     frameData.displayIndex = parseFloat(frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX)) || 0;
545     frameData.zOrder = parseFloat(frameXML.getAttribute(ccs.CONST_A_Z)) || 0;
546     frameData.tweenRotate = parseFloat(frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATION)) || 0;
547 
548     var colorTransformXMLList = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
549     if (colorTransformXMLList.length > 0) {
550         var colorTransformXML = colorTransformXMLList[0];
551         var alpha = 0, red = 0, green = 0, blue = 0;
552         var alphaOffset = 0, redOffset = 0, greenOffset = 0, blueOffset = 100;
553 
554         alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || alpha;
555         red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || red;
556         green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || green;
557         blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || blue;
558 
559         var str_alphaOffset = colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET);
560         if(str_alphaOffset){
561             alphaOffset = parseFloat(str_alphaOffset);
562         }
563         var str_redOffset = colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET);
564         if(str_redOffset){
565             redOffset = parseFloat(str_redOffset);
566         }
567         var str_greenOffset = colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET);
568         if(str_redOffset){
569             greenOffset = parseFloat(str_greenOffset);
570         }
571         var str_blueOffset = colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET);
572         if(str_blueOffset){
573             blueOffset = parseFloat(str_blueOffset);
574         }
575 
576         frameData.a = 2.55 * alphaOffset + alpha;
577         frameData.r = 2.55 * redOffset + red;
578         frameData.g = 2.55 * greenOffset + green;
579         frameData.b = 2.55 * blueOffset + blue;
580 
581         frameData.isUseColorInfo = true;
582     }
583     if(frameData.displayIndex==-1){
584         frameData.a = 0;
585     }
586 
587     var tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
588     if (tweenEasing) {
589         if (tweenEasing != ccs.CONST_FL_NAN) {
590             frameData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
591         } else {
592             frameData.tweenEasing = ccs.TweenType.linear;
593         }
594     }
595 
596     if (parentFrameXml) {
597         //*  recalculate frame data from parent frame data, use for translate matrix
598         var helpNode = new ccs.BaseData();
599         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
600             helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
601             helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
602         }
603         else {
604             helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X)) || 0;
605             helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y)) || 0;
606         }
607         helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X)) || 0;
608         helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y)) || 0;
609 
610         helpNode.y = -helpNode.y;
611         helpNode.skewX = cc.DEGREES_TO_RADIANS(helpNode.skewX);
612         helpNode.skewY = cc.DEGREES_TO_RADIANS(-helpNode.skewY);
613         ccs.TransformHelp.transformFromParent(frameData, helpNode);
614     }
615     return frameData;
616 };
617 
618 ccs.DataReaderHelper.decodeTexture = function (textureXML , dataInfo) {
619     var textureData = new ccs.TextureData();
620     if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
621         textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
622     }
623     var px, py, width, height = 0;
624     if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
625         px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
626         py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
627     }
628     else {
629         px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
630         py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
631     }
632     width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
633     height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
634 
635     var anchorPointX = px / width;
636     var anchorPointY = (height - py) / height;
637 
638     textureData.pivotX = anchorPointX;
639     textureData.pivotY = anchorPointY;
640 
641     var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
642     for (var i = 0; i < contoursXML.length; i++) {
643         this.decodeContour(contoursXML[i], dataInfo);
644     }
645     return textureData;
646 };
647 
648 ccs.DataReaderHelper.decodeContour = function (contourXML, dataInfo) {
649     var contourData = new ccs.ContourData();
650     var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
651     var vertexDataXML;
652     for (var i = 0; i < vertexDatasXML.length; i++) {
653         vertexDataXML = vertexDatasXML[i];
654         var vertex = cc.p(0, 0);
655         vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
656         vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
657         //vertex.y = - vertex.y;//todo
658         contourData.vertexList.push(vertex);
659     }
660     return contourData;
661 
662 };
663 
664 ccs.DataReaderHelper.addDataFromJson = function (filePath,dataInfo,isLoadSpriteFrame) {
665     var fileContent = cc.FileUtils.getInstance().getTextFileData(filePath);
666     this.addDataFromJsonCache(fileContent,dataInfo,isLoadSpriteFrame);
667 };
668 ccs.DataReaderHelper.addDataFromJsonCache = function (content,dataInfo,isLoadSpriteFrame) {
669     var dic = JSON.parse(content);
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.getInstance().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.getInstance().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.getInstance().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.getInstance().addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
702         }
703     }
704 
705     armatureData = null;
706     animationData = null;
707 };
708 
709 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.decodeBoneDisplayFromJson = function (json, dataInfo) {
740     var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DisplayType.sprite;
741     var displayData = null;
742     switch (displayType) {
743         case ccs.DisplayType.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.DisplayType.armature:
768             displayData = new ccs.ArmatureDisplayData();
769             displayData.displayName = json[ccs.CONST_A_NAME] || "";
770             break;
771         case ccs.DisplayType.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.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 ccs.DataReaderHelper.removeConfigFile = function(configFile){
959     cc.ArrayRemoveObject(this._configFileList,configFile);
960 };