1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga 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  * @namespace
 29  * <p>
 30  *     Singleton that manages the Animations.<br/>
 31  *     It saves in a cache the animations. You should use this class if you want to save your animations in a cache.<br/>
 32  * <br/>
 33  * example<br/>
 34  * cc.animationCache.addAnimation(animation,"animation1");<br/>
 35  * </p>
 36  */
 37 cc.animationCache = /** @lends cc.animationCache# */{
 38 	_animations: {},
 39 
 40     /**
 41      * Adds a cc.Animation with a name.
 42      * @param {cc.Animation} animation
 43      * @param {String} name
 44      */
 45     addAnimation:function (animation, name) {
 46         this._animations[name] = animation;
 47     },
 48 
 49     /**
 50      *  Deletes a cc.Animation from the cache.
 51      * @param  {String} name
 52      */
 53     removeAnimation:function (name) {
 54         if (!name) {
 55             return;
 56         }
 57         if (this._animations[name]) {
 58             delete this._animations[name];
 59         }
 60     },
 61 
 62     /**
 63      * <p>
 64      *     Returns a cc.Animation that was previously added.<br/>
 65      *      If the name is not found it will return nil.<br/>
 66      *      You should retain the returned copy if you are going to use it.</br>
 67      * </p>
 68      * @param {String} name
 69      * @return {cc.Animation}
 70      */
 71     getAnimation:function (name) {
 72         if (this._animations[name])
 73             return this._animations[name];
 74         return null;
 75     },
 76 
 77     /**
 78      * <p>
 79      *     Adds an animation from an NSDictionary<br/>
 80      *     Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
 81      * </p>
 82      * @param {object} dictionary
 83      * @param {String} plist
 84      */
 85     _addAnimationsWithDictionary:function (dictionary,plist) {
 86         var animations = dictionary["animations"];
 87         if (!animations) {
 88             cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary);
 89             return;
 90         }
 91 
 92         var version = 1;
 93         var properties = dictionary["properties"];
 94         if (properties) {
 95             version = (properties["format"] != null) ? parseInt(properties["format"]) : version;
 96             var spritesheets = properties["spritesheets"];
 97             var spriteFrameCache = cc.spriteFrameCache;
 98             var path = cc.path;
 99             for (var i = 0; i < spritesheets.length; i++) {
100                 spriteFrameCache.addSpriteFrames(path.changeBasename(plist, spritesheets[i]));
101             }
102         }
103 
104         switch (version) {
105             case 1:
106                 this._parseVersion1(animations);
107                 break;
108             case 2:
109                 this._parseVersion2(animations);
110                 break;
111             default :
112                 cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary_2);
113                 break;
114         }
115     },
116 
117     /**
118      * <p>
119      *    Adds an animation from a plist file.<br/>
120      *    Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
121      * </p>
122      * @param {String} plist
123      */
124     addAnimations:function (plist) {
125 
126         cc.assert(plist, cc._LogInfos.animationCache_addAnimations_2);
127 
128         var dict = cc.loader.getRes(plist);
129 
130         if(!dict){
131             cc.log(cc._LogInfos.animationCache_addAnimations);
132             return;
133         }
134 
135         this._addAnimationsWithDictionary(dict,plist);
136     },
137 
138     _parseVersion1:function (animations) {
139         var frameCache = cc.spriteFrameCache;
140 
141         for (var key in animations) {
142             var animationDict = animations[key];
143             var frameNames = animationDict["frames"];
144             var delay = parseFloat(animationDict["delay"]) || 0;
145             var animation = null;
146             if (!frameNames) {
147                 cc.log(cc._LogInfos.animationCache__parseVersion1, key);
148                 continue;
149             }
150 
151             var frames = [];
152             for (var i = 0; i < frameNames.length; i++) {
153                 var spriteFrame = frameCache.getSpriteFrame(frameNames[i]);
154                 if (!spriteFrame) {
155                     cc.log(cc._LogInfos.animationCache__parseVersion1_2, key, frameNames[i]);
156                     continue;
157                 }
158                 var animFrame = new cc.AnimationFrame();
159                 animFrame.initWithSpriteFrame(spriteFrame, 1, null);
160                 frames.push(animFrame);
161             }
162 
163             if (frames.length === 0) {
164                 cc.log(cc._LogInfos.animationCache__parseVersion1_3, key);
165                 continue;
166             } else if (frames.length != frameNames.length) {
167                 cc.log(cc._LogInfos.animationCache__parseVersion1_4, key);
168             }
169             animation = cc.Animation.create(frames, delay, 1);
170             cc.animationCache.addAnimation(animation, key);
171         }
172     },
173 
174     _parseVersion2:function (animations) {
175         var frameCache = cc.spriteFrameCache;
176 
177         for (var key in animations) {
178             var animationDict = animations[key];
179 
180             var isLoop = animationDict["loop"];
181             var loopsTemp = parseInt(animationDict["loops"]);
182             var loops = isLoop ? cc.REPEAT_FOREVER : ((isNaN(loopsTemp)) ? 1 : loopsTemp);
183             var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false;
184             var frameArray = animationDict["frames"];
185 
186             if (!frameArray) {
187                 cc.log(cc._LogInfos.animationCache__parseVersion2, key);
188                 continue;
189             }
190 
191             //Array of AnimationFrames
192             var arr = [];
193             for (var i = 0; i < frameArray.length; i++) {
194                 var entry = frameArray[i];
195                 var spriteFrameName = entry["spriteframe"];
196                 var spriteFrame = frameCache.getSpriteFrame(spriteFrameName);
197                 if (!spriteFrame) {
198                     cc.log(cc._LogInfos.animationCache__parseVersion2_2, key, spriteFrameName);
199                     continue;
200                 }
201 
202                 var delayUnits = parseFloat(entry["delayUnits"]) || 0;
203                 var userInfo = entry["notification"];
204                 var animFrame = new cc.AnimationFrame();
205                 animFrame.initWithSpriteFrame(spriteFrame, delayUnits, userInfo);
206                 arr.push(animFrame);
207             }
208 
209             var delayPerUnit = parseFloat(animationDict["delayPerUnit"]) || 0;
210             var animation = new cc.Animation();
211             animation.initWithAnimationFrames(arr, delayPerUnit, loops);
212             animation.setRestoreOriginalFrame(restoreOriginalFrame);
213             cc.animationCache.addAnimation(animation, key);
214         }
215     },
216 
217 	_clear: function () {
218 		this._animations = {};
219 	}
220 };
221