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 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  * @namespace
 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     /**
 79      * <p>
 80      *     Adds an animation from an NSDictionary<br/>
 81      *     Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
 82      * </p>
 83      * @param {object} dictionary
 84      * @param {String} plist
 85      */
 86     _addAnimationsWithDictionary:function (dictionary,plist) {
 87         var animations = dictionary["animations"];
 88         if (!animations) {
 89             cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary);
 90             return;
 91         }
 92 
 93         var version = 1;
 94         var properties = dictionary["properties"];
 95         if (properties) {
 96             version = (properties["format"] != null) ? parseInt(properties["format"]) : version;
 97             var spritesheets = properties["spritesheets"];
 98             var spriteFrameCache = cc.spriteFrameCache;
 99             var path = cc.path;
100             for (var i = 0; i < spritesheets.length; i++) {
101                 spriteFrameCache.addSpriteFrames(path.changeBasename(plist, spritesheets[i]));
102             }
103         }
104 
105         switch (version) {
106             case 1:
107                 this._parseVersion1(animations);
108                 break;
109             case 2:
110                 this._parseVersion2(animations);
111                 break;
112             default :
113                 cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary_2);
114                 break;
115         }
116     },
117 
118     /**
119      * <p>
120      *    Adds an animation from a plist file.<br/>
121      *    Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
122      * </p>
123      * @param {String} plist
124      */
125     addAnimations:function (plist) {
126 
127         cc.assert(plist, cc._LogInfos.animationCache_addAnimations_2);
128 
129         var dict = cc.loader.getRes(plist);
130 
131         if(!dict){
132             cc.log(cc._LogInfos.animationCache_addAnimations);
133             return;
134         }
135 
136         this._addAnimationsWithDictionary(dict,plist);
137     },
138 
139     _parseVersion1:function (animations) {
140         var frameCache = cc.spriteFrameCache;
141 
142         for (var key in animations) {
143             var animationDict = animations[key];
144             var frameNames = animationDict["frames"];
145             var delay = parseFloat(animationDict["delay"]) || 0;
146             var animation = null;
147             if (!frameNames) {
148                 cc.log(cc._LogInfos.animationCache__parseVersion1, key);
149                 continue;
150             }
151 
152             var frames = [];
153             for (var i = 0; i < frameNames.length; i++) {
154                 var spriteFrame = frameCache.getSpriteFrame(frameNames[i]);
155                 if (!spriteFrame) {
156                     cc.log(cc._LogInfos.animationCache__parseVersion1_2, key, frameNames[i]);
157                     continue;
158                 }
159                 var animFrame = new cc.AnimationFrame();
160                 animFrame.initWithSpriteFrame(spriteFrame, 1, null);
161                 frames.push(animFrame);
162             }
163 
164             if (frames.length === 0) {
165                 cc.log(cc._LogInfos.animationCache__parseVersion1_3, key);
166                 continue;
167             } else if (frames.length != frameNames.length) {
168                 cc.log(cc._LogInfos.animationCache__parseVersion1_4, key);
169             }
170             animation = cc.Animation.create(frames, delay, 1);
171             cc.animationCache.addAnimation(animation, key);
172         }
173     },
174 
175     _parseVersion2:function (animations) {
176         var frameCache = cc.spriteFrameCache;
177 
178         for (var key in animations) {
179             var animationDict = animations[key];
180 
181             var isLoop = animationDict["loop"];
182             var loopsTemp = parseInt(animationDict["loops"]);
183             var loops = isLoop ? cc.REPEAT_FOREVER : ((isNaN(loopsTemp)) ? 1 : loopsTemp);
184             var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false;
185             var frameArray = animationDict["frames"];
186 
187             if (!frameArray) {
188                 cc.log(cc._LogInfos.animationCache__parseVersion2, key);
189                 continue;
190             }
191 
192             //Array of AnimationFrames
193             var arr = [];
194             for (var i = 0; i < frameArray.length; i++) {
195                 var entry = frameArray[i];
196                 var spriteFrameName = entry["spriteframe"];
197                 var spriteFrame = frameCache.getSpriteFrame(spriteFrameName);
198                 if (!spriteFrame) {
199                     cc.log(cc._LogInfos.animationCache__parseVersion2_2, key, spriteFrameName);
200                     continue;
201                 }
202 
203                 var delayUnits = parseFloat(entry["delayUnits"]) || 0;
204                 var userInfo = entry["notification"];
205                 var animFrame = new cc.AnimationFrame();
206                 animFrame.initWithSpriteFrame(spriteFrame, delayUnits, userInfo);
207                 arr.push(animFrame);
208             }
209 
210             var delayPerUnit = parseFloat(animationDict["delayPerUnit"]) || 0;
211             var animation = new cc.Animation();
212             animation.initWithAnimationFrames(arr, delayPerUnit, loops);
213             animation.setRestoreOriginalFrame(restoreOriginalFrame);
214             cc.animationCache.addAnimation(animation, key);
215         }
216     },
217 
218 	_clear: function () {
219 		this._animations = {};
220 	}
221 };
222