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