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 * cc.textureCache is a singleton object, it's the global cache for cc.Texture2D 29 * @class 30 * @name cc.textureCache 31 */ 32 cc.textureCache = /** @lends cc.textureCache# */{ 33 _textures: {}, 34 _textureColorsCache: {}, 35 _textureKeySeq: (0 | Math.random() * 1000), 36 37 _loadedTexturesBefore: {}, 38 39 //handleLoadedTexture move to Canvas/WebGL 40 41 _initializingRenderer: function () { 42 var selPath; 43 //init texture from _loadedTexturesBefore 44 var locLoadedTexturesBefore = this._loadedTexturesBefore, locTextures = this._textures; 45 for (selPath in locLoadedTexturesBefore) { 46 var tex2d = locLoadedTexturesBefore[selPath]; 47 tex2d.handleLoadedTexture(); 48 locTextures[selPath] = tex2d; 49 } 50 this._loadedTexturesBefore = {}; 51 }, 52 53 /** 54 * <p> 55 * Returns a Texture2D object given an PVR filename <br/> 56 * If the file image was not previously loaded, it will create a new CCTexture2D <br/> 57 * object and it will return it. Otherwise it will return a reference of a previously loaded image <br/> 58 * note: AddPVRTCImage does not support on HTML5 59 * </p> 60 * @param {String} filename 61 * @return {cc.Texture2D} 62 */ 63 addPVRTCImage: function (filename) { 64 cc.log(cc._LogInfos.textureCache_addPVRTCImage); 65 }, 66 67 /** 68 * <p> 69 * Returns a Texture2D object given an ETC filename <br/> 70 * If the file image was not previously loaded, it will create a new CCTexture2D <br/> 71 * object and it will return it. Otherwise it will return a reference of a previously loaded image <br/> 72 * note:addETCImage does not support on HTML5 73 * </p> 74 * @param {String} filename 75 * @return {cc.Texture2D} 76 */ 77 addETCImage: function (filename) { 78 cc.log(cc._LogInfos.textureCache_addETCImage); 79 }, 80 81 /** 82 * Description 83 * @return {String} 84 */ 85 description: function () { 86 return "<TextureCache | Number of textures = " + this._textures.length + ">"; 87 }, 88 89 /** 90 * Returns an already created texture. Returns null if the texture doesn't exist. 91 * @param {String} textureKeyName 92 * @return {cc.Texture2D|Null} 93 * @deprecated 94 * @example 95 * //example 96 * var key = cc.textureCache.textureForKey("hello.png"); 97 */ 98 textureForKey: function (textureKeyName) { 99 cc.log(cc._LogInfos.textureCache_textureForKey); 100 return this.getTextureForKey(textureKeyName); 101 }, 102 103 /** 104 * Returns an already created texture. Returns null if the texture doesn't exist. 105 * @param {String} textureKeyName 106 * @return {cc.Texture2D|Null} 107 * @example 108 * //example 109 * var key = cc.textureCache.getTextureForKey("hello.png"); 110 */ 111 getTextureForKey: function(textureKeyName){ 112 return this._textures[textureKeyName] || this._textures[cc.loader._getAliase(textureKeyName)]; 113 }, 114 115 /** 116 * @param {Image} texture 117 * @return {String|Null} 118 * @example 119 * //example 120 * var key = cc.textureCache.getKeyByTexture(texture); 121 */ 122 getKeyByTexture: function (texture) { 123 for (var key in this._textures) { 124 if (this._textures[key] === texture) { 125 return key; 126 } 127 } 128 return null; 129 }, 130 131 _generalTextureKey: function (id) { 132 return "_textureKey_" + id; 133 }, 134 135 /** 136 * @param {Image} texture 137 * @return {Array} 138 * @example 139 * //example 140 * var cacheTextureForColor = cc.textureCache.getTextureColors(texture); 141 */ 142 getTextureColors: function (texture) { 143 var image = texture._htmlElementObj; 144 var key = this.getKeyByTexture(image); 145 if (!key) { 146 if (image instanceof HTMLImageElement) 147 key = image.src; 148 else 149 key = this._generalTextureKey(texture.__instanceId); 150 } 151 152 if (!this._textureColorsCache[key]) 153 this._textureColorsCache[key] = texture._generateTextureCacheForColor(); 154 return this._textureColorsCache[key]; 155 }, 156 157 /** 158 * <p>Returns a Texture2D object given an PVR filename<br /> 159 * If the file image was not previously loaded, it will create a new Texture2D<br /> 160 * object and it will return it. Otherwise it will return a reference of a previously loaded image </p> 161 * @param {String} path 162 * @return {cc.Texture2D} 163 */ 164 addPVRImage: function (path) { 165 cc.log(cc._LogInfos.textureCache_addPVRImage); 166 }, 167 168 /** 169 * <p>Purges the dictionary of loaded textures. <br /> 170 * Call this method if you receive the "Memory Warning" <br /> 171 * In the short term: it will free some resources preventing your app from being killed <br /> 172 * In the medium term: it will allocate more resources <br /> 173 * In the long term: it will be the same</p> 174 * @example 175 * //example 176 * cc.textureCache.removeAllTextures(); 177 */ 178 removeAllTextures: function () { 179 var locTextures = this._textures; 180 for (var selKey in locTextures) { 181 if (locTextures[selKey]) 182 locTextures[selKey].releaseTexture(); 183 } 184 this._textures = {}; 185 }, 186 187 /** 188 * Deletes a texture from the cache given a texture 189 * @param {Image} texture 190 * @example 191 * //example 192 * cc.textureCache.removeTexture(texture); 193 */ 194 removeTexture: function (texture) { 195 if (!texture) 196 return; 197 198 var locTextures = this._textures; 199 for (var selKey in locTextures) { 200 if (locTextures[selKey] === texture) { 201 locTextures[selKey].releaseTexture(); 202 delete(locTextures[selKey]); 203 } 204 } 205 }, 206 207 /** 208 * Deletes a texture from the cache given a its key name 209 * @param {String} textureKeyName 210 * @example 211 * //example 212 * cc.textureCache.removeTexture("hello.png"); 213 */ 214 removeTextureForKey: function (textureKeyName) { 215 if (textureKeyName == null) 216 return; 217 if (this._textures[textureKeyName]) 218 delete(this._textures[textureKeyName]); 219 }, 220 221 //addImage move to Canvas/WebGL 222 223 /** 224 * Cache the image data 225 * @param {String} path 226 * @param {Image|HTMLImageElement|HTMLCanvasElement} texture 227 */ 228 cacheImage: function (path, texture) { 229 if (texture instanceof cc.Texture2D) { 230 this._textures[path] = texture; 231 return; 232 } 233 var texture2d = new cc.Texture2D(); 234 texture2d.initWithElement(texture); 235 texture2d.handleLoadedTexture(); 236 this._textures[path] = texture2d; 237 }, 238 239 /** 240 * <p>Returns a Texture2D object given an UIImage image<br /> 241 * If the image was not previously loaded, it will create a new Texture2D object and it will return it.<br /> 242 * Otherwise it will return a reference of a previously loaded image<br /> 243 * The "key" parameter will be used as the "key" for the cache.<br /> 244 * If "key" is null, then a new texture will be created each time.</p> 245 * @param {HTMLImageElement|HTMLCanvasElement} image 246 * @param {String} key 247 * @return {cc.Texture2D} 248 */ 249 addUIImage: function (image, key) { 250 cc.assert(image, cc._LogInfos.textureCache_addUIImage_2); 251 252 if (key) { 253 if (this._textures[key]) 254 return this._textures[key]; 255 } 256 257 // prevents overloading the autorelease pool 258 var texture = new cc.Texture2D(); 259 texture.initWithImage(image); 260 if (key != null) 261 this._textures[key] = texture; 262 else 263 cc.log(cc._LogInfos.textureCache_addUIImage); 264 return texture; 265 }, 266 267 /** 268 * <p>Output to cc.log the current contents of this TextureCache <br /> 269 * This will attempt to calculate the size of each texture, and the total texture memory in use. </p> 270 */ 271 dumpCachedTextureInfo: function () { 272 var count = 0; 273 var totalBytes = 0, locTextures = this._textures; 274 275 for (var key in locTextures) { 276 var selTexture = locTextures[key]; 277 count++; 278 if (selTexture.getHtmlElementObj() instanceof HTMLImageElement) 279 cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo, key, selTexture.getHtmlElementObj().src, selTexture.pixelsWidth, selTexture.pixelsHeight); 280 else { 281 cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selTexture.pixelsWidth, selTexture.pixelsHeight); 282 } 283 totalBytes += selTexture.pixelsWidth * selTexture.pixelsHeight * 4; 284 } 285 286 var locTextureColorsCache = this._textureColorsCache; 287 for (key in locTextureColorsCache) { 288 var selCanvasColorsArr = locTextureColorsCache[key]; 289 for (var selCanvasKey in selCanvasColorsArr) { 290 var selCanvas = selCanvasColorsArr[selCanvasKey]; 291 count++; 292 cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selCanvas.width, selCanvas.height); 293 totalBytes += selCanvas.width * selCanvas.height * 4; 294 } 295 296 } 297 cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_3, count, totalBytes / 1024, (totalBytes / (1024.0 * 1024.0)).toFixed(2)); 298 }, 299 300 _clear: function () { 301 this._textures = {}; 302 this._textureColorsCache = {}; 303 this._textureKeySeq = (0 | Math.random() * 1000); 304 this._loadedTexturesBefore = {}; 305 } 306 }; 307 308 cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { 309 if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) { 310 311 var _p = cc.textureCache; 312 313 _p.handleLoadedTexture = function (url) { 314 var locTexs = this._textures; 315 //remove judge 316 var tex = locTexs[url]; 317 if (!tex) { 318 tex = locTexs[url] = new cc.Texture2D(); 319 tex.url = url; 320 } 321 tex.handleLoadedTexture(); 322 }; 323 324 /** 325 * <p>Returns a Texture2D object given an file image <br /> 326 * If the file image was not previously loaded, it will create a new Texture2D <br /> 327 * object and it will return it. It will use the filename as a key.<br /> 328 * Otherwise it will return a reference of a previously loaded image. <br /> 329 * Supported image extensions: .png, .jpg, .gif</p> 330 * @param {String} url 331 * @param {Function} cb 332 * @param {Object} target 333 * @return {cc.Texture2D} 334 * @example 335 * //example 336 * cc.textureCache.addImage("hello.png"); 337 */ 338 _p.addImage = function (url, cb, target) { 339 340 cc.assert(url, cc._LogInfos.Texture2D_addImage); 341 342 var locTexs = this._textures; 343 //remove judge 344 var tex = locTexs[url] || locTexs[cc.loader._getAliase(url)]; 345 if (tex) { 346 if(tex.isLoaded()) { 347 cb && cb.call(target, tex); 348 return tex; 349 } 350 else 351 { 352 tex.addEventListener("load", function(){ 353 cb && cb.call(target, tex); 354 }, target); 355 return tex; 356 } 357 } 358 359 tex = locTexs[url] = new cc.Texture2D(); 360 tex.url = url; 361 var loadFunc = cc.loader._checkIsImageURL(url) ? cc.loader.load : cc.loader.loadImg; 362 loadFunc.call(cc.loader, url, function (err, img) { 363 if (err) 364 return cb && cb.call(target, err); 365 cc.textureCache.handleLoadedTexture(url); 366 367 var texResult = locTexs[url]; 368 cb && cb.call(target, texResult); 369 }); 370 371 return tex; 372 }; 373 374 _p.addImageAsync = _p.addImage; 375 _p = null; 376 377 } else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { 378 cc.assert(cc.isFunction(cc._tmp.WebGLTextureCache), cc._LogInfos.MissingFile, "TexturesWebGL.js"); 379 cc._tmp.WebGLTextureCache(); 380 delete cc._tmp.WebGLTextureCache; 381 } 382 }); 383