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) || true;
525     frameData.isTween = Boolean(isTween);
526 
527     if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
528         frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
529         frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
530     }
531     else {
532         frameData.x = parseFloat(frameXML.getAttribute(ccs.CONST_A_X)) || 0;
533         frameData.y = -parseFloat(frameXML.getAttribute(ccs.CONST_A_Y)) || 0;
534     }
535     frameData.x *= this._positionReadScale;
536     frameData.y *= this._positionReadScale;
537     frameData.scaleX = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_X)) || 0;
538     frameData.scaleY = parseFloat(frameXML.getAttribute(ccs.CONST_A_SCALE_Y)) || 0;
539     frameData.skewX = cc.DEGREES_TO_RADIANS(parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_X)) || 0);
540     frameData.skewY = cc.DEGREES_TO_RADIANS(-parseFloat(frameXML.getAttribute(ccs.CONST_A_SKEW_Y)) || 0);
541     frameData.duration = parseFloat(frameXML.getAttribute(ccs.CONST_A_DURATION)) || 0;
542     frameData.displayIndex = parseFloat(frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX)) || 0;
543     frameData.zOrder = parseFloat(frameXML.getAttribute(ccs.CONST_A_Z)) || 0;
544     frameData.tweenRotate = parseFloat(frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATION)) || 0;
545 
546     var colorTransformXMLList = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
547     if (colorTransformXMLList.length > 0) {
548         var colorTransformXML = colorTransformXMLList[0];
549         var alpha = red = green = blue = 0;
550         var alphaOffset = redOffset = greenOffset = blueOffset = 100;
551 
552         alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || alpha;
553         red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || red;
554         green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || green;
555         blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || blue;
556 
557         var str_alphaOffset = colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET);
558         if(str_alphaOffset){
559             alphaOffset = parseFloat(str_alphaOffset);
560         }
561         var str_redOffset = colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET);
562         if(str_redOffset){
563             redOffset = parseFloat(str_redOffset);
564         }
565         var str_greenOffset = colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET);
566         if(str_redOffset){
567             greenOffset = parseFloat(str_greenOffset);
568         }
569         var str_blueOffset = colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET);
570         if(str_blueOffset){
571             blueOffset = parseFloat(str_blueOffset);
572         }
573 
574         frameData.a = 2.55 * alphaOffset + alpha;
575         frameData.r = 2.55 * redOffset + red;
576         frameData.g = 2.55 * greenOffset + green;
577         frameData.b = 2.55 * blueOffset + blue;
578 
579         frameData.isUseColorInfo = true;
580     }
581     if(frameData.displayIndex==-1){
582         frameData.a = 0;
583     }
584 
585     var tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
586     if (tweenEasing) {
587         if (tweenEasing != ccs.CONST_FL_NAN) {
588             frameData.tweenEasing = tweenEasing == 2 ? ccs.TweenType.sineEaseInOut : tweenEasing;
589         } else {
590             frameData.tweenEasing = ccs.TweenType.linear;
591         }
592     }
593 
594     if (parentFrameXml) {
595         //*  recalculate frame data from parent frame data, use for translate matrix
596         var helpNode = new ccs.BaseData();
597         if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
598             helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X)) || 0;
599             helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y)) || 0;
600         }
601         else {
602             helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X)) || 0;
603             helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y)) || 0;
604         }
605         helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X)) || 0;
606         helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y)) || 0;
607 
608         helpNode.y = -helpNode.y;
609         helpNode.skewX = cc.DEGREES_TO_RADIANS(helpNode.skewX);
610         helpNode.skewY = cc.DEGREES_TO_RADIANS(-helpNode.skewY);
611         ccs.TransformHelp.transformFromParent(frameData, helpNode);
612     }
613     return frameData;
614 };
615 
616 ccs.DataReaderHelper.decodeTexture = function (textureXML , dataInfo) {
617     var textureData = new ccs.TextureData();
618     if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
619         textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
620     }
621     var px, py, width, height = 0;
622     if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
623         px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
624         py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
625     }
626     else {
627         px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
628         py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
629     }
630     width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
631     height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
632 
633     var anchorPointX = px / width;
634     var anchorPointY = (height - py) / height;
635 
636     textureData.pivotX = anchorPointX;
637     textureData.pivotY = anchorPointY;
638 
639     var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
640     for (var i = 0; i < contoursXML.length; i++) {
641         this.decodeContour(contoursXML[i], dataInfo);
642     }
643     return textureData;
644 };
645 
646 ccs.DataReaderHelper.decodeContour = function (contourXML, dataInfo) {
647     var contourData = new ccs.ContourData();
648     var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
649     var vertexDataXML;
650     for (var i = 0; i < vertexDatasXML.length; i++) {
651         vertexDataXML = vertexDatasXML[i];
652         var vertex = cc.p(0, 0);
653         vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
654         vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
655         //vertex.y = - vertex.y;//todo
656         contourData.vertexList.push(vertex);
657     }
658     return contourData;
659 
660 };
661 
662 ccs.DataReaderHelper.addDataFromJson = function (filePath,dataInfo,isLoadSpriteFrame) {
663     var fileContent = cc.FileUtils.getInstance().getTextFileData(filePath);
664     this.addDataFromJsonCache(fileContent,dataInfo,isLoadSpriteFrame);
665 };
666 ccs.DataReaderHelper.addDataFromJsonCache = function (content,dataInfo,isLoadSpriteFrame) {
667     var dic = JSON.parse(content);
668     dataInfo.contentScale = dic[ccs.CONST_CONTENT_SCALE]||1;
669     var armatureDataArr = dic[ccs.CONST_ARMATURE_DATA] || [];
670     var armatureData;
671     for (var i = 0; i < armatureDataArr.length; i++) {
672         armatureData = this.decodeArmatureFromJSON(armatureDataArr[i], dataInfo);
673         ccs.ArmatureDataManager.getInstance().addArmatureData(armatureData.name, armatureData, dataInfo.filename);
674     }
675 
676     var animationDataArr = dic[ccs.CONST_ANIMATION_DATA] || [];
677     var animationData;
678     for (var i = 0; i < animationDataArr.length; i++) {
679         animationData = this.decodeAnimationFromJson(animationDataArr[i], dataInfo);
680         ccs.ArmatureDataManager.getInstance().addAnimationData(animationData.name, animationData, dataInfo.filename);
681     }
682 
683     var textureDataArr = dic[ccs.CONST_TEXTURE_DATA] || [];
684     var textureData;
685     for (var i = 0; i < textureDataArr.length; i++) {
686         textureData = this.decodeTextureFromJson(textureDataArr[i], dataInfo);
687         ccs.ArmatureDataManager.getInstance().addTextureData(textureData.name, textureData, dataInfo.filename);
688     }
689 
690     if (isLoadSpriteFrame) {
691         var configFiles = dic[ccs.CONST_CONFIG_FILE_PATH] || [];
692         var locFilePath, locPos, locPlistPath, locImagePath;
693         for (var i = 0; i < configFiles.length; i++) {
694             locFilePath = configFiles[i];
695             locPos = locFilePath.lastIndexOf(".");
696             locFilePath = locFilePath.substring(0, locPos);
697             locPlistPath = dataInfo.basefilePath + locFilePath + ".plist";
698             locImagePath = dataInfo.basefilePath + locFilePath + ".png";
699             ccs.ArmatureDataManager.getInstance().addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
700         }
701     }
702 
703     armatureData = null;
704     animationData = null;
705 };
706 
707 ccs.DataReaderHelper.decodeArmatureFromJSON = function (json, dataInfo) {
708     var armatureData = new ccs.ArmatureData();
709 
710     var name = json[ccs.CONST_A_NAME];
711     if (name) {
712         armatureData.name = name;
713     }
714 
715     dataInfo.cocoStudioVersion = armatureData.dataVersion = json[ccs.CONST_VERSION] || 0.1;
716 
717     var boneDataList = json[ccs.CONST_BONE_DATA];
718     for (var i = 0; i < boneDataList.length; i++) {
719         armatureData.addBoneData(this.decodeBoneFromJson(boneDataList[i],dataInfo));
720     }
721     return armatureData;
722 };
723 
724 ccs.DataReaderHelper.decodeBoneFromJson = function (json, dataInfo) {
725     var boneData = new ccs.BoneData();
726     this.decodeNodeFromJson(boneData, json, dataInfo);
727     boneData.name = json[ccs.CONST_A_NAME] || "";
728     boneData.parentName = json[ccs.CONST_A_PARENT] || "";
729     var displayDataList = json[ccs.CONST_DISPLAY_DATA] || [];
730     for (var i = 0; i < displayDataList.length; i++) {
731         var locDisplayData = this.decodeBoneDisplayFromJson(displayDataList[i], dataInfo);
732         boneData.addDisplayData(locDisplayData);
733     }
734     return boneData;
735 };
736 
737 ccs.DataReaderHelper.decodeBoneDisplayFromJson = function (json, dataInfo) {
738     var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DisplayType.sprite;
739     var displayData = null;
740     switch (displayType) {
741         case ccs.DisplayType.sprite:
742             displayData = new ccs.SpriteDisplayData();
743             displayData.displayName = json[ccs.CONST_A_NAME] || "";
744 
745             var dicArray = json[ccs.CONST_SKIN_DATA]|| [];
746             var dic = dicArray[0];
747             if(dic){
748                 var skinData = displayData.skinData;
749                 skinData.x = (dic[ccs.CONST_A_X]|| 0) * this._positionReadScale;
750                 skinData.y = (dic[ccs.CONST_A_Y]||0) * this._positionReadScale;
751                 if(dic.hasOwnProperty(ccs.CONST_A_SCALE_X)){
752                     skinData.scaleX = dic[ccs.CONST_A_SCALE_X];
753                 }
754                 if(dic.hasOwnProperty(ccs.CONST_A_SCALE_Y)){
755                     skinData.scaleY = dic[ccs.CONST_A_SCALE_Y];
756                 }
757                 skinData.skewX = dic[ccs.CONST_A_SKEW_X]|| 0;
758                 skinData.skewY = dic[ccs.CONST_A_SKEW_Y]||0;
759 
760                 skinData.x *= dataInfo.contentScale;
761                 skinData.y *= dataInfo.contentScale;
762                 dic = null;
763             }
764             break;
765         case ccs.DisplayType.armature:
766             displayData = new ccs.ArmatureDisplayData();
767             displayData.displayName = json[ccs.CONST_A_NAME] || "";
768             break;
769         case ccs.DisplayType.particle:
770             displayData = new ccs.ParticleDisplayData();
771             displayData.displayName = dataInfo.basefilePath + json[ccs.CONST_A_PLIST] || "";
772             break;
773         default:
774             displayData = new ccs.SpriteDisplayData();
775             break;
776     }
777 
778     displayData.displayType = displayType;
779 
780     return displayData;
781 };
782 
783 ccs.DataReaderHelper.decodeAnimationFromJson = function (json, dataInfo) {
784     var aniData = new ccs.AnimationData();
785     aniData.name = json[ccs.CONST_A_NAME] || "";
786     var movementDataList = json[ccs.CONST_MOVEMENT_DATA] || [];
787     for (var i = 0; i < movementDataList.length; i++) {
788         var locMovementData = this.decodeMovementFromJson(movementDataList[i], dataInfo);
789         aniData.addMovement(locMovementData);
790     }
791     return aniData;
792 };
793 
794 ccs.DataReaderHelper.decodeMovementFromJson = function (json, dataInfo) {
795     var movementData = new ccs.MovementData();
796 
797     movementData.loop = json[ccs.CONST_A_LOOP] || false;
798     movementData.durationTween = json[ccs.CONST_A_DURATION_TWEEN] || 0;
799     movementData.durationTo = json[ccs.CONST_A_DURATION_TO] || 0;
800     movementData.duration = json[ccs.CONST_A_DURATION] || 0;
801     if(json.hasOwnProperty(ccs.CONST_A_MOVEMENT_SCALE)){
802         movementData.scale = json[ccs.CONST_A_MOVEMENT_SCALE]
803     }
804     movementData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.linear;
805     movementData.name = json[ccs.CONST_A_NAME] || "";
806 
807     var movementBoneList = json[ccs.CONST_MOVEMENT_BONE_DATA] || [];
808     for (var i = 0; i < movementBoneList.length; i++) {
809         var locMovementBoneData = this.decodeMovementBoneFromJson(movementBoneList[i], dataInfo);
810         movementData.addMovementBoneData(locMovementBoneData);
811     }
812     return movementData;
813 };
814 
815 ccs.DataReaderHelper.decodeMovementBoneFromJson = function (json, dataInfo) {
816     var movementBoneData = new ccs.MovementBoneData();
817     movementBoneData.delay = json[ccs.CONST_A_MOVEMENT_DELAY] || 0;
818     if(json.hasOwnProperty(ccs.CONST_A_MOVEMENT_SCALE)){
819         movementBoneData.scale = json[ccs.CONST_A_MOVEMENT_SCALE];
820     }
821 
822     movementBoneData.name = json[ccs.CONST_A_NAME] || "";
823     var frameDataList = json[ccs.CONST_FRAME_DATA] || [];
824     for (var i = 0; i < frameDataList.length; i++) {
825         var frameData = this.decodeFrameFromJson(frameDataList[i], dataInfo);
826         movementBoneData.addFrameData(frameData);
827         if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
828             frameData.frameID = movementBoneData.duration;
829             movementBoneData.duration += frameData.duration;
830         }
831     }
832 
833     if (dataInfo.cocoStudioVersion < ccs.VERSION_CHANGE_ROTATION_RANGE) {
834         //! Change rotation range from (-180 -- 180) to (-infinity -- infinity)
835         var frames = movementBoneData.frameList;
836         var pi = Math.PI;
837         for (var i = frames.length - 1; i >= 0; i--) {
838             if (i > 0) {
839                 var difSkewX = frames[i].skewX - frames[i - 1].skewX;
840                 var difSkewY = frames[i].skewY - frames[i - 1].skewY;
841 
842                 if (difSkewX < -pi || difSkewX > pi) {
843                     frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
844                 }
845 
846                 if (difSkewY < -pi || difSkewY > pi) {
847                     frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
848                 }
849             }
850         }
851     }
852 
853     if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
854         if (movementBoneData.frameList.length > 0) {
855             var frameData = new ccs.FrameData();
856             frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
857             movementBoneData.addFrameData(frameData);
858             frameData.frameID = movementBoneData.duration;
859         }
860     }
861     return movementBoneData;
862 };
863 
864 ccs.DataReaderHelper.decodeFrameFromJson = function (json, dataInfo) {
865     var frameData = new ccs.FrameData();
866     this.decodeNodeFromJson(frameData, json, dataInfo);
867     frameData.duration = json[ccs.CONST_A_DURATION] || 0;
868     frameData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.linear;
869     frameData.displayIndex = json[ccs.CONST_A_DISPLAY_INDEX] || 0;
870 
871     var bd_src = json[ccs.CONST_A_BLEND_SRC] || cc.BLEND_SRC;
872     var bd_dst = json[ccs.CONST_A_BLEND_DST] || cc.BLEND_DST;
873     frameData.blendFunc.src = bd_src;
874     frameData.blendFunc.dst = bd_dst;
875 
876     frameData.event = json[ccs.CONST_A_EVENT] || null;
877     if(json.hasOwnProperty(ccs.CONST_A_TWEEN_FRAME)){
878         frameData.isTween = json[ccs.CONST_A_TWEEN_FRAME]
879     }
880     if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED)
881         frameData.duration = json[ccs.CONST_A_DURATION] || 0;
882     else
883         frameData.frameID = json[ccs.CONST_A_FRAME_INDEX] || 0;
884 
885     var twEPs = json[ccs.CONST_A_EASING_PARAM] || [];
886     for (var i = 0; i < twEPs.length; i++) {
887         var twEP = twEPs[i];
888         frameData.easingParams[i] = twEP;
889     }
890 
891     return frameData;
892 };
893 
894 ccs.DataReaderHelper.decodeTextureFromJson = function (json) {
895     var textureData = new ccs.TextureData();
896     textureData.name = json[ccs.CONST_A_NAME] || "";
897     textureData.width = json[ccs.CONST_A_WIDTH] || 0;
898     textureData.height = json[ccs.CONST_A_HEIGHT] || 0;
899     textureData.pivotX = json[ccs.CONST_A_PIVOT_X] || 0;
900     textureData.pivotY = json[ccs.CONST_A_PIVOT_Y] || 0;
901 
902     var contourDataList = json[ccs.CONST_CONTOUR_DATA] || [];
903     for (var i = 0; i < contourDataList.length; i++) {
904         var locContourData = this.decodeContourFromJson(contourDataList[i]);
905         textureData.contourDataList.push(locContourData);
906     }
907     return textureData;
908 };
909 
910 ccs.DataReaderHelper.decodeContourFromJson = function (json) {
911     var contourData = new ccs.ContourData();
912     var vertexPointList = json[ccs.CONST_VERTEX_POINT] || [];
913     for (var i = 0; i < vertexPointList.length; i++) {
914         var dic = vertexPointList[i];
915         var vertex = cc.p(0, 0);
916         vertex.x = dic[ccs.CONST_A_X] || 0;
917         vertex.y = dic[ccs.CONST_A_Y] || 0;
918         contourData.vertexList.push(vertex);
919     }
920     return contourData;
921 };
922 
923 ccs.DataReaderHelper.decodeNodeFromJson = function (node, json, dataInfo) {
924     node.x = json[ccs.CONST_A_X] || 0 ;
925     node.y = json[ccs.CONST_A_Y] || 0;
926 
927     node.x *= dataInfo.contentScale;
928     node.y *= dataInfo.contentScale;
929     
930     node.zOrder = json[ccs.CONST_A_Z] || 0;
931 
932     node.skewX = json[ccs.CONST_A_SKEW_X] || 0;
933     node.skewY = json[ccs.CONST_A_SKEW_Y] || 0;
934     if(json.hasOwnProperty(ccs.CONST_A_SCALE_X)){
935         node.scaleX = json[ccs.CONST_A_SCALE_X];
936     }
937     if(json.hasOwnProperty(ccs.CONST_A_SCALE_Y)){
938         node.scaleY = json[ccs.CONST_A_SCALE_Y];
939     }
940 
941     var colorDic = json[ccs.CONST_COLOR_INFO] || null;
942     if (colorDic) {
943         //compatible old version
944         if(dataInfo.cocoStudioVersion<ccs.VERSION_COLOR_READING){
945             colorDic = colorDic[0];
946         }
947         node.a = colorDic[ccs.CONST_A_ALPHA];
948         node.r = colorDic[ccs.CONST_A_RED];
949         node.g = colorDic[ccs.CONST_A_GREEN];
950         node.b = colorDic[ccs.CONST_A_BLUE];
951         node.isUseColorInfo = true;
952         delete colorDic;
953     }
954 };
955 
956 ccs.DataReaderHelper.removeConfigFile = function(configFile){
957     cc.ArrayRemoveObject(this._configFileList,configFile);
958 };