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  * Device type
 29  * @constant
 30  * @type {Object}
 31  */
 32 cc.TARGET_PLATFORM = {
 33     WINDOWS:0,
 34     LINUX:1,
 35     MACOS:2,
 36     ANDROID:3,
 37     IPHONE:4,
 38     IPAD:5,
 39     BLACKBERRY:6,
 40     NACL:7,
 41     EMSCRIPTEN:8,
 42     MOBILE_BROWSER:100,
 43     PC_BROWSER:101
 44 };
 45 
 46 /**
 47  * Device oriented vertically, home button on the bottom
 48  * @constant
 49  * @type Number
 50  */
 51 cc.ORIENTATION_PORTRAIT = 0;
 52 
 53 /**
 54  * Device oriented vertically, home button on the top
 55  * @constant
 56  * @type Number
 57  */
 58 cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1;
 59 
 60 /**
 61  * Device oriented horizontally, home button on the right
 62  * @constant
 63  * @type Number
 64  */
 65 cc.ORIENTATION_LANDSCAPE_LEFT = 2;
 66 
 67 /**
 68  * Device oriented horizontally, home button on the left
 69  * @constant
 70  * @type Number
 71  */
 72 cc.ORIENTATION_LANDSCAPE_RIGHT = 3;
 73 
 74 //engine render type
 75 
 76 /**
 77  * Canvas of render type
 78  * @constant
 79  * @type Number
 80  */
 81 cc.CANVAS = 0;
 82 
 83 /**
 84  * WebGL of render type
 85  * @constant
 86  * @type Number
 87  */
 88 cc.WEBGL = 1;
 89 
 90 /**
 91  * drawing primitive of game engine
 92  * @type cc.DrawingPrimitive
 93  */
 94 cc.drawingUtil = null;
 95 
 96 /**
 97  * main Canvas 2D/3D Context of game engine
 98  * @type CanvasRenderingContext2D|WebGLRenderingContext
 99  */
