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