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