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.Assert(false, "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 cc.Assert(plist, "Invalid texture file name") 122 var fileUtils = cc.FileUtils.getInstance(); 123 124 var path = fileUtils.fullPathForFilename(plist); 125 var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(path); 126 127 cc.Assert(dict, "cc.AnimationCache: File could not be found"); 128 129 this.addAnimationsWithDictionary(dict); 130 }, 131 132 _parseVersion1:function (animations) { 133 var frameCache = cc.SpriteFrameCache.getInstance(); 134 135 for (var key in animations) { 136 var animationDict = animations[key]; 137 var frameNames = animationDict["frames"]; 138 var delay = parseFloat(animationDict["delay"]) || 0; 139 var animation = null; 140 if (!frameNames) { 141 cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache."); 142 continue; 143 } 144 145 var frames = []; 146 for (var i = 0; i < frameNames.length; i++) { 147 var spriteFrame = frameCache.getSpriteFrame(frameNames[i]); 148 if (!spriteFrame) { 149 cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + frameNames[i] 150 + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation."); 151 continue; 152 } 153 var animFrame = new cc.AnimationFrame(); 154 animFrame.initWithSpriteFrame(spriteFrame, 1, null); 155 frames.push(animFrame); 156 } 157 158 if (frames.length === 0) { 159 cc.log("cocos2d: cc.AnimationCache: None of the frames for animation '" + key 160 + "' were found in the cc.SpriteFrameCache. Animation is not being added to the Animation Cache."); 161 continue; 162 } else if (frames.length != frameNames.length) { 163 cc.log("cocos2d: cc.AnimationCache: An animation in your dictionary refers to a frame which is not in the cc.SpriteFrameCache." + 164 " Some or all of the frames for the animation '" + key + "' may be missing."); 165 } 166 animation = cc.Animation.createWithAnimationFrames(frames, delay, 1); 167 cc.AnimationCache.getInstance().addAnimation(animation, key); 168 } 169 }, 170 171 _parseVersion2:function (animations) { 172 var frameCache = cc.SpriteFrameCache.getInstance(); 173 174 for (var key in animations) { 175 var animationDict = animations[key]; 176 177 var loopsTemp = parseInt(animationDict["loops"]); 178 var loops = (isNaN(loopsTemp)) ? 1 : loopsTemp; 179 var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false; 180 var frameArray = animationDict["frames"]; 181 182 if (!frameArray) { 183 cc.log("cocos2d: CCAnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache."); 184 continue; 185 } 186 187 //Array of AnimationFrames 188 var arr = []; 189 for (var i = 0; i < frameArray.length; i++) { 190 var entry = frameArray[i]; 191 var spriteFrameName = entry["spriteframe"]; 192 var spriteFrame = frameCache.getSpriteFrame(spriteFrameName); 193 if (!spriteFrame) { 194 cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + spriteFrameName 195 + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation."); 196 continue; 197 } 198 199 var delayUnits = parseFloat(entry["delayUnits"]) || 0; 200 var userInfo = entry["notification"]; 201 var animFrame = new cc.AnimationFrame(); 202 animFrame.initWithSpriteFrame(spriteFrame, delayUnits, userInfo); 203 arr.push(animFrame); 204 } 205 206 var delayPerUnit = parseFloat(animationDict["delayPerUnit"]) || 0; 207 var animation = new cc.Animation(); 208 animation.initWithAnimationFrames(arr, delayPerUnit, loops); 209 animation.setRestoreOriginalFrame(restoreOriginalFrame); 210 cc.AnimationCache.getInstance().addAnimation(animation, key); 211 } 212 }, 213 214 /** 215 * initialize cc.AnimationCache 216 * @return {Boolean} 217 */ 218 init:function () { 219 this._animations = {}; 220 return true; 221 }, 222 223 _animations:null 224 }); 225 226 /** 227 * Purges the cache. It releases all the cc.Animation objects and the shared instance. 228 */ 229 cc.AnimationCache.purgeSharedAnimationCache = function () { 230 if (cc.s_sharedAnimationCache) { 231 cc.s_sharedAnimationCache._animations = null; 232 cc.s_sharedAnimationCache = null; 233 } 234 }; 235 236 /** 237 * Retruns ths shared instance of the Animation cache 238 * @return {cc.AnimationCache} 239 */ 240 cc.AnimationCache.getInstance = function () { 241 if (cc.s_sharedAnimationCache === null) { 242 cc.s_sharedAnimationCache = new cc.AnimationCache(); 243 cc.s_sharedAnimationCache.init(); 244 } 245 return cc.s_sharedAnimationCache; 246 }; 247 248 cc.s_sharedAnimationCache = null; 249