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 * <p> 29 * 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 * </p> 32 * @class 33 * @extends cc.Class 34 * 35 * @example 36 * cc.AnimationCache.getInstance().addAnimation(animation,"animation1"); 37 */ 38 cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{ 39 /** 40 * Adds a cc.Animation with a name. 41 * @param {cc.Animation} animation 42 * @param {String} name 43 */ 44 addAnimation:function (animation, name) { 45 this._animations[name] = animation; 46 }, 47 48 /** 49 * Deletes a cc.Animation from the cache. 50 * @param {String} name 51 */ 52 removeAnimation:function (name) { 53 if (!name) { 54 return; 55 } 56 if (this._animations.hasOwnProperty(name)) { 57 delete this._animations[name]; 58 } 59 }, 60 61 /** 62 * <p> 63 * Returns a cc.Animation that was previously added.<br/> 64 * If the name is not found it will return nil.<br/> 65 * You should retain the returned copy if you are going to use it.</br> 66 * </p> 67 * @param {String} name 68 * @return {cc.Animation} 69 */ 70 getAnimation:function (name) { 71 if (this._animations.hasOwnProperty(name)) 72 return this._animations[name]; 73 return null; 74 }, 75 76 /** 77 * <p> 78 * Adds an animation from an NSDictionary<br/> 79 * Make sure that the frames were previously loaded in the cc.SpriteFrameCache. 80 * </p> 81 * @param {object} dictionary 82 */ 83 addAnimationsWithDictionary:function (dictionary) { 84 var animations = dictionary["animations"]; 85 if (!animations) { 86 cc.log("cocos2d: cc.AnimationCache: No animations were found in provided dictionary."); 87 return; 88 } 89 90 var version = 1; 91 var properties = dictionary["properties"]; 92 if (properties) { 93 version = (properties["format"] != null) ? parseInt(properties["format"]) : version; 94 var spritesheets = properties["spritesheets"]; 95 for (var i = 0; i < spritesheets.length; i++) { 96 cc.SpriteFrameCache.getInstance().addSpriteFrames(spritesheets[i]); 97 } 98 } 99 100 switch (version) { 101 case 1: 102 this._parseVersion1(animations); 103 break; 104 case 2: 105 this._parseVersion2(animations); 106 break; 107 default : 108 cc.log("cc.AnimationCache. Invalid animation format"); 109 break; 110 } 111 }, 112 113 /** 114 * <p> 115 * Adds an animation from a plist file.<br/> 116 * Make sure that the frames were previously loaded in the cc.SpriteFrameCache. 117 * </p> 118 * @param {String} plist 119 */ 120 addAnimations:function (plist) { 121 if(!plist) 122 throw "cc.AnimationCache.addAnimations(): Invalid texture file name"; 123 var fileUtils = cc.FileUtils.getInstance(); 124 125 var path = fileUtils.fullPathForFilename(plist); 126 var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(path); 127 128 if(!dict){ 129 cc.log("cc.AnimationCache.addAnimations(): File could not be found"); 130 return; 131 } 132 133 this.addAnimationsWithDictionary(dict); 134 }, 135 136 _parseVersion1:function (animations) { 137 var frameCache = cc.SpriteFrameCache.getInstance(); 138 139 for (var key in animations) { 140 var animationDict = animations[key]; 141 var frameNames = animationDict["frames"]; 142 var delay = parseFloat(animationDict["delay"]) || 0; 143 var animation = null; 144 if (!frameNames) { 145 cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache."); 146 continue; 147 } 148 149 var frames = []; 150 for (var i = 0; i < frameNames.length; i++) { 151 var spriteFrame = frameCache.getSpriteFrame(frameNames[i]); 152 if (!spriteFrame) { 153 cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + frameNames[i] 154 + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation."); 155 continue; 156 } 157 var animFrame = new cc.AnimationFrame(); 158 animFrame.initWithSpriteFrame(spriteFrame, 1, null); 159 frames.push(animFrame); 160 } 161 162 if (frames.length === 0) { 163 cc.log("cocos2d: cc.AnimationCache: None of the frames for animation '" + key 164 + "' were found in the cc.SpriteFrameCache. Animation is not being added to the Animation Cache."); 165 continue; 166 } else if (frames.length != frameNames.length) { 167 cc.log("cocos2d: cc.AnimationCache: An animation in your dictionary refers to a frame which is not in the cc.SpriteFrameCache." + 168 " Some or all of the frames for the animation '" + key + "' may be missing."); 169 } 170 animation = cc.Animation.createWithAnimationFrames(frames, delay, 1); 171 cc.AnimationCache.getInstance().addAnimation(animation, key); 172 } 173 }, 174 175 _parseVersion2:function (animations) { 176 var frameCache = cc.SpriteFrameCache.getInstance(); 177 178 for (var key in animations) { 179 var animationDict = animations[key]; 180 181 var loopsTemp = parseInt(animationDict["loops"]); 182 var loops = (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("cocos2d: CCAnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache."); 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("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + spriteFrameName 199 + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation."); 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.getInstance().addAnimation(animation, key); 215 } 216 }, 217 218 /** 219 * initialize cc.AnimationCache 220 * @return {Boolean} 221 */ 222 init:function () { 223 this._animations = {}; 224 return true; 225 }, 226 227 _animations:null 228 }); 229 230 /** 231 * Purges the cache. It releases all the cc.Animation objects and the shared instance. 232 */ 233 cc.AnimationCache.purgeSharedAnimationCache = function () { 234 if (cc.s_sharedAnimationCache) { 235 cc.s_sharedAnimationCache._animations = null; 236 cc.s_sharedAnimationCache = null; 237 } 238 }; 239 240 /** 241 * Retruns ths shared instance of the Animation cache 242 * @return {cc.AnimationCache} 243 */ 244 cc.AnimationCache.getInstance = function () { 245 if (cc.s_sharedAnimationCache === null) { 246 cc.s_sharedAnimationCache = new cc.AnimationCache(); 247 cc.s_sharedAnimationCache.init(); 248 } 249 return cc.s_sharedAnimationCache; 250 }; 251 252 cc.s_sharedAnimationCache = null; 253