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