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 * @ignore 29 */ 30 cc.Touches = []; 31 cc.TouchesIntergerDict = {}; 32 33 /** 34 * cc.view is the shared view object. 35 * @namespace 36 * @name cc.view 37 */ 38 cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ 39 _delegate: null, 40 // Size of parent node that contains cc.container and cc._canvas 41 _frameSize: null, 42 // resolution size, it is the size appropriate for the app resources. 43 _designResolutionSize: null, 44 _originalDesignResolutionSize: null, 45 // Viewport is the container's rect related to content's coordinates in pixel 46 _viewPortRect: null, 47 // The visible rect in content's coordinate in point 48 _visibleRect: null, 49 _retinaEnabled: false, 50 _autoFullScreen: true, 51 // The device's pixel ratio (for retina displays) 52 _devicePixelRatio: 1, 53 // the view name 54 _viewName: "", 55 // Custom callback for resize event 56 _resizeCallback: null, 57 _scaleX: 1, 58 _originalScaleX: 1, 59 _scaleY: 1, 60 _originalScaleY: 1, 61 _indexBitsUsed: 0, 62 _maxTouches: 5, 63 _resolutionPolicy: null, 64 _rpExactFit: null, 65 _rpShowAll: null, 66 _rpNoBorder: null, 67 _rpFixedHeight: null, 68 _rpFixedWidth: null, 69 _initialized: false, 70 71 _captured: false, 72 _wnd: null, 73 _hDC: null, 74 _hRC: null, 75 _supportTouch: false, 76 _contentTranslateLeftTop: null, 77 78 // Parent node that contains cc.container and cc._canvas 79 _frame: null, 80 _frameZoomFactor: 1.0, 81 __resizeWithBrowserSize: false, 82 _isAdjustViewPort: true, 83 84 ctor: function () { 85 var _t = this, d = document, _strategyer = cc.ContainerStrategy, _strategy = cc.ContentStrategy; 86 _t._frame = (cc.container.parentNode === d.body) ? d.documentElement : cc.container.parentNode; 87 _t._frameSize = cc.size(0, 0); 88 _t._initFrameSize(); 89 90 var w = cc._canvas.width, h = cc._canvas.height; 91 _t._designResolutionSize = cc.size(w, h); 92 _t._originalDesignResolutionSize = cc.size(w, h); 93 _t._viewPortRect = cc.rect(0, 0, w, h); 94 _t._visibleRect = cc.rect(0, 0, w, h); 95 _t._contentTranslateLeftTop = {left: 0, top: 0}; 96 _t._viewName = "Cocos2dHTML5"; 97 98 var sys = cc.sys; 99 _t.enableRetina(sys.os == sys.OS_IOS || sys.os == sys.OS_OSX); 100 cc.visibleRect && cc.visibleRect.init(_t._visibleRect); 101 102 // Setup system default resolution policies 103 _t._rpExactFit = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.EXACT_FIT); 104 _t._rpShowAll = new cc.ResolutionPolicy(_strategyer.PROPORTION_TO_FRAME, _strategy.SHOW_ALL); 105 _t._rpNoBorder = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.NO_BORDER); 106 _t._rpFixedHeight = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_HEIGHT); 107 _t._rpFixedWidth = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_WIDTH); 108 109 _t._hDC = cc._canvas; 110 _t._hRC = cc._renderContext; 111 }, 112 113 // Resize helper functions 114 _resizeEvent: function () { 115 var width = this._originalDesignResolutionSize.width; 116 var height = this._originalDesignResolutionSize.height; 117 if (this._resizeCallback) { 118 this._initFrameSize(); 119 this._resizeCallback.call(); 120 } 121 if (width > 0) 122 this.setDesignResolutionSize(width, height, this._resolutionPolicy); 123 }, 124 125 resizeWithBrowserSize: function (enabled) { 126 var adjustSize, _t = this; 127 if (enabled) { 128 //enable 129 if (!_t.__resizeWithBrowserSize) { 130 _t.__resizeWithBrowserSize = true; 131 adjustSize = _t._resizeEvent.bind(_t); 132 cc._addEventListener(window, 'resize', adjustSize, false); 133 } 134 } else { 135 //disable 136 if (_t.__resizeWithBrowserSize) { 137 _t.__resizeWithBrowserSize = true; 138 adjustSize = _t._resizeEvent.bind(_t); 139 window.removeEventListener('resize', adjustSize, false); 140 } 141 } 142 }, 143 144 setResizeCallback: function (callback) { 145 if (typeof callback == "function" || callback == null) { 146 this._resizeCallback = callback; 147 } 148 }, 149 150 _initFrameSize: function () { 151 var locFrameSize = this._frameSize; 152 locFrameSize.width = this._frame.clientWidth; 153 locFrameSize.height = this._frame.clientHeight; 154 }, 155 156 // hack 157 _adjustSizeKeepCanvasSize: function () { 158 var designWidth = this._originalDesignResolutionSize.width; 159 var designHeight = this._originalDesignResolutionSize.height; 160 if (designWidth > 0) 161 this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy); 162 }, 163 164 _setViewPortMeta: function (width, height) { 165 if (this._isAdjustViewPort) { 166 var viewportMetas = {"user-scalable": "no", "maximum-scale": "1.0", "initial-scale": "1.0"}, elems = document.getElementsByName("viewport"), vp, content; 167 if (elems.length == 0) { 168 vp = cc.newElement("meta"); 169 vp.name = "viewport"; 170 vp.content = ""; 171 document.head.appendChild(vp); 172 } 173 else vp = elems[0]; 174 175 // For avoiding Android Firefox issue, to remove once firefox fixes its issue. 176 if (cc.sys.isMobile && cc.sys.browserType == cc.sys.BROWSER_TYPE_FIREFOX) { 177 vp.content = "initial-scale:1"; 178 return; 179 } 180 181 content = vp.content; 182 for (var key in viewportMetas) { 183 var pattern = new RegExp(key); 184 if (!pattern.test(content)) { 185 content += (content == "" ? "" : ",") + key + "=" + viewportMetas[key]; 186 } 187 } 188 /* 189 if(width<=320){ 190 width = 321; 191 } 192 if(height) 193 content ="height="+height+","+content; 194 if(width) 195 content ="width="+width+","+content; 196 */ 197 vp.content = content; 198 } 199 }, 200 201 // RenderTexture hacker 202 _setScaleXYForRenderTexture: function () { 203 //hack for RenderTexture on canvas mode when adapting multiple resolution resources 204 var scaleFactor = cc.contentScaleFactor(); 205 this._scaleX = scaleFactor; 206 this._scaleY = scaleFactor; 207 }, 208 209 // Other helper functions 210 _resetScale: function () { 211 this._scaleX = this._originalScaleX; 212 this._scaleY = this._originalScaleY; 213 }, 214 215 // Useless, just make sure the compatibility temporarily, should be removed 216 _adjustSizeToBrowser: function () { 217 }, 218 219 /** 220 * init 221 */ 222 initialize: function () { 223 this._initialized = true; 224 }, 225 226 adjustViewPort: function (enabled) { 227 this._isAdjustViewPort = enabled; 228 }, 229 230 /** 231 * Retina support is enabled by default for Apple device but disabled for other devices, 232 * it takes effect only when you called setDesignResolutionPolicy 233 * @param {Boolean} enabled Enable or disable retina display 234 */ 235 enableRetina: function(enabled) { 236 this._retinaEnabled = enabled ? true : false; 237 }, 238 239 /** 240 * Check whether retina display is enabled. 241 * @return {Boolean} 242 */ 243 isRetinaEnabled: function() { 244 return this._retinaEnabled; 245 }, 246 247 /** 248 * If enabled, the application will try automatically to enter full screen mode on mobile devices 249 * You can pass true as parameter to enable it and disable it by passing false 250 * @param {Boolean} enabled Enable or disable auto full screen on mobile devices 251 */ 252 enableAutoFullScreen: function(enabled) { 253 this._autoFullScreen = enabled ? true : false; 254 }, 255 256 /** 257 * Check whether auto full screen is enabled. 258 * @return {Boolean} 259 */ 260 isAutoFullScreenEnabled: function() { 261 return this._autoFullScreen; 262 }, 263 264 /** 265 * Force destroying EGL view, subclass must implement this method. 266 */ 267 end: function () { 268 }, 269 270 /** 271 * Get whether render system is ready(no matter opengl or canvas), 272 * this name is for the compatibility with cocos2d-x, subclass must implement this method. 273 * @return {Boolean} 274 */ 275 isOpenGLReady: function () { 276 return (this._hDC != null && this._hRC != null); 277 }, 278 279 /* 280 * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop. 281 * @param {Number} zoomFactor 282 */ 283 setFrameZoomFactor: function (zoomFactor) { 284 this._frameZoomFactor = zoomFactor; 285 this.centerWindow(); 286 cc.director.setProjection(cc.director.getProjection()); 287 }, 288 289 /** 290 * Exchanges the front and back buffers, subclass must implement this method. 291 */ 292 swapBuffers: function () { 293 }, 294 295 /** 296 * Open or close IME keyboard , subclass must implement this method. 297 */ 298 setIMEKeyboardState: function (isOpen) { 299 }, 300 301 /** 302 * <p> 303 * The resolution translate on EGLView 304 * </p> 305 * @param {Number} offsetLeft 306 * @param {Number} offsetTop 307 */ 308 setContentTranslateLeftTop: function (offsetLeft, offsetTop) { 309 this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop}; 310 }, 311 312 /** 313 * <p> 314 * get the resolution translate on EGLView 315 * </p> 316 * @return {cc.Size|Object} 317 */ 318 getContentTranslateLeftTop: function () { 319 return this._contentTranslateLeftTop; 320 }, 321 322 /** 323 * Get the frame size of EGL view. 324 * In general, it returns the screen size since the EGL view is a fullscreen view. 325 * @return {cc.Size} 326 */ 327 getFrameSize: function () { 328 return cc.size(this._frameSize.width, this._frameSize.height); 329 }, 330 331 /** 332 * Set the frame size of EGL view. 333 * @param {Number} width 334 * @param {Number} height 335 */ 336 setFrameSize: function (width, height) { 337 this._frameSize.width = width; 338 this._frameSize.height = height; 339 this._frame.style.width = width + "px"; 340 this._frame.style.height = height + "px"; 341 //this.centerWindow(); 342 this._resizeEvent(); 343 cc.director.setProjection(cc.director.getProjection()); 344 }, 345 346 centerWindow: function () { 347 }, 348 349 /** 350 * Get the visible area size of OpenGL view port. 351 * @return {cc.Size} 352 */ 353 getVisibleSize: function () { 354 return cc.size(this._visibleRect.width,this._visibleRect.height); 355 }, 356 357 /** 358 * Get the visible origin of OpenGL view port. 359 * @return {cc.Point} 360 */ 361 getVisibleOrigin: function () { 362 return cc.p(this._visibleRect.x,this._visibleRect.y); 363 }, 364 365 canSetContentScaleFactor: function () { 366 return true; 367 }, 368 369 /** 370 * Get the current resolution policy 371 * @return {cc.ResolutionPolicy} 372 */ 373 getResolutionPolicy: function () { 374 return this._resolutionPolicy; 375 }, 376 377 /** 378 * Set the current resolution policy 379 * @param {cc.ResolutionPolicy|Number} resolutionPolicy 380 */ 381 setResolutionPolicy: function (resolutionPolicy) { 382 var _t = this; 383 if (resolutionPolicy instanceof cc.ResolutionPolicy) { 384 _t._resolutionPolicy = resolutionPolicy; 385 } 386 // Ensure compatibility with JSB 387 else { 388 var _locPolicy = cc.ResolutionPolicy; 389 if(resolutionPolicy === _locPolicy.EXACT_FIT) 390 _t._resolutionPolicy = _t._rpExactFit; 391 if(resolutionPolicy === _locPolicy.SHOW_ALL) 392 _t._resolutionPolicy = _t._rpShowAll; 393 if(resolutionPolicy === _locPolicy.NO_BORDER) 394 _t._resolutionPolicy = _t._rpNoBorder; 395 if(resolutionPolicy === _locPolicy.FIXED_HEIGHT) 396 _t._resolutionPolicy = _t._rpFixedHeight; 397 if(resolutionPolicy === _locPolicy.FIXED_WIDTH) 398 _t._resolutionPolicy = _t._rpFixedWidth; 399 } 400 }, 401 402 /** 403 * Set the design resolution size. 404 * @param {Number} width Design resolution width. 405 * @param {Number} height Design resolution height. 406 * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired, you may choose: 407 * [1] ResolutionExactFit Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched. 408 * [2] ResolutionNoBorder Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut. 409 * [3] ResolutionShowAll Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown. 410 * [4] ResolutionFixedHeight Scale the content's height to screen's height and proportionally scale its width 411 * [5] ResolutionFixedWidth Scale the content's width to screen's width and proportionally scale its height 412 * [cc.ResolutionPolicy] Custom resolution policy, constructed by cc.ResolutionPolicy 413 */ 414 setDesignResolutionSize: function (width, height, resolutionPolicy) { 415 // Defensive code 416 if (isNaN(width) || width == 0 || isNaN(height) || height == 0) { 417 cc.log(cc._LogInfos.EGLView_setDesignResolutionSize); 418 return; 419 } 420 var _t = this; 421 _t.setResolutionPolicy(resolutionPolicy); 422 var policy = _t._resolutionPolicy; 423 if (policy) 424 policy.preApply(_t); 425 else { 426 cc.log(cc._LogInfos.EGLView_setDesignResolutionSize_2); 427 return; 428 } 429 430 // Reinit frame size 431 var frameW = _t._frameSize.width, frameH = _t._frameSize.height; 432 if (cc.sys.isMobile) 433 _t._setViewPortMeta(_t._frameSize.width, _t._frameSize.height); 434 _t._initFrameSize(); 435 // No change 436 if (resolutionPolicy == _t._resolutionPolicy 437 && width == _t._originalDesignResolutionSize.width && height == _t._originalDesignResolutionSize.height 438 && frameW == _t._frameSize.width && frameH == _t._frameSize.height) 439 return; 440 _t._designResolutionSize = cc.size(width, height); 441 _t._originalDesignResolutionSize = cc.size(width, height); 442 443 var result = policy.apply(_t, _t._designResolutionSize); 444 if (result.scale && result.scale.length == 2) { 445 _t._scaleX = result.scale[0]; 446 _t._scaleY = result.scale[1]; 447 } 448 if (result.viewport) { 449 var vp = _t._viewPortRect = result.viewport, visible = _t._visibleRect; 450 visible.width = cc._canvas.width / _t._scaleX; 451 visible.height = cc._canvas.height / _t._scaleY; 452 visible.x = -vp.x / _t._scaleX; 453 visible.y = -vp.y / _t._scaleY; 454 } 455 456 // reset director's member variables to fit visible rect 457 var director = cc.director; 458 cc.winSize.width = director._winSizeInPoints.width = _t._visibleRect.width; 459 cc.winSize.height = director._winSizeInPoints.height = _t._visibleRect.height; 460 461 policy.postApply(_t); 462 463 if (cc._renderType == cc._RENDER_TYPE_WEBGL) { 464 // reset director's member variables to fit visible rect 465 director._createStatsLabel(); 466 director.setGLDefaultValues(); 467 } 468 469 _t._originalScaleX = _t._scaleX; 470 _t._originalScaleY = _t._scaleY; 471 // For editbox 472 if (cc.DOM) 473 cc.DOM._resetEGLViewDiv(); 474 cc.visibleRect && cc.visibleRect.init(_t._visibleRect); 475 }, 476 477 /** 478 * Get design resolution size. 479 * Default resolution size is the same as 'getFrameSize'. 480 * @return {cc.Size} 481 */ 482 getDesignResolutionSize: function () { 483 return cc.size(this._designResolutionSize.width, this._designResolutionSize.height); 484 }, 485 486 /** 487 * Set opengl view port rectangle with points. 488 * @param {Number} x 489 * @param {Number} y 490 * @param {Number} w width 491 * @param {Number} h height 492 */ 493 setViewPortInPoints: function (x, y, w, h) { 494 var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY; 495 cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor), 496 (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor), 497 (w * locScaleX * locFrameZoomFactor), 498 (h * locScaleY * locFrameZoomFactor)); 499 }, 500 501 /** 502 * Set Scissor rectangle with points. 503 * @param {Number} x 504 * @param {Number} y 505 * @param {Number} w 506 * @param {Number} h 507 */ 508 setScissorInPoints: function (x, y, w, h) { 509 var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY; 510 cc._renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor), 511 (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor), 512 (w * locScaleX * locFrameZoomFactor), 513 (h * locScaleY * locFrameZoomFactor)); 514 }, 515 516 /** 517 * Get whether GL_SCISSOR_TEST is enable 518 */ 519 isScissorEnabled: function () { 520 var gl = cc._renderContext; 521 return gl.isEnabled(gl.SCISSOR_TEST); 522 }, 523 524 /** 525 * Get the current scissor rectangle 526 * @return {cc.Rect} 527 */ 528 getScissorRect: function () { 529 var gl = cc._renderContext, scaleX = this._scaleX, scaleY = this._scaleY; 530 var boxArr = gl.getParameter(gl.SCISSOR_BOX); 531 return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY, 532 boxArr[2] / scaleX, boxArr[3] / scaleY); 533 }, 534 535 /** 536 * @param {String} viewName 537 */ 538 setViewName: function (viewName) { 539 if (viewName != null && viewName.length > 0) { 540 this._viewName = viewName; 541 } 542 }, 543 544 /** 545 * get view name 546 * @return {String} 547 */ 548 getViewName: function () { 549 return this._viewName; 550 }, 551 552 /** 553 * Get the opengl view port rectangle. 554 */ 555 getViewPortRect: function () { 556 return this._viewPortRect; 557 }, 558 559 /** 560 * Get scale factor of the horizontal direction. 561 */ 562 getScaleX: function () { 563 return this._scaleX; 564 }, 565 566 /** 567 * Get scale factor of the vertical direction. 568 */ 569 getScaleY: function () { 570 return this._scaleY; 571 }, 572 573 /** 574 * Get device pixel ratio for retina display. 575 */ 576 getDevicePixelRatio: function() { 577 return this._devicePixelRatio; 578 }, 579 580 /** 581 * Get the real location in view 582 */ 583 convertToLocationInView: function (tx, ty, relatedPos) { 584 return {x: this._devicePixelRatio * (tx - relatedPos.left), y: this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty)}; 585 }, 586 587 _convertMouseToLocationInView: function(point, relatedPos) { 588 var locViewPortRect = this._viewPortRect, _t = this; 589 point.x = ((_t._devicePixelRatio * (point.x - relatedPos.left)) - locViewPortRect.x) / _t._scaleX; 590 point.y = (_t._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - locViewPortRect.y) / _t._scaleY; 591 }, 592 593 _convertTouchesWithScale: function(touches){ 594 var locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY, selTouch, selPoint, selPrePoint; 595 for( var i = 0; i < touches.length; i ++){ 596 selTouch = touches[i]; 597 selPoint = selTouch._point; 598 selPrePoint = selTouch._prevPoint; 599 selTouch._setPoint((selPoint.x - locViewPortRect.x) / locScaleX, 600 (selPoint.y - locViewPortRect.y) / locScaleY); 601 selTouch._setPrevPoint((selPrePoint.x - locViewPortRect.x) / locScaleX, 602 (selPrePoint.y - locViewPortRect.y) / locScaleY); 603 } 604 } 605 }); 606 607 cc.EGLView._getInstance = function () { 608 if (!this._instance) { 609 this._instance = this._instance || new cc.EGLView(); 610 this._instance.initialize(); 611 } 612 return this._instance; 613 }; 614 615 /** 616 * <p>cc.ContainerStrategy class is the root strategy class of container's scale strategy, 617 * it controls the behavior of how to scale the cc.container and cc._canvas object</p> 618 * 619 * @class 620 * @extends cc.Class 621 */ 622 cc.ContainerStrategy = cc.Class.extend(/** @lends cc.ContainerStrategy# */{ 623 /** 624 * Manipulation before appling the strategy 625 * @param {cc.view} The target view 626 */ 627 preApply: function (view) { 628 }, 629 630 /** 631 * Function to apply this strategy 632 * @param {cc.view} view 633 * @param {cc.Size} designedResolution 634 */ 635 apply: function (view, designedResolution) { 636 }, 637 638 /** 639 * Manipulation after applying the strategy 640 * @param {cc.view} view The target view 641 */ 642 postApply: function (view) { 643 644 }, 645 646 _setupContainer: function (view, w, h) { 647 var frame = view._frame; 648 if (cc.view._autoFullScreen && cc.sys.isMobile && frame == document.documentElement) { 649 // Automatically full screen when user touches on mobile version 650 cc.screen.autoFullScreen(frame); 651 } 652 653 var locCanvasElement = cc._canvas, locContainer = cc.container; 654 // Setup container 655 locContainer.style.width = locCanvasElement.style.width = w + "px"; 656 locContainer.style.height = locCanvasElement.style.height = h + "px"; 657 // Setup pixel ratio for retina display 658 var devicePixelRatio = view._devicePixelRatio = 1; 659 if (view.isRetinaEnabled()) 660 devicePixelRatio = view._devicePixelRatio = window.devicePixelRatio || 1; 661 // Setup canvas 662 locCanvasElement.width = w * devicePixelRatio; 663 locCanvasElement.height = h * devicePixelRatio; 664 665 var body = document.body, style; 666 if (body && (style = body.style)) { 667 style.paddingTop = style.paddingTop || "0px"; 668 style.paddingRight = style.paddingRight || "0px"; 669 style.paddingBottom = style.paddingBottom || "0px"; 670 style.paddingLeft = style.paddingLeft || "0px"; 671 style.borderTop = style.borderTop || "0px"; 672 style.borderRight = style.borderRight || "0px"; 673 style.borderBottom = style.borderBottom || "0px"; 674 style.borderLeft = style.borderLeft || "0px"; 675 style.marginTop = style.marginTop || "0px"; 676 style.marginRight = style.marginRight || "0px"; 677 style.marginBottom = style.marginBottom || "0px"; 678 style.marginLeft = style.marginLeft || "0px"; 679 } 680 }, 681 682 _fixContainer: function () { 683 // Add container to document body 684 document.body.insertBefore(cc.container, document.body.firstChild); 685 // Set body's width height to window's size, and forbid overflow, so that game will be centered 686 var bs = document.body.style; 687 bs.width = window.innerWidth + "px"; 688 bs.height = window.innerHeight + "px"; 689 bs.overflow = "hidden"; 690 // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container 691 var contStyle = cc.container.style; 692 contStyle.position = "fixed"; 693 contStyle.left = contStyle.top = "0px"; 694 // Reposition body 695 document.body.scrollTop = 0; 696 } 697 }); 698 699 /** 700 * <p>cc.ContentStrategy class is the root strategy class of content's scale strategy, 701 * it controls the behavior of how to scale the scene and setup the viewport for the game</p> 702 * 703 * @class 704 * @extends cc.Class 705 */ 706 cc.ContentStrategy = cc.Class.extend(/** @lends cc.ContentStrategy# */{ 707 708 _result: { 709 scale: [1, 1], 710 viewport: null 711 }, 712 713 _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) { 714 // Makes content fit better the canvas 715 Math.abs(containerW - contentW) < 2 && (contentW = containerW); 716 Math.abs(containerH - contentH) < 2 && (contentH = containerH); 717 718 var viewport = cc.rect(Math.round((containerW - contentW) / 2), 719 Math.round((containerH - contentH) / 2), 720 contentW, contentH); 721 722 // Translate the content 723 if (cc._renderType == cc._RENDER_TYPE_CANVAS) 724 cc._renderContext.translate(viewport.x, viewport.y + contentH); 725 726 this._result.scale = [scaleX, scaleY]; 727 this._result.viewport = viewport; 728 return this._result; 729 }, 730 731 /** 732 * Manipulation before applying the strategy 733 * @param {cc.view} view The target view 734 */ 735 preApply: function (view) { 736 }, 737 738 /** 739 * Function to apply this strategy 740 * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}}, 741 * The target view can then apply these value to itself, it's preferred not to modify directly its private variables 742 * @param {cc.view} view 743 * @param {cc.Size} designedResolution 744 * @return {object} scaleAndViewportRect 745 */ 746 apply: function (view, designedResolution) { 747 return {"scale": [1, 1]}; 748 }, 749 750 /** 751 * Manipulation after applying the strategy 752 * @param {cc.view} view The target view 753 */ 754 postApply: function (view) { 755 } 756 }); 757 758 (function () { 759 760 // Container scale strategys 761 var EqualToFrame = cc.ContainerStrategy.extend({ 762 apply: function (view) { 763 this._setupContainer(view, view._frameSize.width, view._frameSize.height); 764 } 765 }); 766 767 var ProportionalToFrame = cc.ContainerStrategy.extend({ 768 apply: function (view, designedResolution) { 769 var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style, 770 designW = designedResolution.width, designH = designedResolution.height, 771 scaleX = frameW / designW, scaleY = frameH / designH, 772 containerW, containerH; 773 774 scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH); 775 776 // Adjust container size with integer value 777 var offx = Math.round((frameW - containerW) / 2); 778 var offy = Math.round((frameH - containerH) / 2); 779 containerW = frameW - 2 * offx; 780 containerH = frameH - 2 * offy; 781 782 this._setupContainer(view, containerW, containerH); 783 // Setup container's margin 784 containerStyle.marginLeft = offx + "px"; 785 containerStyle.marginRight = offx + "px"; 786 containerStyle.marginTop = offy + "px"; 787 containerStyle.marginBottom = offy + "px"; 788 } 789 }); 790 791 var EqualToWindow = EqualToFrame.extend({ 792 preApply: function (view) { 793 this._super(view); 794 view._frame = document.documentElement; 795 }, 796 797 apply: function (view) { 798 this._super(view); 799 this._fixContainer(); 800 } 801 }); 802 803 var ProportionalToWindow = ProportionalToFrame.extend({ 804 preApply: function (view) { 805 this._super(view); 806 view._frame = document.documentElement; 807 }, 808 809 apply: function (view, designedResolution) { 810 this._super(view, designedResolution); 811 this._fixContainer(); 812 } 813 }); 814 815 var OriginalContainer = cc.ContainerStrategy.extend({ 816 apply: function (view) { 817 this._setupContainer(view, cc._canvas.width, cc._canvas.height); 818 } 819 }); 820 821 // #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size 822 // cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow(); 823 // #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size 824 // cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow(); 825 // Alias: Strategy that makes the container's size equals to the frame's size 826 cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame(); 827 // Alias: Strategy that scale proportionally the container's size to frame's size 828 cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame(); 829 // Alias: Strategy that keeps the original container's size 830 cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer(); 831 832 // Content scale strategys 833 var ExactFit = cc.ContentStrategy.extend({ 834 apply: function (view, designedResolution) { 835 var containerW = cc._canvas.width, containerH = cc._canvas.height, 836 scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height; 837 838 return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY); 839 } 840 }); 841 842 var ShowAll = cc.ContentStrategy.extend({ 843 apply: function (view, designedResolution) { 844 var containerW = cc._canvas.width, containerH = cc._canvas.height, 845 designW = designedResolution.width, designH = designedResolution.height, 846 scaleX = containerW / designW, scaleY = containerH / designH, scale = 0, 847 contentW, contentH; 848 849 scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale) 850 : (scale = scaleY, contentW = designW * scale, contentH = containerH); 851 852 return this._buildResult(containerW, containerH, contentW, contentH, scale, scale); 853 } 854 }); 855 856 var NoBorder = cc.ContentStrategy.extend({ 857 apply: function (view, designedResolution) { 858 var containerW = cc._canvas.width, containerH = cc._canvas.height, 859 designW = designedResolution.width, designH = designedResolution.height, 860 scaleX = containerW / designW, scaleY = containerH / designH, scale, 861 contentW, contentH; 862 863 scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH) 864 : (scale = scaleX, contentW = containerW, contentH = designH * scale); 865 866 return this._buildResult(containerW, containerH, contentW, contentH, scale, scale); 867 } 868 }); 869 870 var FixedHeight = cc.ContentStrategy.extend({ 871 apply: function (view, designedResolution) { 872 var containerW = cc._canvas.width, containerH = cc._canvas.height, 873 designH = designedResolution.height, scale = containerH / designH, 874 contentW = containerW, contentH = containerH; 875 876 return this._buildResult(containerW, containerH, contentW, contentH, scale, scale); 877 }, 878 879 postApply: function (view) { 880 cc.director._winSizeInPoints = view.getVisibleSize(); 881 } 882 }); 883 884 var FixedWidth = cc.ContentStrategy.extend({ 885 apply: function (view, designedResolution) { 886 var containerW = cc._canvas.width, containerH = cc._canvas.height, 887 designW = designedResolution.width, scale = containerW / designW, 888 contentW = containerW, contentH = containerH; 889 890 return this._buildResult(containerW, containerH, contentW, contentH, scale, scale); 891 }, 892 893 postApply: function (view) { 894 cc.director._winSizeInPoints = view.getVisibleSize(); 895 } 896 }); 897 898 // Alias: Strategy to scale the content's size to container's size, non proportional 899 cc.ContentStrategy.EXACT_FIT = new ExactFit(); 900 // Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible 901 cc.ContentStrategy.SHOW_ALL = new ShowAll(); 902 // Alias: Strategy to scale the content's size proportionally to fill the whole container area 903 cc.ContentStrategy.NO_BORDER = new NoBorder(); 904 // Alias: Strategy to scale the content's height to container's height and proportionally scale its width 905 cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight(); 906 // Alias: Strategy to scale the content's width to container's width and proportionally scale its height 907 cc.ContentStrategy.FIXED_WIDTH = new FixedWidth(); 908 909 })(); 910 911 /** 912 * <p>cc.ResolutionPolicy class is the root strategy class of scale strategy, 913 * its main task is to maintain the compatibility with Cocos2d-x</p> 914 * 915 * @class 916 * @extends cc.Class 917 */ 918 cc.ResolutionPolicy = cc.Class.extend(/** @lends cc.ResolutionPolicy# */{ 919 _containerStrategy: null, 920 _contentStrategy: null, 921 922 ctor: function (containerStg, contentStg) { 923 this.setContainerStrategy(containerStg); 924 this.setContentStrategy(contentStg); 925 }, 926 927 /** 928 * Manipulation before applying the resolution policy 929 * @param {cc.view} view The target view 930 */ 931 preApply: function (view) { 932 this._containerStrategy.preApply(view); 933 this._contentStrategy.preApply(view); 934 }, 935 936 /** 937 * Function to apply this resolution policy 938 * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}}, 939 * The target view can then apply these value to itself, it's preferred not to modify directly its private variables 940 * @param {cc.view} view The target view 941 * @param {cc.Size} designedResolution The user defined design resolution 942 * @return {object} An object contains the scale X/Y values and the viewport rect 943 */ 944 apply: function (view, designedResolution) { 945 this._containerStrategy.apply(view, designedResolution); 946 return this._contentStrategy.apply(view, designedResolution); 947 }, 948 949 /** 950 * Manipulation after appyling the strategy 951 * @param {cc.view} view The target view 952 */ 953 postApply: function (view) { 954 this._containerStrategy.postApply(view); 955 this._contentStrategy.postApply(view); 956 }, 957 958 /** 959 * Setup the container's scale strategy 960 * @param {cc.ContainerStrategy} containerStg 961 */ 962 setContainerStrategy: function (containerStg) { 963 if (containerStg instanceof cc.ContainerStrategy) 964 this._containerStrategy = containerStg; 965 }, 966 967 /** 968 * Setup the content's scale strategy 969 * @param {cc.ContentStrategy} contentStg 970 */ 971 setContentStrategy: function (contentStg) { 972 if (contentStg instanceof cc.ContentStrategy) 973 this._contentStrategy = contentStg; 974 } 975 }); 976 977 /* 978 * @memberOf cc.ResolutionPolicy# 979 * @name EXACT_FIT 980 * @const 981 * @static 982 * The entire application is visible in the specified area without trying to preserve the original aspect ratio.<br/> 983 * Distortion can occur, and the application may appear stretched or compressed. 984 */ 985 cc.ResolutionPolicy.EXACT_FIT = 0; 986 987 /* 988 * @memberOf cc.ResolutionPolicy# 989 * @name NO_BORDER 990 * @const 991 * @static 992 * The entire application fills the specified area, without distortion but possibly with some cropping,<br/> 993 * while maintaining the original aspect ratio of the application. 994 */ 995 cc.ResolutionPolicy.NO_BORDER = 1; 996 997 /* 998 * @memberOf cc.ResolutionPolicy# 999 * @name SHOW_ALL 1000 * @const 1001 * @static 1002 * The entire application is visible in the specified area without distortion while maintaining the original<br/> 1003 * aspect ratio of the application. Borders can appear on two sides of the application. 1004 */ 1005 cc.ResolutionPolicy.SHOW_ALL = 2; 1006 1007 /* 1008 * @memberOf cc.ResolutionPolicy# 1009 * @name FIXED_HEIGHT 1010 * @const 1011 * @static 1012 * The application takes the height of the design resolution size and modifies the width of the internal<br/> 1013 * canvas so that it fits the aspect ratio of the device<br/> 1014 * no distortion will occur however you must make sure your application works on different<br/> 1015 * aspect ratios 1016 */ 1017 cc.ResolutionPolicy.FIXED_HEIGHT = 3; 1018 1019 /* 1020 * @memberOf cc.ResolutionPolicy# 1021 * @name FIXED_WIDTH 1022 * @const 1023 * @static 1024 * The application takes the width of the design resolution size and modifies the height of the internal<br/> 1025 * canvas so that it fits the aspect ratio of the device<br/> 1026 * no distortion will occur however you must make sure your application works on different<br/> 1027 * aspect ratios 1028 */ 1029 cc.ResolutionPolicy.FIXED_WIDTH = 4; 1030 1031 /* 1032 * @memberOf cc.ResolutionPolicy# 1033 * @name UNKNOWN 1034 * @const 1035 * @static 1036 * Unknow policy 1037 */ 1038 cc.ResolutionPolicy.UNKNOWN = 5;