1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 4 http://www.cocos2d-x.org 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 ****************************************************************************/ 24 /** 25 * layoutBackGround color type 26 * @type {Object} 27 */ 28 ccs.LayoutBackGroundColorType = { 29 none: 0, 30 solid: 1, 31 gradient: 2 32 }; 33 34 /** 35 * Layout type 36 * @type {Object} 37 */ 38 ccs.LayoutType = { 39 absolute: 0, 40 linearVertical: 1, 41 linearHorizontal: 2, 42 relative: 3 43 }; 44 45 /** 46 * Layout type 47 * @type {Object} 48 */ 49 ccs.LayoutClippingType = { 50 stencil: 0, 51 scissor: 1 52 }; 53 54 ccs.BACKGROUNDIMAGEZ = -2; 55 ccs.BACKGROUNDCOLORRENDERERZ = -2; 56 /** 57 * Base class for ccs.Layout 58 * @class 59 * @extends ccs.Widget 60 */ 61 ccs.Layout = ccs.Widget.extend(/** @lends ccs.Layout# */{ 62 _clippingEnabled: null, 63 _backGroundScale9Enabled: null, 64 _backGroundImage: null, 65 _backGroundImageFileName: null, 66 _backGroundImageCapInsets: null, 67 _colorType: null, 68 _bgImageTexType: null, 69 _colorRender: null, 70 _gradientRender: null, 71 _color: null, 72 _startColor: null, 73 _endColor: null, 74 _alongVector: null, 75 _opacity: null, 76 _backGroundImageTextureSize: null, 77 _layoutType: null, 78 _doLayoutDirty: false, 79 _clippingRectDirty: false, 80 _clippingType : null, 81 _clippingStencil: null, 82 _handleScissor: false, 83 _scissorRectDirty: false, 84 _clippingRect: null, 85 _clippingParent: null, 86 _backGroundImageColor:null, 87 _backGroundImageOpacity:null, 88 ctor: function () { 89 ccs.Widget.prototype.ctor.call(this); 90 this._clippingEnabled = false; 91 this._backGroundScale9Enabled = false; 92 this._backGroundImage = null; 93 this._backGroundImageFileName = ""; 94 this._backGroundImageCapInsets = cc.RectZero(); 95 this._colorType = ccs.LayoutBackGroundColorType.none; 96 this._bgImageTexType = ccs.TextureResType.local; 97 this._colorRender = null; 98 this._gradientRender = null; 99 this._color = cc.white(); 100 this._startColor = cc.white(); 101 this._endColor = cc.white(); 102 this._alongVector = cc.p(0, -1); 103 this._opacity = 255; 104 this._backGroundImageTextureSize = cc.SizeZero(); 105 this._layoutType = ccs.LayoutType.absolute; 106 this._widgetType = ccs.WidgetType.container; 107 this._doLayoutDirty = true; 108 this._clippingRectDirty = true; 109 this._clippingType = ccs.LayoutClippingType.stencil; 110 this._clippingStencil = null; 111 this._handleScissor = false; 112 this._scissorRectDirty = false; 113 this._clippingRect = cc.rect(0, 0, 0, 0); 114 this._clippingParent = null; 115 this._backGroundImageColor = cc.c3b(255, 255, 255); 116 this._backGroundImageOpacity = 255; 117 }, 118 init: function () { 119 if (cc.Node.prototype.init.call(this)){ 120 this._layoutParameterDictionary = {}; 121 this._widgetChildren = []; 122 this.initRenderer(); 123 this.ignoreContentAdaptWithSize(false); 124 this.setSize(cc.SizeZero()); 125 this.setBright(true); 126 this.setAnchorPoint(0, 0); 127 this.initStencil(); 128 return true; 129 } 130 return false; 131 }, 132 initStencil : null, 133 _initStencilForWebGL:function(){ 134 this._clippingStencil = cc.DrawNode.create(); 135 ccs.Layout._init_once = true; 136 if (ccs.Layout._init_once) { 137 cc.stencilBits = cc.renderContext.getParameter(cc.renderContext.STENCIL_BITS); 138 if (cc.stencilBits <= 0) 139 cc.log("Stencil buffer is not enabled."); 140 ccs.Layout._init_once = false; 141 } 142 }, 143 _initStencilForCanvas: function () { 144 this._clippingStencil = cc.DrawNode.create(); 145 var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY(); 146 var locContext = cc.renderContext; 147 var stencil = this._clippingStencil; 148 stencil.draw = function () { 149 for (var i = 0; i < stencil._buffer.length; i++) { 150 var element = stencil._buffer[i]; 151 var vertices = element.verts; 152 var firstPoint = vertices[0]; 153 locContext.beginPath(); 154 locContext.moveTo(firstPoint.x * locEGL_ScaleX, -firstPoint.y * locEGL_ScaleY); 155 for (var j = 1, len = vertices.length; j < len; j++) 156 locContext.lineTo(vertices[j].x * locEGL_ScaleX, -vertices[j].y * locEGL_ScaleY); 157 } 158 } 159 }, 160 161 /** 162 * Adds a widget to the container. 163 * @param {ccs.Widget} widget 164 * @param {Number} zOrder 165 * @param {Number} tag 166 */ 167 addChild: function (widget, zOrder, tag) { 168 if(!(widget instanceof ccs.Widget)){ 169 throw "the child add to Layout must a type of cc.Widget"; 170 } 171 this.supplyTheLayoutParameterLackToChild(widget); 172 ccs.Widget.prototype.addChild.call(this, widget, zOrder, tag); 173 this._doLayoutDirty = true; 174 }, 175 176 /** 177 * Remove widget 178 * @param {ccs.Widget} widget 179 * @param {Boolean} cleanup 180 */ 181 removeChild:function(widget,cleanup){ 182 ccs.Widget.prototype.removeChild.call(this, widget,cleanup); 183 this._doLayoutDirty = true; 184 }, 185 186 /** 187 * Remove all widget 188 * @param {Boolean} cleanup 189 */ 190 removeAllChildren:function(cleanup){ 191 ccs.Widget.prototype.removeAllChildren.call(this, cleanup); 192 this._doLayoutDirty = true; 193 }, 194 195 /** 196 * Gets if layout is clipping enabled. 197 * @returns {Boolean} 198 */ 199 isClippingEnabled: function () { 200 return this._clippingEnabled; 201 }, 202 203 visit: function (ctx) { 204 if (!this._enabled) { 205 return; 206 } 207 if (this._clippingEnabled) { 208 switch (this._clippingType) { 209 case ccs.LayoutClippingType.stencil: 210 this.stencilClippingVisit(ctx); 211 break; 212 case ccs.LayoutClippingType.scissor: 213 this.scissorClippingVisit(ctx); 214 break; 215 default: 216 break; 217 } 218 } 219 else { 220 cc.Node.prototype.visit.call(this,ctx); 221 } 222 }, 223 224 sortAllChildren: function () { 225 ccs.Widget.prototype.sortAllChildren.call(this); 226 this.doLayout(); 227 }, 228 229 stencilClippingVisit : null, 230 231 _stencilClippingVisitForWebGL: function (ctx) { 232 var gl = ctx || cc.renderContext; 233 234 // if stencil buffer disabled 235 if (cc.stencilBits < 1) { 236 // draw everything, as if there where no stencil 237 cc.Node.prototype.visit.call(this, ctx); 238 return; 239 } 240 241 // return fast (draw nothing, or draw everything if in inverted mode) if: 242 // - nil stencil node 243 // - or stencil node invisible: 244 if (!this._clippingStencil || !this._clippingStencil.isVisible()) { 245 return; 246 } 247 248 // store the current stencil layer (position in the stencil buffer), 249 // this will allow nesting up to n CCClippingNode, 250 // where n is the number of bits of the stencil buffer. 251 ccs.Layout._layer = -1; 252 253 // all the _stencilBits are in use? 254 if (ccs.Layout._layer + 1 == cc.stencilBits) { 255 // warn once 256 ccs.Layout._visit_once = true; 257 if (ccs.Layout._visit_once) { 258 cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its childs."); 259 ccs.Layout._visit_once = false; 260 } 261 // draw everything, as if there where no stencil 262 cc.Node.prototype.visit.call(this, ctx); 263 return; 264 } 265 266 /////////////////////////////////// 267 // INIT 268 269 // increment the current layer 270 ccs.Layout._layer++; 271 272 // mask of the current layer (ie: for layer 3: 00000100) 273 var mask_layer = 0x1 << ccs.Layout._layer; 274 // mask of all layers less than the current (ie: for layer 3: 00000011) 275 var mask_layer_l = mask_layer - 1; 276 // mask of all layers less than or equal to the current (ie: for layer 3: 00000111) 277 var mask_layer_le = mask_layer | mask_layer_l; 278 279 // manually save the stencil state 280 var currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST); 281 var currentStencilWriteMask = gl.getParameter(gl.STENCIL_WRITEMASK); 282 var currentStencilFunc = gl.getParameter(gl.STENCIL_FUNC); 283 var currentStencilRef = gl.getParameter(gl.STENCIL_REF); 284 var currentStencilValueMask = gl.getParameter(gl.STENCIL_VALUE_MASK); 285 var currentStencilFail = gl.getParameter(gl.STENCIL_FAIL); 286 var currentStencilPassDepthFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL); 287 var currentStencilPassDepthPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS); 288 289 // enable stencil use 290 gl.enable(gl.STENCIL_TEST); 291 // check for OpenGL error while enabling stencil test 292 //cc.CHECK_GL_ERROR_DEBUG(); 293 294 // all bits on the stencil buffer are readonly, except the current layer bit, 295 // this means that operation like glClear or glStencilOp will be masked with this value 296 gl.stencilMask(mask_layer); 297 298 // manually save the depth test state 299 //GLboolean currentDepthTestEnabled = GL_TRUE; 300 //currentDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST); 301 var currentDepthWriteMask = gl.getParameter(gl.DEPTH_WRITEMASK); 302 303 // disable depth test while drawing the stencil 304 //glDisable(GL_DEPTH_TEST); 305 // disable update to the depth buffer while drawing the stencil, 306 // as the stencil is not meant to be rendered in the real scene, 307 // it should never prevent something else to be drawn, 308 // only disabling depth buffer update should do 309 gl.depthMask(false); 310 311 /////////////////////////////////// 312 // CLEAR STENCIL BUFFER 313 314 // manually clear the stencil buffer by drawing a fullscreen rectangle on it 315 // setup the stencil test func like this: 316 // for each pixel in the fullscreen rectangle 317 // never draw it into the frame buffer 318 // if not in inverted mode: set the current layer value to 0 in the stencil buffer 319 // if in inverted mode: set the current layer value to 1 in the stencil buffer 320 gl.stencilFunc(gl.NEVER, mask_layer, mask_layer); 321 gl.stencilOp(gl.ZERO, gl.KEEP, gl.KEEP); 322 323 // draw a fullscreen solid rectangle to clear the stencil buffer 324 //ccDrawSolidRect(CCPointZero, ccpFromSize([[CCDirector sharedDirector] winSize]), ccc4f(1, 1, 1, 1)); 325 cc.drawingUtil.drawSolidRect(cc.PointZero(), cc.pFromSize(cc.Director.getInstance().getWinSize()), cc.c4f(1, 1, 1, 1)); 326 327 /////////////////////////////////// 328 // DRAW CLIPPING STENCIL 329 330 // setup the stencil test func like this: 331 // for each pixel in the stencil node 332 // never draw it into the frame buffer 333 // if not in inverted mode: set the current layer value to 1 in the stencil buffer 334 // if in inverted mode: set the current layer value to 0 in the stencil buffer 335 gl.stencilFunc(gl.NEVER, mask_layer, mask_layer); 336 gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP); 337 338 339 // draw the stencil node as if it was one of our child 340 // (according to the stencil test func/op and alpha (or alpha shader) test) 341 cc.kmGLPushMatrix(); 342 this.transform(); 343 this._clippingStencil.visit(); 344 cc.kmGLPopMatrix(); 345 346 // restore alpha test state 347 //if (this._alphaThreshold < 1) { 348 // XXX: we need to find a way to restore the shaders of the stencil node and its childs 349 //} 350 351 // restore the depth test state 352 gl.depthMask(currentDepthWriteMask); 353 //if (currentDepthTestEnabled) { 354 // glEnable(GL_DEPTH_TEST); 355 //} 356 357 /////////////////////////////////// 358 // DRAW CONTENT 359 360 // setup the stencil test func like this: 361 // for each pixel of this node and its childs 362 // if all layers less than or equals to the current are set to 1 in the stencil buffer 363 // draw the pixel and keep the current layer in the stencil buffer 364 // else 365 // do not draw the pixel but keep the current layer in the stencil buffer 366 gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le); 367 gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); 368 369 // draw (according to the stencil test func) this node and its childs 370 cc.Node.prototype.visit.call(this, ctx); 371 372 /////////////////////////////////// 373 // CLEANUP 374 375 // manually restore the stencil state 376 gl.stencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask); 377 gl.stencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass); 378 gl.stencilMask(currentStencilWriteMask); 379 if (!currentStencilEnabled) 380 gl.disable(gl.STENCIL_TEST); 381 382 // we are done using this layer, decrement 383 ccs.Layout._layer--; 384 }, 385 386 _stencilClippingVisitForCanvas: function (ctx) { 387 // return fast (draw nothing, or draw everything if in inverted mode) if: 388 // - nil stencil node 389 // - or stencil node invisible: 390 if (!this._clippingStencil || !this._clippingStencil.isVisible()) { 391 return; 392 } 393 394 // Composition mode, costy but support texture stencil 395 if (this._cangodhelpme() || this._clippingStencil instanceof cc.Sprite) { 396 var context = ctx || cc.renderContext; 397 // Cache the current canvas, for later use (This is a little bit heavy, replace this solution with other walkthrough) 398 var canvas = context.canvas; 399 var locCache = ccs.Layout._getSharedCache(); 400 locCache.width = canvas.width; 401 locCache.height = canvas.height; 402 var locCacheCtx = locCache.getContext("2d"); 403 locCacheCtx.drawImage(canvas, 0, 0); 404 405 context.save(); 406 // Draw everything first using node visit function 407 cc.Node.prototype.visit.call(this, context); 408 409 context.globalCompositeOperation = "destination-in"; 410 411 this.transform(context); 412 this._clippingStencil.visit(); 413 414 context.restore(); 415 416 // Redraw the cached canvas, so that the cliped area shows the background etc. 417 context.save(); 418 context.setTransform(1, 0, 0, 1, 0, 0); 419 context.globalCompositeOperation = "destination-over"; 420 context.drawImage(locCache, 0, 0); 421 context.restore(); 422 } 423 // Clip mode, fast, but only support cc.DrawNode 424 else { 425 var context = ctx || cc.renderContext, i, children = this._children, locChild; 426 427 context.save(); 428 this.transform(context); 429 this._clippingStencil.visit(context); 430 context.clip(); 431 432 // Clip mode doesn't support recusive stencil, so once we used a clip stencil, 433 // so if it has ClippingNode as a child, the child must uses composition stencil. 434 this._cangodhelpme(true); 435 var len = children.length; 436 if (len > 0) { 437 this.sortAllChildren(); 438 // draw children zOrder < 0 439 for (i = 0; i < len; i++) { 440 locChild = children[i]; 441 if (locChild._zOrder < 0) 442 locChild.visit(context); 443 else 444 break; 445 } 446 this.draw(context); 447 for (; i < len; i++) { 448 children[i].visit(context); 449 } 450 } else 451 this.draw(context); 452 this._cangodhelpme(false); 453 454 context.restore(); 455 } 456 }, 457 458 _godhelpme:false, 459 _cangodhelpme: function (godhelpme) { 460 if (godhelpme === true || godhelpme === false) 461 cc.ClippingNode.prototype._godhelpme = godhelpme; 462 return cc.ClippingNode.prototype._godhelpme; 463 }, 464 465 scissorClippingVisit : null, 466 _scissorClippingVisitForWebGL: function (ctx) { 467 var clippingRect = this.getClippingRect(); 468 var gl = ctx || cc.renderContext; 469 if (this._handleScissor) { 470 gl.enable(gl.SCISSOR_TEST); 471 } 472 cc.EGLView.getInstance().setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height); 473 cc.Node.prototype.visit.call(this); 474 if (this._handleScissor) { 475 gl.disable(gl.SCISSOR_TEST); 476 } 477 }, 478 479 /** 480 * Changes if layout can clip it's content and locChild. 481 * @param {Boolean} able 482 */ 483 setClippingEnabled: function (able) { 484 if (able == this._clippingEnabled) { 485 return; 486 } 487 this._clippingEnabled = able; 488 switch (this._clippingType) { 489 case ccs.LayoutClippingType.stencil: 490 if (able) { 491 this.setStencilClippingSize(this._size); 492 } 493 else { 494 this._clippingStencil = null; 495 } 496 break; 497 default: 498 break; 499 } 500 }, 501 502 /** 503 * Set clipping type 504 * @param {ccs.LayoutClippingType} type 505 */ 506 setClippingType: function (type) { 507 if (type == this._clippingType) { 508 return; 509 } 510 var clippingEnabled = this.isClippingEnabled(); 511 this.setClippingEnabled(false); 512 this._clippingType = type; 513 this.setClippingEnabled(clippingEnabled); 514 }, 515 516 /** 517 * Get clipping type 518 * @returns {ccs.LayoutClippingType} 519 */ 520 getClippingType : function(){ 521 return this._clippingType; 522 }, 523 524 setStencilClippingSize: function (size) { 525 if (this._clippingEnabled && this._clippingType == ccs.LayoutClippingType.stencil) { 526 var rect = []; 527 rect[0] = cc.p(0, 0); 528 rect[1] = cc.p(size.width, 0); 529 rect[2] = cc.p(size.width, size.height); 530 rect[3] = cc.p(0, size.height); 531 var green = cc.c4f(0, 1, 0, 1); 532 this._clippingStencil.clear(); 533 this._clippingStencil.drawPoly(rect, 4, green, 0, green); 534 } 535 }, 536 537 rendererVisitCallBack: function () { 538 this.doLayout(); 539 }, 540 541 getClippingRect: function () { 542 if (this._clippingRectDirty){ 543 this._handleScissor = true; 544 var worldPos = this.convertToWorldSpace(cc.p(0, 0)); 545 var t = this.nodeToWorldTransform(); 546 var scissorWidth = this._size.width * t.a; 547 var scissorHeight = this._size.height * t.d; 548 var parentClippingRect; 549 var parent = this; 550 var firstClippingParentFounded = false; 551 while (parent) { 552 parent = parent.getParent(); 553 if (parent && parent instanceof ccs.Layout) { 554 if (parent.isClippingEnabled()) { 555 if (!firstClippingParentFounded) { 556 this._clippingParent = parent; 557 firstClippingParentFounded = true; 558 } 559 560 if (parent._clippingType == ccs.LayoutClippingType.scissor) { 561 this._handleScissor = false; 562 break; 563 } 564 } 565 } 566 } 567 568 if (this._clippingParent) { 569 parentClippingRect = this._clippingParent.getClippingRect(); 570 var finalX = worldPos.x - (scissorWidth * this._anchorPoint.x); 571 var finalY = worldPos.y - (scissorHeight * this._anchorPoint.y); 572 var finalWidth = scissorWidth; 573 var finalHeight = scissorHeight; 574 575 var leftOffset = worldPos.x - parentClippingRect.x; 576 if (leftOffset < 0) { 577 finalX = parentClippingRect.x; 578 finalWidth += leftOffset; 579 } 580 var rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.x + parentClippingRect.width); 581 if (rightOffset > 0) { 582 finalWidth -= rightOffset; 583 } 584 var topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.y + parentClippingRect.height); 585 if (topOffset > 0) { 586 finalHeight -= topOffset; 587 } 588 var bottomOffset = worldPos.y - parentClippingRect.y; 589 if (bottomOffset < 0) { 590 finalY = parentClippingRect.x; 591 finalHeight += bottomOffset; 592 } 593 if (finalWidth < 0) { 594 finalWidth = 0; 595 } 596 if (finalHeight < 0) { 597 finalHeight = 0; 598 } 599 this._clippingRect.x = finalX; 600 this._clippingRect.y = finalY; 601 this._clippingRect.width = finalWidth; 602 this._clippingRect.height = finalHeight; 603 } 604 else { 605 this._clippingRect.x = worldPos.x - (scissorWidth * this._anchorPoint.x); 606 this._clippingRect.y = worldPos.y - (scissorHeight * this._anchorPoint.y); 607 this._clippingRect.width = scissorWidth; 608 this._clippingRect.height = scissorHeight; 609 } 610 this._clippingRectDirty = false; 611 } 612 return this._clippingRect; 613 }, 614 615 onSizeChanged: function () { 616 ccs.Widget.prototype.onSizeChanged.call(this); 617 this.setContentSize(this._size); 618 this.setStencilClippingSize(this._size); 619 this._doLayoutDirty = true; 620 this._clippingRectDirty = true; 621 622 if (this._backGroundImage) { 623 this._backGroundImage.setPosition(this._size.width / 2.0, this._size.height / 2.0); 624 if (this._backGroundScale9Enabled) { 625 if (this._backGroundImage instanceof cc.Scale9Sprite) { 626 this._backGroundImage.setPreferredSize(this._size); 627 } 628 } 629 } 630 if (this._colorRender) { 631 this._colorRender.setContentSize(this._size); 632 } 633 if (this._gradientRender) { 634 this._gradientRender.setContentSize(this._size); 635 } 636 }, 637 638 /** 639 * Sets background image use scale9 renderer. 640 * @param {Boolean} able 641 */ 642 setBackGroundImageScale9Enabled: function (able) { 643 if (this._backGroundScale9Enabled == able) { 644 return; 645 } 646 cc.Node.prototype.removeChild.call(this, this._backGroundImage, true); 647 this._backGroundImage = null; 648 this._backGroundScale9Enabled = able; 649 if (this._backGroundScale9Enabled) { 650 this._backGroundImage = cc.Scale9Sprite.create(); 651 } 652 else { 653 this._backGroundImage = cc.Sprite.create(); 654 } 655 cc.Node.prototype.addChild.call(this, this._backGroundImage, ccs.BACKGROUNDIMAGEZ, -1); 656 this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType); 657 this.setBackGroundImageCapInsets(this._backGroundImageCapInsets); 658 }, 659 660 /** 661 * Get background image is use scale9 renderer. 662 * @returns {Boolean} 663 */ 664 isBackGroundImageScale9Enabled:function(){ 665 return this._backGroundScale9Enabled; 666 }, 667 668 /** 669 * Sets a background image for layout 670 * @param {String} fileName 671 * @param {ccs.TextureResType} texType 672 */ 673 setBackGroundImage: function (fileName, texType) { 674 if (!fileName) { 675 return; 676 } 677 texType = texType || ccs.TextureResType.local; 678 if (this._backGroundImage == null) { 679 this.addBackGroundImage(); 680 } 681 this._backGroundImageFileName = fileName; 682 this._bgImageTexType = texType; 683 switch (this._bgImageTexType) { 684 case ccs.TextureResType.local: 685 this._backGroundImage.initWithFile(fileName); 686 break; 687 case ccs.TextureResType.plist: 688 this._backGroundImage.initWithSpriteFrameName(fileName); 689 break; 690 default: 691 break; 692 } 693 if (this._backGroundScale9Enabled) { 694 this._backGroundImage.setPreferredSize(this._size); 695 } 696 697 this.updateBackGroundImageRGBA(); 698 this._backGroundImageTextureSize = this._backGroundImage.getContentSize(); 699 this._backGroundImage.setPosition(this._size.width / 2.0, this._size.height / 2.0); 700 }, 701 702 /** 703 * Sets a background image capinsets for layout, if the background image is a scale9 render. 704 * @param {cc.Rect} capInsets 705 */ 706 setBackGroundImageCapInsets: function (capInsets) { 707 this._backGroundImageCapInsets = capInsets; 708 if (this._backGroundScale9Enabled) { 709 this._backGroundImage.setCapInsets(capInsets); 710 } 711 }, 712 713 /** 714 * Get background image cap insets. 715 * @returns {cc.Rect} 716 */ 717 getBackGroundImageCapInsets:function(){ 718 return this._backGroundImageCapInsets; 719 }, 720 721 supplyTheLayoutParameterLackToChild: function (locChild) { 722 if (!locChild) { 723 return; 724 } 725 switch (this._layoutType) { 726 case ccs.LayoutType.absolute: 727 break; 728 case ccs.LayoutType.linearHorizontal: 729 case ccs.LayoutType.linearVertical: 730 var layoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear); 731 if (!layoutParameter) { 732 locChild.setLayoutParameter(ccs.LinearLayoutParameter.create()); 733 } 734 break; 735 case ccs.LayoutType.relative: 736 var layoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative); 737 if (!layoutParameter) { 738 locChild.setLayoutParameter(ccs.RelativeLayoutParameter.create()); 739 } 740 break; 741 default: 742 break; 743 } 744 }, 745 746 /** 747 * init background image renderer. 748 */ 749 addBackGroundImage: function () { 750 if (this._backGroundScale9Enabled) { 751 this._backGroundImage = cc.Scale9Sprite.create(); 752 this._backGroundImage.setPreferredSize(this._size); 753 } 754 else { 755 this._backGroundImage = cc.Sprite.create(); 756 } 757 cc.Node.prototype.addChild.call(this, this._backGroundImage, ccs.BACKGROUNDIMAGEZ, -1); 758 this._backGroundImage.setPosition(this._size.width / 2.0, this._size.height / 2.0); 759 }, 760 761 /** 762 * Remove the background image of layout. 763 */ 764 removeBackGroundImage: function () { 765 if (!this._backGroundImage) { 766 return; 767 } 768 cc.Node.prototype.removeChild.call(this, this._backGroundImage, true); 769 this._backGroundImage = null; 770 this._backGroundImageFileName = ""; 771 this._backGroundImageTextureSize = cc.SizeZero(); 772 }, 773 774 /** 775 * Sets Color Type for layout. 776 * @param {ccs.LayoutBackGroundColorType} type 777 */ 778 setBackGroundColorType: function (type) { 779 if (this._colorType == type) { 780 return; 781 } 782 switch (this._colorType) { 783 case ccs.LayoutBackGroundColorType.none: 784 if (this._colorRender) { 785 cc.Node.prototype.removeChild.call(this, this._colorRender, true); 786 this._colorRender = null; 787 } 788 if (this._gradientRender) { 789 cc.Node.prototype.removeChild.call(this, this._gradientRender, true); 790 this._gradientRender = null; 791 } 792 break; 793 case ccs.LayoutBackGroundColorType.solid: 794 if (this._colorRender) { 795 cc.Node.prototype.removeChild.call(this, this._colorRender, true); 796 this._colorRender = null; 797 } 798 break; 799 case ccs.LayoutBackGroundColorType.gradient: 800 if (this._gradientRender) { 801 cc.Node.prototype.removeChild.call(this, this._gradientRender, true); 802 this._gradientRender = null; 803 } 804 break; 805 default: 806 break; 807 } 808 this._colorType = type; 809 switch (this._colorType) { 810 case ccs.LayoutBackGroundColorType.none: 811 break; 812 case ccs.LayoutBackGroundColorType.solid: 813 this._colorRender = cc.LayerColor.create(); 814 this._colorRender.setContentSize(this._size); 815 this._colorRender.setOpacity(this._opacity); 816 this._colorRender.setColor(this._color); 817 cc.Node.prototype.addChild.call(this, this._colorRender, ccs.BACKGROUNDCOLORRENDERERZ, -1); 818 break; 819 case ccs.LayoutBackGroundColorType.gradient: 820 this._gradientRender = cc.LayerGradient.create(cc.c4b(255, 0, 0, 255), cc.c4b(0, 255, 0, 255)); 821 this._gradientRender.setContentSize(this._size); 822 this._gradientRender.setOpacity(this._opacity); 823 this._gradientRender.setStartColor(this._startColor); 824 this._gradientRender.setEndColor(this._endColor); 825 this._gradientRender.setVector(this._alongVector); 826 cc.Node.prototype.addChild.call(this, this._gradientRender, ccs.BACKGROUNDCOLORRENDERERZ, -1); 827 break; 828 default: 829 break; 830 } 831 }, 832 833 /** 834 * Get color type. 835 * @returns {ccs.LayoutBackGroundColorType} 836 */ 837 getBackGroundColorType:function(){ 838 return this._colorType; 839 }, 840 841 /** 842 * Sets background color for layout, if color type is LAYOUT_COLOR_SOLID 843 * @param {cc.c3b} color 844 * @param {cc.c3b} endColor 845 */ 846 setBackGroundColor: function (color, endColor) { 847 if (!endColor) { 848 this._color.r = color.r; 849 this._color.g = color.g; 850 this._color.b = color.b; 851 if (this._colorRender) { 852 this._colorRender.setColor(color); 853 } 854 } else { 855 this._startColor.r = color.r; 856 this._startColor.g = color.g; 857 this._startColor.b = color.b; 858 859 if (this._gradientRender) { 860 this._gradientRender.setStartColor(color); 861 } 862 this._endColor = endColor; 863 if (this._gradientRender) { 864 this._gradientRender.setEndColor(endColor); 865 } 866 } 867 }, 868 869 /** 870 * Get back ground color 871 * @returns {cc.Color} 872 */ 873 getBackGroundColor:function(){ 874 return this._color; 875 }, 876 877 /** 878 * Get back ground start color 879 * @returns {cc.Color} 880 */ 881 getBackGroundStartColor:function(){ 882 return this._startColor; 883 }, 884 885 /** 886 * Get back ground end color 887 * @returns {cc.Color} 888 */ 889 getBackGroundEndColor:function(){ 890 return this._endColor; 891 }, 892 893 /** 894 * Sets background opacity layout. 895 * @param {number} opacity 896 */ 897 setBackGroundColorOpacity: function (opacity) { 898 this._opacity = opacity; 899 switch (this._colorType) { 900 case ccs.LayoutBackGroundColorType.none: 901 break; 902 case ccs.LayoutBackGroundColorType.solid: 903 this._colorRender.setOpacity(opacity); 904 break; 905 case ccs.LayoutBackGroundColorType.gradient: 906 this._gradientRender.setOpacity(opacity); 907 break; 908 default: 909 break; 910 } 911 }, 912 913 /** 914 * Get background opacity value. 915 * @returns {Number} 916 */ 917 getBackGroundColorOpacity:function(){ 918 return this._opacity; 919 }, 920 921 /** 922 * Sets background color vector for layout, if color type is LAYOUT_COLOR_GRADIENT 923 * @param {cc.Point} vector 924 */ 925 setBackGroundColorVector: function (vector) { 926 this._alongVector.x = vector.x; 927 this._alongVector.y = vector.y; 928 if (this._gradientRender) { 929 this._gradientRender.setVector(vector); 930 } 931 }, 932 933 /** 934 * Get background color value. 935 * @returns {cc.Point} 936 */ 937 getBackGroundColorVector:function(){ 938 return this._alongVector; 939 }, 940 941 /** 942 * Set backGround image color 943 * @param {cc.Color3B} color 944 */ 945 setBackGroundImageColor: function (color) { 946 this._backGroundImageColor.r = color.r; 947 this._backGroundImageColor.g = color.g; 948 this._backGroundImageColor.b = color.b; 949 950 this.updateBackGroundImageColor(); 951 }, 952 953 /** 954 * Get backGround image color 955 * @param {Number} opacity 956 */ 957 setBackGroundImageOpacity: function (opacity) { 958 this._backGroundImageOpacity = opacity; 959 this.getBackGroundImageColor(); 960 }, 961 962 /** 963 * Get backGround image color 964 * @returns {cc.Color3B} 965 */ 966 getBackGroundImageColor: function () { 967 var color = this._backGroundImageColor; 968 return cc.color(color.r, color.g, color.b); 969 }, 970 971 /** 972 * Get backGround image opacity 973 * @returns {Number} 974 */ 975 getBackGroundImageOpacity: function () { 976 return this._backGroundImageOpacity; 977 }, 978 979 updateBackGroundImageColor: function () { 980 this._backGroundImage.setColor(this._backGroundImageColor); 981 }, 982 983 updateBackGroundImageOpacity: function () { 984 this._backGroundImage.setOpacity(this._backGroundImageOpacity); 985 }, 986 987 updateBackGroundImageRGBA: function () { 988 this.updateBackGroundImageColor(); 989 this.updateBackGroundImageOpacity(); 990 }, 991 992 /** 993 * Gets background image texture size. 994 * @returns {cc.Size} 995 */ 996 getBackGroundImageTextureSize: function () { 997 return this._backGroundImageTextureSize; 998 }, 999 1000 /** 1001 * Sets LayoutType. 1002 * @param {ccs.LayoutType} type 1003 */ 1004 setLayoutType: function (type) { 1005 this._layoutType = type; 1006 var layoutChildrenArray = this._widgetChildren; 1007 var locChild = null; 1008 for (var i = 0; i < layoutChildrenArray.length; i++) { 1009 locChild = layoutChildrenArray[i]; 1010 this.supplyTheLayoutParameterLackToChild(locChild); 1011 } 1012 this._doLayoutDirty = true; 1013 }, 1014 1015 /** 1016 * Gets LayoutType. 1017 * @returns {null} 1018 */ 1019 getLayoutType: function () { 1020 return this._layoutType; 1021 }, 1022 1023 /** 1024 * request do layout 1025 */ 1026 requestDoLayout: function () { 1027 this._doLayoutDirty = true; 1028 }, 1029 1030 doLayout_LINEAR_VERTICAL: function () { 1031 var layoutChildrenArray = this._widgetChildren; 1032 var layoutSize = this.getSize(); 1033 var topBoundary = layoutSize.height; 1034 for (var i = 0; i < layoutChildrenArray.length; ++i) { 1035 var locChild = layoutChildrenArray[i]; 1036 var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear); 1037 1038 if (locLayoutParameter) { 1039 var locChildGravity = locLayoutParameter.getGravity(); 1040 var locAP = locChild.getAnchorPoint(); 1041 var locSize = locChild.getSize(); 1042 var locFinalPosX = locAP.x * locSize.width; 1043 var locFinalPosY = topBoundary - ((1 - locAP.y) * locSize.height); 1044 switch (locChildGravity) { 1045 case ccs.LinearGravity.none: 1046 case ccs.LinearGravity.left: 1047 break; 1048 case ccs.LinearGravity.right: 1049 locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width); 1050 break; 1051 case ccs.LinearGravity.centerHorizontal: 1052 locFinalPosX = layoutSize.width / 2 - locSize.width * (0.5 - locAP.x); 1053 break; 1054 default: 1055 break; 1056 } 1057 var locMargin = locLayoutParameter.getMargin(); 1058 locFinalPosX += locMargin.left; 1059 locFinalPosY -= locMargin.top; 1060 locChild.setPosition(cc.p(locFinalPosX, locFinalPosY)); 1061 topBoundary = locChild.getBottomInParent() - locMargin.bottom; 1062 } 1063 } 1064 }, 1065 doLayout_LINEAR_HORIZONTAL: function () { 1066 var layoutChildrenArray = this._widgetChildren; 1067 var layoutSize = this.getSize(); 1068 var leftBoundary = 0; 1069 for (var i = 0; i < layoutChildrenArray.length; ++i) { 1070 var locChild = layoutChildrenArray[i]; 1071 var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.linear); 1072 1073 if (locLayoutParameter) { 1074 var locChildGravity = locLayoutParameter.getGravity(); 1075 var locAP = locChild.getAnchorPoint(); 1076 var locSize = locChild.getSize(); 1077 var locFinalPosX = leftBoundary + (locAP.x * locSize.width); 1078 var locFinalPosY = layoutSize.height - (1 - locAP.y) * locSize.height; 1079 switch (locChildGravity) { 1080 case ccs.LinearGravity.none: 1081 case ccs.LinearGravity.top: 1082 break; 1083 case ccs.LinearGravity.bottom: 1084 locFinalPosY = locAP.y * locSize.height; 1085 break; 1086 case ccs.LinearGravity.centerVertical: 1087 locFinalPosY = layoutSize.height / 2 - locSize.height * (0.5 - locAP.y); 1088 break; 1089 default: 1090 break; 1091 } 1092 var locMargin = locLayoutParameter.getMargin(); 1093 locFinalPosX += locMargin.left; 1094 locFinalPosY -= locMargin.top; 1095 locChild.setPosition(cc.p(locFinalPosX, locFinalPosY)); 1096 leftBoundary = locChild.getRightInParent() + locMargin.right; 1097 } 1098 } 1099 }, 1100 doLayout_RELATIVE: function () { 1101 var layoutChildrenArray = this._widgetChildren; 1102 var length = layoutChildrenArray.length; 1103 var unlayoutChildCount = length; 1104 var layoutSize = this.getSize(); 1105 1106 for (var i = 0; i < length; i++) { 1107 var locChild = layoutChildrenArray[i]; 1108 var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative); 1109 locLayoutParameter._put = false; 1110 } 1111 1112 while (unlayoutChildCount > 0) { 1113 for (var i = 0; i < length; i++) { 1114 var locChild = layoutChildrenArray[i]; 1115 var locLayoutParameter = locChild.getLayoutParameter(ccs.LayoutParameterType.relative); 1116 1117 if (locLayoutParameter) { 1118 if (locLayoutParameter._put) { 1119 continue; 1120 } 1121 var locAP = locChild.getAnchorPoint(); 1122 var locSize = locChild.getSize(); 1123 var locAlign = locLayoutParameter.getAlign(); 1124 var locRelativeName = locLayoutParameter.getRelativeToWidgetName(); 1125 var locRelativeWidget = null; 1126 var locRelativeWidgetLP = null; 1127 var locFinalPosX = 0; 1128 var locFinalPosY = 0; 1129 if (locRelativeName) { 1130 locRelativeWidget = ccs.UIHelper.seekWidgetByRelativeName(this, locRelativeName); 1131 if (locRelativeWidget) { 1132 locRelativeWidgetLP = locRelativeWidget.getLayoutParameter(ccs.LayoutParameterType.relative); 1133 } 1134 } 1135 switch (locAlign) { 1136 case ccs.RelativeAlign.alignNone: 1137 case ccs.RelativeAlign.alignParentTopLeft: 1138 locFinalPosX = locAP.x * locSize.width; 1139 locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height); 1140 break; 1141 case ccs.RelativeAlign.alignParentTopCenterHorizontal: 1142 locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x); 1143 locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height); 1144 break; 1145 case ccs.RelativeAlign.alignParentTopRight: 1146 locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width); 1147 locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height); 1148 break; 1149 case ccs.RelativeAlign.alignParentLeftCenterVertical: 1150 locFinalPosX = locAP.x * locSize.width; 1151 locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y); 1152 break; 1153 case ccs.RelativeAlign.centerInParent: 1154 locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x); 1155 locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y); 1156 break; 1157 case ccs.RelativeAlign.alignParentRightCenterVertical: 1158 locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width); 1159 locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y); 1160 break; 1161 case ccs.RelativeAlign.alignParentLeftBottom: 1162 locFinalPosX = locAP.x * locSize.width; 1163 locFinalPosY = locAP.y * locSize.height; 1164 break; 1165 case ccs.RelativeAlign.alignParentBottomCenterHorizontal: 1166 locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x); 1167 locFinalPosY = locAP.y * locSize.height; 1168 break; 1169 case ccs.RelativeAlign.alignParentRightBottom: 1170 locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width); 1171 locFinalPosY = locAP.y * locSize.height; 1172 break; 1173 1174 case ccs.RelativeAlign.locationAboveLeftAlign: 1175 if (locRelativeWidget) { 1176 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1177 continue; 1178 } 1179 var locationBottom = locRelativeWidget.getTopInParent(); 1180 var locationLeft = locRelativeWidget.getLeftInParent(); 1181 locFinalPosY = locationBottom + locAP.y * locSize.height; 1182 locFinalPosX = locationLeft + locAP.x * locSize.width; 1183 } 1184 break; 1185 case ccs.RelativeAlign.locationAboveCenter: 1186 if (locRelativeWidget) { 1187 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1188 continue; 1189 } 1190 var rbs = locRelativeWidget.getSize(); 1191 var locationBottom = locRelativeWidget.getTopInParent(); 1192 1193 locFinalPosY = locationBottom + locAP.y * locSize.height; 1194 locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5; 1195 } 1196 break; 1197 case ccs.RelativeAlign.locationAboveRightAlign: 1198 if (locRelativeWidget) { 1199 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1200 continue; 1201 } 1202 var locationBottom = locRelativeWidget.getTopInParent(); 1203 var locationRight = locRelativeWidget.getRightInParent(); 1204 locFinalPosY = locationBottom + locAP.y * locSize.height; 1205 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width; 1206 } 1207 break; 1208 case ccs.RelativeAlign.locationLeftOfTopAlign: 1209 if (locRelativeWidget) { 1210 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1211 continue; 1212 } 1213 var locationTop = locRelativeWidget.getTopInParent(); 1214 var locationRight = locRelativeWidget.getLeftInParent(); 1215 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height; 1216 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width; 1217 } 1218 break; 1219 case ccs.RelativeAlign.locationLeftOfCenter: 1220 if (locRelativeWidget) { 1221 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1222 continue; 1223 } 1224 var rbs = locRelativeWidget.getSize(); 1225 var locationRight = locRelativeWidget.getLeftInParent(); 1226 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width; 1227 1228 locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5; 1229 } 1230 break; 1231 case ccs.RelativeAlign.locationLeftOfBottomAlign: 1232 if (locRelativeWidget) { 1233 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1234 continue; 1235 } 1236 var locationBottom = locRelativeWidget.getBottomInParent(); 1237 var locationRight = locRelativeWidget.getLeftInParent(); 1238 locFinalPosY = locationBottom + locAP.y * locSize.height; 1239 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width; 1240 } 1241 break; 1242 case ccs.RelativeAlign.locationRightOfTopAlign: 1243 if (locRelativeWidget) { 1244 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1245 continue; 1246 } 1247 var locationTop = locRelativeWidget.getTopInParent(); 1248 var locationLeft = locRelativeWidget.getRightInParent(); 1249 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height; 1250 locFinalPosX = locationLeft + locAP.x * locSize.width; 1251 } 1252 break; 1253 case ccs.RelativeAlign.locationRightOfCenter: 1254 if (locRelativeWidget) { 1255 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1256 continue; 1257 } 1258 var rbs = locRelativeWidget.getSize(); 1259 var locationLeft = locRelativeWidget.getRightInParent(); 1260 locFinalPosX = locationLeft + locAP.x * locSize.width; 1261 1262 locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5; 1263 } 1264 break; 1265 case ccs.RelativeAlign.locationRightOfBottomAlign: 1266 if (locRelativeWidget) { 1267 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1268 continue; 1269 } 1270 var locationBottom = locRelativeWidget.getBottomInParent(); 1271 var locationLeft = locRelativeWidget.getRightInParent(); 1272 locFinalPosY = locationBottom + locAP.y * locSize.height; 1273 locFinalPosX = locationLeft + locAP.x * locSize.width; 1274 } 1275 break; 1276 case ccs.RelativeAlign.locationBelowLeftAlign: 1277 if (locRelativeWidget) { 1278 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1279 continue; 1280 } 1281 var locationTop = locRelativeWidget.getBottomInParent(); 1282 var locationLeft = locRelativeWidget.getLeftInParent(); 1283 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height; 1284 locFinalPosX = locationLeft + locAP.x * locSize.width; 1285 } 1286 break; 1287 case ccs.RelativeAlign.locationBelowCenter: 1288 if (locRelativeWidget) { 1289 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1290 continue; 1291 } 1292 var rbs = locRelativeWidget.getSize(); 1293 var locationTop = locRelativeWidget.getBottomInParent(); 1294 1295 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height; 1296 locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5; 1297 } 1298 break; 1299 case ccs.RelativeAlign.locationBelowRightAlign: 1300 if (locRelativeWidget) { 1301 if (locRelativeWidgetLP && !locRelativeWidgetLP._put) { 1302 continue; 1303 } 1304 var locationTop = locRelativeWidget.getBottomInParent(); 1305 var locationRight = locRelativeWidget.getRightInParent(); 1306 locFinalPosY = locationTop - (1 - locAP.y) * locSize.height; 1307 locFinalPosX = locationRight - (1 - locAP.x) * locSize.width; 1308 } 1309 break; 1310 default: 1311 break; 1312 } 1313 var locRelativeWidgetMargin,locRelativeWidgetLPAlign; 1314 var locMargin = locLayoutParameter.getMargin(); 1315 if (locRelativeWidgetLP) { 1316 locRelativeWidgetMargin = locRelativeWidgetLP.getMargin(); 1317 locRelativeWidgetLPAlign = locRelativeWidgetLP.getAlign(); 1318 } 1319 //handle margin 1320 switch (locAlign) { 1321 case ccs.RelativeAlign.alignNone: 1322 case ccs.RelativeAlign.alignParentTopLeft: 1323 locFinalPosX += locMargin.left; 1324 locFinalPosY -= locMargin.top; 1325 break; 1326 case ccs.RelativeAlign.alignParentTopCenterHorizontal: 1327 locFinalPosY -= locMargin.top; 1328 break; 1329 case ccs.RelativeAlign.alignParentTopRight: 1330 locFinalPosX -= locMargin.right; 1331 locFinalPosY -= locMargin.top; 1332 break; 1333 case ccs.RelativeAlign.alignParentLeftCenterVertical: 1334 locFinalPosX += locMargin.left; 1335 break; 1336 case ccs.RelativeAlign.centerInParent: 1337 break; 1338 case ccs.RelativeAlign.alignParentRightCenterVertical: 1339 locFinalPosX -= locMargin.right; 1340 break; 1341 case ccs.RelativeAlign.alignParentLeftBottom: 1342 locFinalPosX += locMargin.left; 1343 locFinalPosY += locMargin.bottom; 1344 break; 1345 case ccs.RelativeAlign.alignParentBottomCenterHorizontal: 1346 locFinalPosY += locMargin.bottom; 1347 break; 1348 case ccs.RelativeAlign.alignParentRightBottom: 1349 locFinalPosX -= locMargin.right; 1350 locFinalPosY += locMargin.bottom; 1351 break; 1352 1353 case ccs.RelativeAlign.locationAboveLeftAlign: 1354 locFinalPosY += locMargin.bottom; 1355 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopCenterHorizontal 1356 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1357 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1358 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight) 1359 { 1360 locFinalPosY += locRelativeWidgetMargin.top; 1361 } 1362 locFinalPosY += locMargin.left; 1363 break; 1364 case ccs.RelativeAlign.locationAboveCenter: 1365 locFinalPosY += locMargin.bottom; 1366 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopCenterHorizontal 1367 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1368 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1369 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight) 1370 { 1371 locFinalPosY += locRelativeWidgetMargin.top; 1372 } 1373 break; 1374 case ccs.RelativeAlign.locationAboveRightAlign: 1375 locFinalPosY += locMargin.bottom; 1376 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopCenterHorizontal 1377 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1378 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1379 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight) 1380 { 1381 locFinalPosY += locRelativeWidgetMargin.top; 1382 } 1383 locFinalPosX -= locMargin.right; 1384 break; 1385 case ccs.RelativeAlign.locationLeftOfTopAlign: 1386 locFinalPosX -= locMargin.right; 1387 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1388 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1389 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1390 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftCenterVertical) 1391 { 1392 locFinalPosX -= locRelativeWidgetMargin.left; 1393 } 1394 locFinalPosY -= locMargin.top; 1395 break; 1396 case ccs.RelativeAlign.locationLeftOfCenter: 1397 locFinalPosX -= locMargin.right; 1398 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1399 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1400 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1401 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftCenterVertical) 1402 { 1403 locFinalPosX -= locRelativeWidgetMargin.left; 1404 } 1405 break; 1406 case ccs.RelativeAlign.locationLeftOfBottomAlign: 1407 locFinalPosX -= locMargin.right; 1408 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopLeft 1409 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignNone 1410 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1411 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftCenterVertical) 1412 { 1413 locFinalPosX -= locRelativeWidgetMargin.left; 1414 } 1415 locFinalPosY += locMargin.bottom; 1416 break; 1417 break; 1418 case ccs.RelativeAlign.locationRightOfTopAlign: 1419 locFinalPosX += locMargin.left; 1420 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight 1421 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1422 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightCenterVertical) 1423 { 1424 locFinalPosX += locRelativeWidgetMargin.right; 1425 } 1426 locFinalPosY -= locMargin.top; 1427 break; 1428 case ccs.RelativeAlign.locationRightOfCenter: 1429 locFinalPosX += locMargin.left; 1430 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight 1431 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1432 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightCenterVertical) 1433 { 1434 locFinalPosX += locRelativeWidgetMargin.right; 1435 } 1436 break; 1437 case ccs.RelativeAlign.locationRightOfBottomAlign: 1438 locFinalPosX += locMargin.left; 1439 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentTopRight 1440 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1441 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightCenterVertical) 1442 { 1443 locFinalPosX += locRelativeWidgetMargin.right; 1444 } 1445 locFinalPosY += locMargin.bottom; 1446 break; 1447 break; 1448 case ccs.RelativeAlign.locationBelowLeftAlign: 1449 locFinalPosY -= locMargin.top; 1450 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1451 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1452 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentBottomCenterHorizontal) 1453 { 1454 locFinalPosY -= locRelativeWidgetMargin.bottom; 1455 } 1456 locFinalPosX += locMargin.left; 1457 break; 1458 case ccs.RelativeAlign.locationBelowCenter: 1459 locFinalPosY -= locMargin.top; 1460 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1461 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1462 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentBottomCenterHorizontal) 1463 { 1464 locFinalPosY -= locRelativeWidgetMargin.bottom; 1465 } 1466 break; 1467 case ccs.RelativeAlign.locationBelowRightAlign: 1468 locFinalPosY -= locMargin.top; 1469 if (locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentLeftBottom 1470 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentRightBottom 1471 && locRelativeWidgetLPAlign != ccs.RelativeAlign.alignParentBottomCenterHorizontal) 1472 { 1473 locFinalPosY -= locRelativeWidgetMargin.bottom; 1474 } 1475 locFinalPosX -= locMargin.right; 1476 break; 1477 default: 1478 break; 1479 } 1480 locChild.setPosition(cc.p(locFinalPosX, locFinalPosY)); 1481 locLayoutParameter._put = true; 1482 unlayoutChildCount--; 1483 } 1484 } 1485 } 1486 }, 1487 doLayout: function () { 1488 if(!this._doLayoutDirty){ 1489 return; 1490 } 1491 switch (this._layoutType) { 1492 case ccs.LayoutType.absolute: 1493 break; 1494 case ccs.LayoutType.linearVertical: 1495 this.doLayout_LINEAR_VERTICAL(); 1496 break; 1497 case ccs.LayoutType.linearHorizontal: 1498 this.doLayout_LINEAR_HORIZONTAL(); 1499 break; 1500 case ccs.LayoutType.relative: 1501 this.doLayout_RELATIVE(); 1502 break; 1503 default: 1504 break; 1505 } 1506 this._doLayoutDirty = false; 1507 }, 1508 1509 /** 1510 * Returns the "class name" of widget. 1511 * @returns {string} 1512 */ 1513 getDescription: function () { 1514 return "Layout"; 1515 }, 1516 1517 createCloneInstance: function () { 1518 return ccs.Layout.create(); 1519 }, 1520 1521 copyClonedWidgetChildren: function (model) { 1522 ccs.Widget.prototype.copyClonedWidgetChildren.call(this, model); 1523 }, 1524 1525 copySpecialProperties: function (layout) { 1526 this.setBackGroundImageScale9Enabled(layout._backGroundScale9Enabled); 1527 this.setBackGroundImage(layout._backGroundImageFileName, layout._bgImageTexType); 1528 this.setBackGroundImageCapInsets(layout._backGroundImageCapInsets); 1529 this.setBackGroundColorType(layout._colorType); 1530 this.setBackGroundColor(layout._color); 1531 this.setBackGroundColor(layout._startColor, layout._endColor); 1532 this.setBackGroundColorOpacity(layout._opacity); 1533 this.setBackGroundColorVector(layout._alongVector); 1534 this.setLayoutType(layout._layoutType); 1535 this.setClippingEnabled(layout._clippingEnabled); 1536 this.setClippingType(layout._clippingType); 1537 } 1538 }); 1539 ccs.Layout._init_once = null; 1540 ccs.Layout._visit_once = null; 1541 ccs.Layout._layer = null; 1542 ccs.Layout._sharedCache = null; 1543 1544 if (cc.Browser.supportWebGL) { 1545 //WebGL 1546 ccs.Layout.prototype.initStencil = ccs.Layout.prototype._initStencilForWebGL; 1547 ccs.Layout.prototype.stencilClippingVisit = ccs.Layout.prototype._stencilClippingVisitForWebGL; 1548 ccs.Layout.prototype.scissorClippingVisit = ccs.Layout.prototype._scissorClippingVisitForWebGL; 1549 }else{ 1550 ccs.Layout.prototype.initStencil = ccs.Layout.prototype._initStencilForCanvas; 1551 ccs.Layout.prototype.stencilClippingVisit = ccs.Layout.prototype._stencilClippingVisitForCanvas; 1552 ccs.Layout.prototype.scissorClippingVisit = ccs.Layout.prototype._stencilClippingVisitForCanvas; 1553 } 1554 ccs.Layout._getSharedCache = function () { 1555 return (cc.ClippingNode._sharedCache) || (cc.ClippingNode._sharedCache = document.createElement("canvas")); 1556 }; 1557 /** 1558 * allocates and initializes a UILayout. 1559 * @constructs 1560 * @return {ccs.Layout} 1561 * @example 1562 * // example 1563 * var uiLayout = ccs.Layout.create(); 1564 */ 1565 ccs.Layout.create = function () { 1566 var layout = new ccs.Layout(); 1567 if (layout && layout.init()) { 1568 return layout; 1569 } 1570 return null; 1571 }; 1572