100 cc.renderContext = null;
101 
102 /**
103  * main Canvas of game engine
104  * @type HTMLCanvasElement
105  */
106 cc.canvas = null;
107 
108 /**
109  * This Div element contain all game canvas
110  * @type HTMLDivElement
111  */
112 cc.gameDiv = null;
113 
114 /**
115  * current render type of game engine
116  * @type Number
117  */
118 cc.renderContextType = cc.CANVAS;
119 
120 /**
121  * save original size of canvas, use for resize canvas
122  * @type cc.Size
123  */
124 cc.originalCanvasSize = cc.size(0, 0);
125 
126 window.requestAnimFrame = (function () {
127     return  window.requestAnimationFrame ||
128         window.webkitRequestAnimationFrame ||
129         window.mozRequestAnimationFrame ||
130         window.oRequestAnimationFrame ||
131         window.msRequestAnimationFrame
132 })();
133 
134 
135 if (!window.console) {
136     window.console = {};
137     window.console.log = function () {
138     };
139     window.console.assert = function () {
140     };
141 }
142 
143 cc.isAddedHiddenEvent = false;
144 
145 /**
146  * <p>
147  *   setup game main canvas,renderContext,gameDiv and drawingUtil with argument  <br/>
148  *   <br/>
149  *   can receive follow type of arguemnt: <br/>
150  *      - empty: create a canvas append to document's body, and setup other option    <br/>
151  *      - string: search the element by document.getElementById(),    <br/>
152  *          if this element is HTMLCanvasElement, set this element as main canvas of engine, and set it's ParentNode as cc.gameDiv.<br/>
153  *          if this element is HTMLDivElement, set it's ParentNode to cc.gameDiv´╝î and create a canvas as main canvas of engine.   <br/>
154  * </p>
155  * @function
156  * @example
157  * //setup with null
158  * cc.setup();
159  *
160  * // setup with HTMLCanvasElement, gameCanvas is Canvas element
161  * // declare like this: <canvas id="gameCanvas" width="800" height="450"></canvas>
162  * cc.setup("gameCanvas");
163  *
164  * //setup with HTMLDivElement, gameDiv is Div element
165  * // declare like this: <div id="Cocos2dGameContainer" width="800" height="450"></div>
166  * cc.setup("Cocos2dGameContainer");
167  */
168 cc.setup = function (el, width, height) {
169     var element = cc.$(el) || cc.$('#' + el);
170     if (element.tagName == "CANVAS") {
171         width = width || element.width;
172         height = height || element.height;
173 
174         //it is already a canvas, we wrap it around with a div
175         cc.container = cc.$new("DIV");
176         cc.canvas = element;
177         cc.canvas.parentNode.insertBefore(cc.container, cc.canvas);
178         cc.canvas.appendTo(cc.container);
179         cc.container.style.width = (width || 480) + "px";
180         cc.container.style.height = (height || 320) + "px";
181         cc.container.setAttribute('id', 'Cocos2dGameContainer');
182         cc.canvas.setAttribute("width", width || 480);
183         cc.canvas.setAttribute("height", height || 320);
184     } else {//we must make a new canvas and place into this element
185         if (element.tagName != "DIV") {
186             cc.log("Warning: target element is not a DIV or CANVAS");
187         }
188         width = width || element.clientWidth;
189         height = height || element.clientHeight;
190 
191         cc.canvas = cc.$new("CANVAS");
192         cc.canvas.addClass("gameCanvas");
193         cc.canvas.setAttribute("width", width || 480);
194         cc.canvas.setAttribute("height", height || 320);
195         cc.container = element;
196         element.appendChild(cc.canvas);
197         cc.container.style.width = (width || 480) + "px";
198         cc.container.style.height = (height || 320) + "px";
199     }
200     cc.container.style.position = 'relative';
201     cc.container.style.overflow = 'hidden';
202     cc.container.top = '100%';
203 
204     if(cc.__renderDoesnotSupport)
205         return;
206 
207     if (cc.Browser.supportWebGL)
208         cc.renderContext = cc.webglContext = cc.create3DContext(cc.canvas,{'stencil': true, 'preserveDrawingBuffer': true, 'alpha': false });
209     if(cc.renderContext){
210         cc.renderContextType = cc.WEBGL;
211         window.gl = cc.renderContext; // global variable declared in CCMacro.js
212         cc.drawingUtil = new cc.DrawingPrimitiveWebGL(cc.renderContext);
213         cc.TextureCache.getInstance()._initializingRenderer();
214     } else {
215         cc.renderContext = cc.canvas.getContext("2d");
216         cc.mainRenderContextBackup = cc.renderContext;
217         cc.renderContextType = cc.CANVAS;
218         cc.renderContext.translate(0, cc.canvas.height);
219         cc.drawingUtil = new cc.DrawingPrimitiveCanvas(cc.renderContext);
220     }
221 
222     cc.originalCanvasSize = cc.size(cc.canvas.width, cc.canvas.height);
223     cc.gameDiv = cc.container;
224 
225     cc.log(cc.ENGINE_VERSION);
226     cc.Configuration.getInstance();
227 
228     cc.setContextMenuEnable(false);
229 
230     if(cc.Browser.isMobile){
231         cc._addUserSelectStatus();
232         cc._addBottomTag();
233     }
234 
235     var hidden, visibilityChange;
236     if (typeof document.hidden !== "undefined") {
237         hidden = "hidden";
238         visibilityChange = "visibilitychange";
239     } else if (typeof document.mozHidden !== "undefined") {
240         hidden = "mozHidden";
241         visibilityChange = "mozvisibilitychange";
242     } else if (typeof document.msHidden !== "undefined") {
243         hidden = "msHidden";
244         visibilityChange = "msvisibilitychange";
245     } else if (typeof document.webkitHidden !== "undefined") {
246         hidden = "webkitHidden";
247         visibilityChange = "webkitvisibilitychange";
248     }
249 
250     function handleVisibilityChange() {
251         if (!document[hidden])
252             cc.Director.getInstance()._resetLastUpdate();
253     }
254 
255     if (typeof document.addEventListener === "undefined" ||
256         typeof hidden === "undefined") {
257         cc.isAddedHiddenEvent = false;
258     } else {
259         cc.isAddedHiddenEvent = true;
260         document.addEventListener(visibilityChange, handleVisibilityChange, false);
261     }
262 };
263 
264 cc._addUserSelectStatus = function(){
265     var fontStyle = document.createElement("style");
266     fontStyle.type = "text/css";
267     document.body.appendChild(fontStyle);
268 
269     fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
270         +"-webkit-tap-highlight-color:rgba(0,0,0,0);}";
271 };
272 
273 cc._addBottomTag = function () {
274     var bottom = document.createElement("div");
275     bottom.id = "bottom";
276     bottom.style.border = bottom.style.margin = bottom.style.padding = bottom.style.height = bottom.style.lineHeight = bottom.style.fontSize = "0px";
277     document.body.appendChild(bottom);
278     window.location.href="#bottom";
279 };
280 
281 cc._isContextMenuEnable = false;
282 /**
283  * enable/disable contextMenu for Canvas
284  * @param {Boolean} enabled
285  */
286 cc.setContextMenuEnable = function (enabled) {
287     cc._isContextMenuEnable = enabled;
288     if (!cc._isContextMenuEnable) {
289         cc.canvas.oncontextmenu = function () {
290             return false;
291         };
292     } else {
293         cc.canvas.oncontextmenu = function () {
294         };
295     }
296 };
297 
298 /**
299  * Run main loop of game engine
300  * @class
301  * @extends cc.Class
302  */
303 cc.Application = cc.Class.extend(/** @lends cc.Application# */{
304     _animationInterval:null,
305     /**
306      * Constructor
307      */
308     ctor:function () {
309         this._animationInterval = 0;
310         cc.Assert(!cc._sharedApplication, "CCApplication ctor");
311         cc._sharedApplication = this;
312     },
313 
314     /**
315      * Callback by cc.Director for limit FPS.
316      * @param {Number} interval The time, which expressed in second, between current frame and next.
317      */
318     setAnimationInterval:function (interval) {
319         this._animationInterval = interval;
320     },
321 
322     /**
323      *  Get status bar rectangle in EGLView window.
324      * @param {cc.Rect} rect
325      * @deprecated
326      */
327     statusBarFrame:function (rect) {
328         if (rect) {
329             // Windows doesn't have status bar.
330             rect = cc.rect(0, 0, 0, 0);
331         }
332     },
333 
334     getTargetPlatform:function(){
335         return cc.Browser.isMobile ? cc.TARGET_PLATFORM.MOBILE_BROWSER : cc.TARGET_PLATFORM.PC_BROWSER;
336     },
337 
338     /**
339      * Run the message loop.
340      * @return {Number}
341      */
342     run:function () {
343         // Initialize instance and cocos2d.
344         if (!this.applicationDidFinishLaunching())
345             return 0;
346 
347         var callback, director = cc.Director.getInstance(), w = window;
348         if (w.requestAnimFrame && this._animationInterval == 1 / 60) {
349             callback = function () {
350                 director.mainLoop();
351                 w.requestAnimFrame(callback);
352             };
353             //cc.log(window.requestAnimFrame);
354             w.requestAnimFrame(callback);
355         } else {
356             callback = function () {
357                 director.mainLoop();
358             };
359             setInterval(callback, this._animationInterval * 1000);
360         }
361         return 0;
362     }
363 });
364 
365 /**
366  * Get current applicaiton instance.
367  * @return {cc.Application}  Current application instance pointer.
368  */
369 cc.Application.getInstance = function () {
370     cc.Assert(cc._sharedApplication, "sharedApplication");
371     return cc._sharedApplication;
372 };
373 
374 /**
375  * Get current language config
376  * @return {Number} Current language config
377  */
378 cc.Application.getCurrentLanguage = function () {
379     var ret = cc.LANGUAGE_ENGLISH;
380 
381     var currentLang = navigator.language;
382     if(!currentLang)
383         currentLang = navigator.browserLanguage || navigator.userLanguage;
384     if(!currentLang)
385         return ret;
386 
387     currentLang = currentLang.toLowerCase();
388     switch (currentLang) {
389         case "zh-cn":
390             ret = cc.LANGUAGE_CHINESE;
391             break;
392         case "fr":
393             ret = cc.LANGUAGE_FRENCH;
394             break;
395         case "it":
396             ret = cc.LANGUAGE_ITALIAN;
397             break;
398         case "de":
399             ret = cc.LANGUAGE_GERMAN;
400             break;
401         case "es":
402             ret = cc.LANGUAGE_SPANISH;
403             break;
404         case "ru":
405             ret = cc.LANGUAGE_RUSSIAN;
406             break;
407         case "ko":
408             ret = cc.LANGUAGE_KOREAN;
409             break;
410         case "ja":
411             ret = cc.LANGUAGE_JAPANESE;
412             break;
413         case "hu":
414             ret = cc.LANGUAGE_HUNGARIAN;
415             break;
416         case "pt":
417             ret = cc.LANGUAGE_PORTUGUESE;
418             break;
419         case "ar":
420             ret = cc.LANGUAGE_ARABIC;
421             break;
422         case "no":
423             ret = cc.LANGUAGE_NORWEGIAN;
424             break;
425         case "pl":
426             ret = cc.LANGUAGE_POLISH;
427             break;
428     }
429 
430     return ret;
431 };
432 
433 cc._sharedApplication = null;
434