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