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  * resource type
 29  * @constant
 30  * @type Object
 31  */
 32 cc.RESOURCE_TYPE = {
 33     "IMAGE": ["png", "jpg", "bmp","jpeg","gif"],
 34     "SOUND": ["mp3", "ogg", "wav", "mp4", "m4a"],
 35     "XML": ["plist", "xml", "fnt", "tmx", "tsx"],
 36     "BINARY": ["ccbi"],
 37     "FONT": "FONT",
 38     "TEXT":["txt", "vsh", "fsh","json", "ExportJson"],
 39     "UNKNOW": []
 40 };
 41 
 42 /**
 43  * A class to pre-load resources before engine start game main loop.
 44  * @class
 45  * @extends cc.Scene
 46  */
 47 cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{
 48     _curNumber: 0,
 49     _totalNumber: 0,
 50     _loadedNumber: 0,
 51     _resouces: null,
 52     _animationInterval: 1 / 60,
 53     _interval: null,
 54     _isAsync: false,
 55 
 56     /**
 57      * Constructor
 58      */
 59     ctor: function () {
 60         this._resouces = [];
 61     },
 62 
 63     /**
 64      * init with resources
 65      * @param {Array} resources
 66      * @param {Function|String} selector
 67      * @param {Object} target
 68      */
 69     initWithResources: function (resources, selector, target) {
 70         if(!resources){
 71             console.log("resources should not null");
 72             return;
 73         }
 74 
 75         if (selector) {
 76             this._selector = selector;
 77             this._target = target;
 78         }
 79 
 80         if ((resources != this._resouces) || (this._curNumber == 0)) {
 81             this._curNumber = 0;
 82             this._loadedNumber = 0;
 83             if (resources[0] instanceof Array) {
 84                 for (var i = 0; i < resources.length; i++) {
 85                     var each = resources[i];
 86                     this._resouces = this._resouces.concat(each);
 87                 }
 88             } else
 89                 this._resouces = resources;
 90             this._totalNumber = this._resouces.length;
 91         }
 92 
 93         //load resources
 94         this._schedulePreload();
 95     },
 96 
 97     setAsync: function (isAsync) {
 98         this._isAsync = isAsync;
 99     },
100 
101     /**
102      * Callback when a resource file load failed.
103      * @example
104      * //example
105      * cc.Loader.getInstance().onResLoaded();
106      */
107     onResLoadingErr: function (name) {
108         this._loadedNumber++;
109         cc.log("cocos2d:Failed loading resource: " + name);
110     },
111 
112     /**
113      * Callback when a resource file loaded.
114      * @example
115      * //example
116      * cc.Loader.getInstance().onResLoaded();
117      */
118     onResLoaded: function () {
119         this._loadedNumber++;
120     },
121 
122     /**
123      * Get loading percentage
124      * @return {Number}
125      * @example
126      * //example
127      * cc.log(cc.Loader.getInstance().getPercentage() + "%");
128      */
129     getPercentage: function () {
130         var percent = 0;
131         if (this._totalNumber == 0) {
132             percent = 100;
133         } else {
134             percent = (0 | (this._loadedNumber / this._totalNumber * 100));
135         }
136         return percent;
137     },
138 
139     /**
140      * release resources from a list
141      * @param resources
142      */
143     releaseResources: function (resources) {
144         if (resources && resources.length > 0) {
145             var sharedTextureCache = cc.TextureCache.getInstance();
146             var sharedEngine = cc.AudioEngine ? cc.AudioEngine.getInstance() : null;
147             var sharedParser = cc.SAXParser.getInstance();
148             var sharedFileUtils = cc.FileUtils.getInstance();
149 
150             var resInfo;
151             for (var i = 0; i < resources.length; i++) {
152                 resInfo = resources[i];
153                 var type = this._getResType(resInfo);
154                 switch (type) {
155                     case "IMAGE":
156                         sharedTextureCache.removeTextureForKey(resInfo.src);
157                         break;
158                     case "SOUND":
159                         if(!sharedEngine) throw "Can not find AudioEngine! Install it, please.";
160                         sharedEngine.unloadEffect(resInfo.src);
161                         break;
162                     case "XML":
163                         sharedParser.unloadPlist(resInfo.src);
164                         break;
165                     case "BINARY":
166                         sharedFileUtils.unloadBinaryFileData(resInfo.src);
167                         break;
168                     case "TEXT":
169                         sharedFileUtils.unloadTextFileData(resInfo.src);
170                         break;
171                     case "FONT":
172                         this._unregisterFaceFont(resInfo);
173                         break;
174                     default:
175                         throw "cocos2d:unknown filename extension: " + type;
176                         break;
177                 }
178             }
179         }
180     },
181 
182     _preload: function () {
183         this._updatePercent();
184         if (this._isAsync) {
185             var frameRate = cc.Director.getInstance()._frameRate;
186             if (frameRate != null && frameRate < 20) {
187                 cc.log("cocos2d: frame rate less than 20 fps, skip frame.");
188                 return;
189             }
190         }
191 
192         if (this._curNumber < this._totalNumber) {
193             this._loadOneResource();
194             this._curNumber++;
195         }
196     },
197 
198     _loadOneResource: function () {
199         var sharedTextureCache = cc.TextureCache.getInstance();
200         var sharedEngine = cc.AudioEngine ? cc.AudioEngine.getInstance() : null;
201         var sharedParser = cc.SAXParser.getInstance();
202         var sharedFileUtils = cc.FileUtils.getInstance();
203 
204         var resInfo = this._resouces[this._curNumber];
205         var type = this._getResType(resInfo);
206         switch (type) {
207             case "IMAGE":
208                 sharedTextureCache.addImage(resInfo.src);
209                 break;
210             case "SOUND":
211                 if(!sharedEngine) throw "Can not find AudioEngine! Install it, please.";
212                 sharedEngine.preloadSound(resInfo.src);
213                 break;
214             case "XML":
215                 sharedParser.preloadPlist(resInfo.src);
216                 break;
217             case "BINARY":
218                 sharedFileUtils.preloadBinaryFileData(resInfo.src);
219                 break;
220             case "TEXT" :
221                 sharedFileUtils.preloadTextFileData(resInfo.src);
222                 break;
223             case "FONT":
224                 this._registerFaceFont(resInfo);
225                 break;
226             default:
227                 throw "cocos2d:unknown filename extension: " + type;
228                 break;
229         }
230     },
231 
232     _schedulePreload: function () {
233         var _self = this;
234         this._interval = setInterval(function () {
235             _self._preload();
236         }, this._animationInterval * 1000);
237     },
238 
239     _unschedulePreload: function () {
240         clearInterval(this._interval);
241     },
242 
243     _getResType: function (resInfo) {
244         var isFont = resInfo.fontName;
245         if (isFont != null) {
246             return cc.RESOURCE_TYPE["FONT"];
247         } else {
248             var src = resInfo.src;
249             var ext = src.substring(src.lastIndexOf(".") + 1, src.length);
250 
251             var index = ext.indexOf("?");
252             if(index > 0) ext = ext.substring(0, index);
253 
254             for (var resType in cc.RESOURCE_TYPE) {
255                 if (cc.RESOURCE_TYPE[resType].indexOf(ext) != -1) {
256                     return resType;
257                 }
258             }
259             return ext;
260         }
261     },
262 
263     _updatePercent: function () {
264         var percent = this.getPercentage();
265 
266         if (percent >= 100) {
267             this._unschedulePreload();
268             this._complete();
269         }
270     },
271 
272     _complete: function () {
273         if (this._target && (typeof(this._selector) == "string")) {
274             this._target[this._selector](this);
275         } else if (this._target && (typeof(this._selector) == "function")) {
276             this._selector.call(this._target, this);
277         } else {
278             this._selector(this);
279         }
280 
281         this._curNumber = 0;
282         this._loadedNumber = 0;
283         this._totalNumber = 0;
284     },
285 
286     _registerFaceFont: function (fontRes) {
287         var srcArr = fontRes.src;
288         var fileUtils = cc.FileUtils.getInstance();
289         if (srcArr && srcArr.length > 0) {
290             var fontStyle = document.createElement("style");
291             fontStyle.type = "text/css";
292             document.body.appendChild(fontStyle);
293 
294             var fontStr = "@font-face { font-family:" + fontRes.fontName + "; src:";
295             for (var i = 0; i < srcArr.length; i++) {
296                 fontStr += "url('" + fileUtils.fullPathForFilename(encodeURI(srcArr[i].src)) + "') format('" + srcArr[i].type + "')";
297                 fontStr += (i == (srcArr.length - 1)) ? ";" : ",";
298             }
299             fontStyle.textContent += fontStr + "};";
300 
301             //preload
302             //<div style="font-family: PressStart;">.</div>
303             var preloadDiv = document.createElement("div");
304             preloadDiv.style.fontFamily = fontRes.fontName;
305             preloadDiv.innerHTML = ".";
306             preloadDiv.style.position = "absolute";
307             preloadDiv.style.left = "-100px";
308             preloadDiv.style.top = "-100px";
309             document.body.appendChild(preloadDiv);
310         }
311         cc.Loader.getInstance().onResLoaded();
312     },
313 
314     _unregisterFaceFont: function (fontRes) {
315         //todo remove style
316     }
317 });
318 
319 /**
320  * Preload resources in the background
321  * @param {Array} resources
322  * @param {Function|String} selector
323  * @param {Object} target
324  * @return {cc.Loader}
325  * @example
326  * //example
327  * var g_mainmenu = [
328  *    {src:"res/hello.png"},
329  *    {src:"res/hello.plist"},
330  *
331  *    {src:"res/logo.png"},
332  *    {src:"res/btn.png"},
333  *
334  *    {src:"res/boom.mp3"},
335  * ]
336  *
337  * var g_level = [
338  *    {src:"res/level01.png"},
339  *    {src:"res/level02.png"},
340  *    {src:"res/level03.png"}
341  * ]
342  *
343  * //load a list of resources
344  * cc.Loader.preload(g_mainmenu, this.startGame, this);
345  *
346  * //load multi lists of resources
347  * cc.Loader.preload([g_mainmenu,g_level], this.startGame, this);
348  */
349 cc.Loader.preload = function (resources, selector, target) {
350     if (!this._instance) {
351         this._instance = new cc.Loader();
352     }
353     this._instance.initWithResources(resources, selector, target);
354     return this._instance;
355 };
356 
357 /**
358  * Preload resources async
359  * @param {Array} resources
360  * @param {Function|String} selector
361  * @param {Object} target
362  * @return {cc.Loader}
363  */
364 cc.Loader.preloadAsync = function (resources, selector, target) {
365     if (!this._instance) {
366         this._instance = new cc.Loader();
367     }
368     this._instance.setAsync(true);
369     this._instance.initWithResources(resources, selector, target);
370     return this._instance;
371 };
372 
373 /**
374  * Release the resources from a list
375  * @param {Array} resources
376  */
377 cc.Loader.purgeCachedData = function (resources) {
378     if (this._instance) {
379         this._instance.releaseResources(resources);
380     }
381 };
382 
383 /**
384  * Returns a shared instance of the loader
385  * @function
386  * @return {cc.Loader}
387  */
388 cc.Loader.getInstance = function () {
389     if (!this._instance) {
390         this._instance = new cc.Loader();
391     }
392     return this._instance;
393 };
394 
395 cc.Loader._instance = null;
396 
397 
398 /**
399  * Used to display the loading screen
400  * @class
401  * @extends cc.Scene
402  */
403 cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{
404     _logo: null,
405     _logoTexture: null,
406     _texture2d: null,
407     _bgLayer: null,
408     _label: null,
409     _winSize:null,
410 
411     /**
412      * Constructor
413      */
414     ctor: function () {
415         cc.Scene.prototype.ctor.call(this);
416         this._winSize = cc.Director.getInstance().getWinSize();
417     },
418     init:function(){
419         cc.Scene.prototype.init.call(this);
420 
421         //logo
422         var logoWidth = 160;
423         var logoHeight = 200;
424         var centerPos = cc.p(this._winSize.width / 2, this._winSize.height / 2);
425 
426         this._logoTexture = new Image();
427         var _this = this;
428         this._logoTexture.addEventListener("load", function () {
429             _this._initStage(centerPos);
430             this.removeEventListener('load', arguments.callee, false);
431         });
432         this._logoTexture.src = "data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAlAAD/4QMpaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MCA2MS4xMzQ3NzcsIDIwMTAvMDIvMTItMTc6MzI6MDAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjM4MDBEMDY2QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM4MDBEMDY1QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2RTk0OEM4OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2RTk0OEM5OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4ADkFkb2JlAGTAAAAAAf/bAIQADQkJCQoJDQoKDRMMCwwTFhENDREW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";
433         this._logoTexture.width = logoWidth;
434         this._logoTexture.height = logoHeight;
435 
436         // bg
437         this._bgLayer = cc.LayerColor.create(cc.c4(32, 32, 32, 255));
438         this._bgLayer.setPosition(0, 0);
439         this.addChild(this._bgLayer, 0);
440 
441         //loading percent
442         this._label = cc.LabelTTF.create("Loading... 0%", "Arial", 14);
443         this._label.setColor(cc.c3(180, 180, 180));
444         this._label.setPosition(cc.pAdd(centerPos, cc.p(0, -logoHeight / 2 - 10)));
445         this._bgLayer.addChild(this._label, 10);
446     },
447 
448     _initStage: function (centerPos) {
449         this._texture2d = new cc.Texture2D();
450         this._texture2d.initWithElement(this._logoTexture);
451         this._texture2d.handleLoadedTexture();
452         this._logo = cc.Sprite.createWithTexture(this._texture2d);
453         this._logo.setScale(cc.CONTENT_SCALE_FACTOR());
454         this._logo.setPosition(centerPos);
455         this._bgLayer.addChild(this._logo, 10);
456     },
457 
458     onEnter: function () {
459         cc.Node.prototype.onEnter.call(this);
460         this.schedule(this._startLoading, 0.3);
461     },
462 
463     onExit: function () {
464         cc.Node.prototype.onExit.call(this);
465         var tmpStr = "Loading... 0%";
466         this._label.setString(tmpStr);
467     },
468 
469     /**
470      * init with resources
471      * @param {Array} resources
472      * @param {Function|String} selector
473      * @param {Object} target
474      */
475     initWithResources: function (resources, selector, target) {
476         this.resources = resources;
477         this.selector = selector;
478         this.target = target;
479     },
480 
481     _startLoading: function () {
482         this.unschedule(this._startLoading);
483         cc.Loader.preload(this.resources, this.selector, this.target);
484         this.schedule(this._updatePercent);
485     },
486 
487     _updatePercent: function () {
488         var percent = cc.Loader.getInstance().getPercentage();
489         var tmpStr = "Loading... " + percent + "%";
490         this._label.setString(tmpStr);
491 
492         if (percent >= 100)
493             this.unschedule(this._updatePercent);
494     }
495 });
496 
497 /**
498  * Preload multi scene resources.
499  * @param {Array} resources
500  * @param {Function|String} selector
501  * @param {Object} target
502  * @return {cc.LoaderScene}
503  * @example
504  * //example
505  * var g_mainmenu = [
506  *    {src:"res/hello.png"},
507  *    {src:"res/hello.plist"},
508  *
509  *    {src:"res/logo.png"},
510  *    {src:"res/btn.png"},
511  *
512  *    {src:"res/boom.mp3"},
513  * ]
514  *
515  * var g_level = [
516  *    {src:"res/level01.png"},
517  *    {src:"res/level02.png"},
518  *    {src:"res/level03.png"}
519  * ]
520  *
521  * //load a list of resources
522  * cc.LoaderScene.preload(g_mainmenu, this.startGame, this);
523  *
524  * //load multi lists of resources
525  * cc.LoaderScene.preload([g_mainmenu,g_level], this.startGame, this);
526  */
527 cc.LoaderScene.preload = function (resources, selector, target) {
528     if (!this._instance) {
529         this._instance = new cc.LoaderScene();
530         this._instance.init();
531     }
532 
533     this._instance.initWithResources(resources, selector, target);
534 
535     var director = cc.Director.getInstance();
536     if (director.getRunningScene()) {
537         director.replaceScene(this._instance);
538     } else {
539         director.runWithScene(this._instance);
540     }
541 
542     return this._instance;
543 };
544