1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * <p>
 29  *     cc.animationCache is a singleton object that manages the Animations.<br/>
 30  *     It saves in a cache the animations. You should use this class if you want to save your animations in a cache.<br/>
 31  * <br/>
 32  * example<br/>
 33  * cc.animationCache.addAnimation(animation,"animation1");<br/>
 34  * </p>
 35  * @class
 36  * @name cc.animationCache
 37  */
 38 cc.animationCache = /** @lends cc.animationCache# */{
 39 	_animations: {},
 40 
 41     /**
 42      * Adds a cc.Animation with a name.
 43      * @param {cc.Animation} animation
 44      * @param {String} name
 45      */
 46     addAnimation:function (animation, name) {
 47         this._animations[name] = animation;
 48     },
 49 
 50     /**
 51      * Deletes a cc.Animation from the cache.
 52      * @param {String} name
 53      */
 54     removeAnimation:function (name) {
 55         if (!name) {
 56             return;
 57         }
 58         if (this._animations[name]) {
 59             delete this._animations[name];
 60         }
 61     },
 62 
 63     /**
 64      * <p>
 65      *     Returns a cc.Animation that was previously added.<br/>
 66      *      If the name is not found it will return nil.<br/>
 67      *      You should retain the returned copy if you are going to use it.</br>
 68      * </p>
 69      * @param {String} name
 70      * @return {cc.Animation}
 71      */
 72     getAnimation:function (name) {
 73         if (this._animations[name])
 74             return this._animations[name];
 75         return null;
 76     },
 77 
 78     _addAnimationsWithDictionary:function (dictionary,plist) {
 79         var animations = dictionary["animations"];
 80         if (!animations) {
 81             cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary);
 82             return;
 83         }
 84 
 85         var version = 1;
 86         var properties = dictionary["properties"];
 87         if (properties) {
 88             version = (properties["format"] != null) ? parseInt(properties["format"]) : version;
 89             var spritesheets = properties["spritesheets"];
 90             var spriteFrameCache = cc.spriteFrameCache;
 91             var path = cc.path;
 92             for (var i = 0; i < spritesheets.length; i++) {
 93                 spriteFrameCache.addSpriteFrames(path.changeBasename(plist, spritesheets[i]));
 94             }
 95         }
 96 
 97         switch (version) {
 98             case 1:
 99                 this._parseVersion1(animations);
100                 break;
101             case 2:
102                 this._parseVersion2(animations);
103                 break;
104             default :
105                 cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary_2);
106                 break;
107         }
108     },
109 
110     /**
111      * <p>
112      *    Adds an animations from a plist file.<br/>
113      *    Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
114      * </p>
115      * @param {String} plist
116      */
117     addAnimations:function (plist) {
118 
119         cc.assert(plist, cc._LogInfos.animationCache_addAnimations_2);
120 
121         var dict = cc.loader.getRes(plist);
122 
123         if(!dict){
124             cc.log(cc._LogInfos.animationCache_addAnimations);
125             return;
126         }
127 
128         this._addAnimationsWithDictionary(dict,plist);
129     },
130 
131     _parseVersion1:function (animations) {
132         var frameCache = cc.spriteFrameCache;
133 
134         for (var key in animations) {
135             var animationDict = animations[key];
136             var frameNames = animationDict["frames"];
137             var delay = parseFloat(animationDict["delay"]) || 0;
138             var animation = null;
139             if (!frameNames) {
140                 cc.log(cc._LogInfos.animationCache__parseVersion1, key);
141                 continue;
142             }
143 
144             var frames = [];
145             for (var i = 0; i < frameNames.length; i++) {
146                 var spriteFrame = frameCache.getSpriteFrame(frameNames[i]);
147                 if (!spriteFrame) {
148                     cc.log(cc._LogInfos.animationCache__parseVersion1_2, key, frameNames[i]);
149                     continue;
150                 }
151                 var animFrame = new cc.AnimationFrame();
152                 animFrame.initWithSpriteFrame(spriteFrame, 1, null);
153                 frames.push(animFrame);
154             }
155 
156             if (frames.length === 0) {
157                 cc.log(cc._LogInfos.animationCache__parseVersion1_3, key);
158                 continue;
159             } else if (frames.length != frameNames.length) {
160                 cc.log(cc._LogInfos.animationCache__parseVersion1_4, key);
161             }
162             animation = cc.Animation.create(frames, delay, 1);
163             cc.animationCache.addAnimation(animation, key);
164         }
165     },
166 
167     _parseVersion2:function (animations) {
168         var frameCache = cc.spriteFrameCache;
169 
170         for (var key in animations) {
171             var animationDict = animations[key];
172 
173             var isLoop = animationDict["loop"];
174             var loopsTemp = parseInt(animationDict["loops"]);
175             var loops = isLoop ? cc.REPEAT_FOREVER : ((isNaN(loopsTemp)) ? 1 : loopsTemp);
176             var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false;
177             var frameArray = animationDict["frames"];
178 
179             if (!frameArray) {
180                 cc.log(cc._LogInfos.animationCache__parseVersion2, key);
181                 continue;
182             }
183 
184             //Array of AnimationFrames
185             var arr = [];
186             for (var i = 0; i < frameArray.length; i++) {
187                 var entry = frameArray[i];
188                 var spriteFrameName = entry["spriteframe"];
189                 var spriteFrame = frameCache.getSpriteFrame(spriteFrameName);
190                 if (!spriteFrame) {
191                     cc.log(cc._LogInfos.animationCache__parseVersion2_2, key, spriteFrameName);
192                     continue;
193                 }
194 
195                 var delayUnits = parseFloat(entry["delayUnits"]) || 0;
196                 var userInfo = entry["notification"];
197                 var animFrame = new cc.AnimationFrame();
198                 animFrame.initWithSpriteFrame(spriteFrame, delayUnits, userInfo);
199                 arr.push(animFrame);
200             }
201 
202             var delayPerUnit = parseFloat(animationDict["delayPerUnit"]) || 0;
203             var animation = new cc.Animation();
204             animation.initWithAnimationFrames(arr, delayPerUnit, loops);
205             animation.setRestoreOriginalFrame(restoreOriginalFrame);
206             cc.animationCache.addAnimation(animation, key);
207         }
208     },
209 
210 	_clear: function () {
211 		this._animations = {};
212 	}
213 };
214