1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** cc.Layer is a subclass of cc.Node that implements the TouchEventsDelegate protocol.<br/> 28 * All features from cc.Node are valid, plus the following new features:<br/> 29 * It can receive iPhone Touches<br/> 30 * It can receive Accelerometer input 31 * @class 32 * @extends cc.Node 33 */ 34 cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ 35 _isBaked: false, 36 _bakeSprite: null, 37 _className: "Layer", 38 39 /** 40 * Constructor of cc.Layer 41 */ 42 ctor: function () { 43 var nodep = cc.Node.prototype; 44 nodep.ctor.call(this); 45 this._ignoreAnchorPointForPosition = true; 46 nodep.setAnchorPoint.call(this, 0.5, 0.5); 47 nodep.setContentSize.call(this, cc.winSize); 48 }, 49 50 /** 51 * set the layer to cache all of children to a bake sprite, and draw itself by bake sprite. recommend using it in UI. 52 * @function 53 */ 54 bake: null, 55 56 /** 57 * cancel the layer to cache all of children to a bake sprite. 58 * @function 59 */ 60 unbake: null, 61 62 /** 63 * Determines if the layer is baked. 64 * @function 65 * @returns {boolean} 66 */ 67 isBaked: function(){ 68 return this._isBaked; 69 }, 70 71 visit: null 72 }); 73 74 /** 75 * creates a layer 76 * @example 77 * // Example 78 * var myLayer = cc.Layer.create(); 79 * //Yes! it's that simple 80 * @return {cc.Layer|Null} 81 */ 82 cc.Layer.create = function () { 83 return new cc.Layer(); 84 }; 85 86 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 87 var p = cc.Layer.prototype; 88 p.bake = function(){ 89 if (!this._isBaked) { 90 //limit: 1. its children's blendfunc are invalid. 91 this._isBaked = this._cacheDirty = true; 92 93 this._cachedParent = this; 94 var children = this._children; 95 for(var i = 0, len = children.length; i < len; i++) 96 children[i]._setCachedParent(this); 97 98 if (!this._bakeSprite) 99 this._bakeSprite = new cc.BakeSprite(); 100 } 101 }; 102 103 p.unbake = function(){ 104 if (this._isBaked) { 105 this._isBaked = false; 106 this._cacheDirty = true; 107 108 this._cachedParent = null; 109 var children = this._children; 110 for(var i = 0, len = children.length; i < len; i++) 111 children[i]._setCachedParent(null); 112 } 113 }; 114 115 p.visit = function(ctx){ 116 if(!this._isBaked){ 117 cc.Node.prototype.visit.call(this, ctx); 118 return; 119 } 120 121 var context = ctx || cc._renderContext, i; 122 var _t = this; 123 var children = _t._children; 124 var len = children.length; 125 // quick return if not visible 126 if (!_t._visible || len === 0) 127 return; 128 129 var locBakeSprite = this._bakeSprite; 130 131 context.save(); 132 _t.transform(context); 133 134 if(this._cacheDirty){ 135 //compute the bounding box of the bake layer. 136 var boundingBox = this._getBoundingBoxForBake(); 137 boundingBox.width = 0 | boundingBox.width; 138 boundingBox.height = 0 | boundingBox.height; 139 var bakeContext = locBakeSprite.getCacheContext(); 140 locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height); 141 bakeContext.translate(0 - boundingBox.x, boundingBox.height + boundingBox.y); 142 143 //reset the bake sprite's position 144 var anchor = locBakeSprite.getAnchorPointInPoints(); 145 locBakeSprite.setPosition(anchor.x + boundingBox.x, anchor.y + boundingBox.y); 146 147 //visit for canvas 148 _t.sortAllChildren(); 149 // draw children zOrder < 0 150 for (i = 0; i < len; i++) { 151 children[i].visit(bakeContext); 152 } 153 154 this._cacheDirty = false; 155 } 156 157 //the bakeSprite is drawing 158 locBakeSprite.visit(context); 159 160 _t.arrivalOrder = 0; 161 context.restore(); 162 }; 163 164 p._getBoundingBoxForBake = function () { 165 var rect = null; 166 167 //query child's BoundingBox 168 if (!this._children || this._children.length === 0) 169 return cc.rect(0, 0, 10, 10); 170 171 var locChildren = this._children; 172 for (var i = 0; i < locChildren.length; i++) { 173 var child = locChildren[i]; 174 if (child && child._visible) { 175 if(rect){ 176 var childRect = child._getBoundingBoxToCurrentNode(); 177 if (childRect) 178 rect = cc.rectUnion(rect, childRect); 179 }else{ 180 rect = child._getBoundingBoxToCurrentNode(); 181 } 182 } 183 } 184 return rect; 185 }; 186 p = null; 187 }else{ 188 cc.assert(typeof cc._tmp.LayerDefineForWebGL === "function", cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 189 cc._tmp.LayerDefineForWebGL(); 190 delete cc._tmp.LayerDefineForWebGL; 191 } 192 193 /** 194 * <p> 195 * CCLayerRGBA is a subclass of CCLayer that implements the CCRGBAProtocol protocol using a solid color as the background. <br/> 196 * All features from CCLayer are valid, plus the following new features that propagate into children that conform to the CCRGBAProtocol: <br/> 197 * - opacity <br/> 198 * - RGB colors 199 * </p> 200 * @class 201 * @extends cc.Layer 202 * 203 * @property {Number} opacity - Opacity of layer 204 * @property {Boolean} opacityModifyRGB - Indicate whether or not the opacity modify color 205 * @property {Boolean} cascadeOpacity - Indicate whether or not it will set cascade opacity 206 * @property {cc.Color} color - Color of layer 207 * @property {Boolean} cascadeColor - Indicate whether or not it will set cascade color 208 */ 209 cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{ 210 RGBAProtocol: true, 211 _displayedOpacity: 255, 212 _realOpacity: 255, 213 _displayedColor: null, 214 _realColor: null, 215 _cascadeOpacityEnabled: false, 216 _cascadeColorEnabled: false, 217 _className: "LayerRGBA", 218 219 /** 220 * Constructor of cc.LayerRGBA 221 */ 222 ctor: function () { 223 cc.Layer.prototype.ctor.call(this); 224 this._displayedColor = cc.color(255, 255, 255, 255); 225 this._realColor = cc.color(255, 255, 255, 255); 226 }, 227 228 init: function () { 229 var nodep = cc.Layer.prototype, _t = this; 230 _t._ignoreAnchorPointForPosition = true; 231 nodep.setAnchorPoint.call(_t, 0.5, 0.5); 232 nodep.setContentSize.call(_t, cc.winSize); 233 _t.cascadeOpacity = false; 234 _t.cascadeColor = false; 235 return true; 236 }, 237 238 /** 239 * Get the opacity of Layer 240 * @returns {number} opacity 241 */ 242 getOpacity: function () { 243 return this._realOpacity; 244 }, 245 246 /** 247 * Get the displayed opacity of Layer 248 * @returns {number} displayed opacity 249 */ 250 getDisplayedOpacity: function () { 251 return this._displayedOpacity; 252 }, 253 254 /** 255 * Override synthesized setOpacity to recurse items 256 * @param {Number} opacity 257 */ 258 setOpacity: function (opacity) { 259 var _t = this; 260 _t._displayedOpacity = _t._realOpacity = opacity; 261 262 var parentOpacity = 255, locParent = _t._parent; 263 if (locParent && locParent.RGBAProtocol && locParent.cascadeOpacity) 264 parentOpacity = locParent.getDisplayedOpacity(); 265 _t.updateDisplayedOpacity(parentOpacity); 266 267 _t._displayedColor.a = _t._realColor.a = opacity; 268 }, 269 270 /** 271 * Update displayed opacity of Layer 272 * @param {Number} parentOpacity 273 */ 274 updateDisplayedOpacity: function (parentOpacity) { 275 var _t = this; 276 _t._displayedOpacity = 0 | (_t._realOpacity * parentOpacity / 255.0); 277 278 if (_t._cascadeOpacityEnabled) { 279 var locChildren = _t._children, selItem; 280 for (var i = 0; i < locChildren.length; i++) { 281 selItem = locChildren[i]; 282 if (selItem && selItem.RGBAProtocol) 283 selItem.updateDisplayedOpacity(_t._displayedOpacity); 284 } 285 } 286 }, 287 288 /** 289 * whether or not it will set cascade opacity. 290 * @returns {boolean} 291 */ 292 isCascadeOpacityEnabled: function () { 293 return this._cascadeOpacityEnabled; 294 }, 295 296 /** 297 * Enable or disable cascade opacity 298 * @param {boolean} cascadeOpacityEnabled 299 */ 300 setCascadeOpacityEnabled: function (cascadeOpacityEnabled) { 301 if (this._cascadeOpacityEnabled === cascadeOpacityEnabled) 302 return; 303 304 this._cascadeOpacityEnabled = cascadeOpacityEnabled; 305 if (cascadeOpacityEnabled) 306 this._enableCascadeOpacity(); 307 else 308 this._disableCascadeOpacity(); 309 }, 310 311 _enableCascadeOpacity: function () { 312 var parentOpacity = 255, locParent = this._parent; 313 if (locParent && locParent.RGBAProtocol && locParent.cascadeOpacity) 314 parentOpacity = locParent.getDisplayedOpacity(); 315 this.updateDisplayedOpacity(parentOpacity); 316 }, 317 318 _disableCascadeOpacity: function () { 319 this._displayedOpacity = this._realOpacity; 320 var selChildren = this._children, item; 321 for (var i = 0; i < selChildren.length; i++) { 322 item = selChildren[i]; 323 if (item && item.RGBAProtocol) 324 item.updateDisplayedOpacity(255); 325 } 326 }, 327 328 /** 329 * Get the color of Layer 330 * @returns {cc.Color} 331 */ 332 getColor: function () { 333 var locRealColor = this._realColor; 334 return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a); 335 }, 336 337 /** 338 * Get the displayed color of Layer 339 * @returns {cc.Color} 340 */ 341 getDisplayedColor: function () { 342 var locDisplayedColor = this._displayedColor; 343 return cc.color(locDisplayedColor.r, locDisplayedColor.g, locDisplayedColor.b); 344 }, 345 346 /** 347 * Set the color of Layer 348 * @param {cc.Color} color 349 */ 350 setColor: function (color) { 351 var locDisplayed = this._displayedColor, locRealColor = this._realColor; 352 locDisplayed.r = locRealColor.r = color.r; 353 locDisplayed.g = locRealColor.g = color.g; 354 locDisplayed.b = locRealColor.b = color.b; 355 356 var parentColor, locParent = this._parent; 357 if (locParent && locParent.RGBAProtocol && locParent.cascadeColor) 358 parentColor = locParent.getDisplayedColor(); 359 else 360 parentColor = cc.color.WHITE; 361 this.updateDisplayedColor(parentColor); 362 363 if (color.a !== undefined && !color.a_undefined) { 364 this.setOpacity(color.a); 365 } 366 }, 367 368 /** 369 * update the displayed color of Node 370 * @param {cc.Color} parentColor 371 */ 372 updateDisplayedColor: function (parentColor) { 373 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 374 locDisplayedColor.r = 0 | (locRealColor.r * parentColor.r / 255.0); 375 locDisplayedColor.g = 0 | (locRealColor.g * parentColor.g / 255.0); 376 locDisplayedColor.b = 0 | (locRealColor.b * parentColor.b / 255.0); 377 378 if (this._cascadeColorEnabled) { 379 var locChildren = this._children, selItem; 380 for (var i = 0; i < locChildren.length; i++) { 381 selItem = locChildren[i]; 382 if (selItem && selItem.RGBAProtocol) 383 selItem.updateDisplayedColor(locDisplayedColor); 384 } 385 } 386 }, 387 388 /** 389 * whether or not it will set cascade color. 390 * @returns {boolean} 391 */ 392 isCascadeColorEnabled: function () { 393 return this._cascadeColorEnabled; 394 }, 395 396 /** 397 * Enable or disable cascade color 398 * @param {boolean} cascadeColorEnabled 399 */ 400 setCascadeColorEnabled: function (cascadeColorEnabled) { 401 if (this._cascadeColorEnabled === cascadeColorEnabled) 402 return; 403 this._cascadeColorEnabled = cascadeColorEnabled; 404 if (this._cascadeColorEnabled) 405 this._enableCascadeColor(); 406 else 407 this._disableCascadeColor(); 408 }, 409 410 _enableCascadeColor: function () { 411 var parentColor , locParent = this._parent; 412 if (locParent && locParent.RGBAProtocol && locParent.cascadeColor) 413 parentColor = locParent.getDisplayedColor(); 414 else 415 parentColor = cc.color.WHITE; 416 this.updateDisplayedColor(parentColor); 417 }, 418 419 _disableCascadeColor: function () { 420 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 421 locDisplayedColor.r = locRealColor.r; 422 locDisplayedColor.g = locRealColor.g; 423 locDisplayedColor.b = locRealColor.b; 424 425 var selChildren = this._children, whiteColor = cc.color.WHITE, item, i; 426 for (i = 0; i < selChildren.length; i++) { 427 item = selChildren[i]; 428 if (item && item.RGBAProtocol) 429 item.updateDisplayedColor(whiteColor); 430 } 431 }, 432 433 /** 434 * add a child to layer 435 * @overried 436 * @param {cc.Node} child A child node 437 * @param {Number} [zOrder=] Z order for drawing priority. Please refer to setLocalZOrder(int) 438 * @param {Number} [tag=] A integer to identify the node easily. Please refer to setTag(int) 439 */ 440 addChild: function (child, zOrder, tag) { 441 cc.Node.prototype.addChild.call(this, child, zOrder, tag); 442 443 if (this._cascadeColorEnabled) 444 this._enableCascadeColor(); 445 if (this._cascadeOpacityEnabled) 446 this._enableCascadeOpacity(); 447 }, 448 449 setOpacityModifyRGB: function (bValue) { 450 }, 451 452 isOpacityModifyRGB: function () { 453 return false; 454 } 455 }); 456 457 cc.assert(typeof cc._tmp.PrototypeLayerRGBA === "function", cc._LogInfos.MissingFile, "CCLayerPropertyDefine.js"); 458 cc._tmp.PrototypeLayerRGBA(); 459 delete cc._tmp.PrototypeLayerRGBA; 460 461 /** 462 * <p> 463 * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. <br/> 464 * All features from CCLayer are valid, plus the following new features: <br/> 465 * <ul><li>opacity</li> <br/> 466 * <li>RGB colors</li></ul> <br/> 467 * </p> 468 * @class 469 * @extends cc.LayerRGBA 470 */ 471 cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{ 472 _blendFunc: null, 473 _className: "LayerColor", 474 475 /** 476 * blendFunc getter 477 * @return {cc.BlendFunc} 478 */ 479 getBlendFunc: function () { 480 return this._blendFunc; 481 }, 482 483 /** 484 * change width and height in Points 485 * @deprecated 486 * @param {Number} w width 487 * @param {Number} h height 488 */ 489 changeWidthAndHeight: function (w, h) { 490 this.width = w; 491 this.height = h; 492 }, 493 494 /** 495 * change width in Points 496 * @deprecated 497 * @param {Number} w width 498 */ 499 changeWidth: function (w) { 500 this.width = w; 501 }, 502 503 /** 504 * change height in Points 505 * @deprecated 506 * @param {Number} h height 507 */ 508 changeHeight: function (h) { 509 this.height = h; 510 }, 511 512 /** 513 * set OpacityModifyRGB of cc.LayerColor 514 * @param {Boolean} value 515 */ 516 setOpacityModifyRGB: function (value) { 517 }, 518 519 /** 520 * is OpacityModifyRGB 521 * @return {Boolean} 522 */ 523 isOpacityModifyRGB: function () { 524 return false; 525 }, 526 527 setColor: function (color) { 528 cc.LayerRGBA.prototype.setColor.call(this, color); 529 this._updateColor(); 530 }, 531 532 setOpacity: function (opacity) { 533 cc.LayerRGBA.prototype.setOpacity.call(this, opacity); 534 this._updateColor(); 535 }, 536 537 _isLighterMode: false, 538 /** 539 * Constructor of cc.LayerColor 540 * @function 541 * @param {cc.Color} [color=] 542 * @param {Number} [width=] 543 * @param {Number} [height=] 544 */ 545 ctor: null, 546 547 /** 548 * @param {cc.Color} [color=] 549 * @param {Number} [width=] 550 * @param {Number} [height=] 551 * @return {Boolean} 552 */ 553 init: function (color, width, height) { 554 if (cc._renderType !== cc._RENDER_TYPE_CANVAS) 555 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR); 556 557 var winSize = cc.director.getWinSize(); 558 color = color || cc.color(0, 0, 0, 255); 559 width = width === undefined ? winSize.width : width; 560 height = height === undefined ? winSize.height : height; 561 562 var locDisplayedColor = this._displayedColor; 563 locDisplayedColor.r = color.r; 564 locDisplayedColor.g = color.g; 565 locDisplayedColor.b = color.b; 566 567 var locRealColor = this._realColor; 568 locRealColor.r = color.r; 569 locRealColor.g = color.g; 570 locRealColor.b = color.b; 571 572 this._displayedOpacity = color.a; 573 this._realOpacity = color.a; 574 575 var proto = cc.LayerColor.prototype; 576 proto.setContentSize.call(this, width, height); 577 proto._updateColor.call(this); 578 return true; 579 }, 580 581 /** 582 * blendFunc setter 583 * @param {Number} src 584 * @param {Number} dst 585 */ 586 setBlendFunc: function (src, dst) { 587 var _t = this; 588 if (dst === undefined) 589 _t._blendFunc = src; 590 else 591 _t._blendFunc = {src: src, dst: dst}; 592 if (cc._renderType === cc._RENDER_TYPE_CANVAS) 593 _t._isLighterMode = (_t._blendFunc && (_t._blendFunc.src == 1) && (_t._blendFunc.dst == 771)); 594 }, 595 596 _setWidth: null, 597 598 _setHeight: null, 599 600 _updateColor: null, 601 602 updateDisplayedColor: function (parentColor) { 603 cc.LayerRGBA.prototype.updateDisplayedColor.call(this, parentColor); 604 this._updateColor(); 605 }, 606 607 updateDisplayedOpacity: function (parentOpacity) { 608 cc.LayerRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 609 this._updateColor(); 610 }, 611 612 /** 613 * Renders the layer 614 * @function 615 * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx 616 */ 617 draw: null 618 }); 619 620 /** 621 * creates a cc.Layer with color, width and height in Points 622 * @param {cc.Color} color 623 * @param {Number|Null} [width=] 624 * @param {Number|Null} [height=] 625 * @return {cc.LayerColor} 626 * @example 627 * // Example 628 * //Create a yellow color layer as background 629 * var yellowBackground = cc.LayerColor.create(cc.color(255,255,0,255)); 630 * //If you didnt pass in width and height, it defaults to the same size as the canvas 631 * 632 * //create a yellow box, 200 by 200 in size 633 * var yellowBox = cc.LayerColor.create(cc.color(255,255,0,255), 200, 200); 634 */ 635 cc.LayerColor.create = function (color, width, height) { 636 return new cc.LayerColor(color, width, height); 637 }; 638 639 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 640 //cc.LayerColor define start 641 var _p = cc.LayerColor.prototype; 642 _p.ctor = function (color, width, height) { 643 cc.LayerRGBA.prototype.ctor.call(this); 644 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 645 cc.LayerColor.prototype.init.call(this, color, width, height); 646 }; 647 _p._setWidth = cc.LayerRGBA.prototype._setWidth; 648 _p._setHeight = cc.LayerRGBA.prototype._setHeight; 649 _p._updateColor = function () { 650 }; 651 _p.draw = function (ctx) { 652 var context = ctx || cc._renderContext, _t = this; 653 var locEGLViewer = cc.view, locDisplayedColor = _t._displayedColor; 654 655 context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + "," 656 + (0 | locDisplayedColor.b) + "," + _t._displayedOpacity / 255 + ")"; 657 context.fillRect(0, 0, _t.width * locEGLViewer.getScaleX(), -_t.height * locEGLViewer.getScaleY()); 658 cc.g_NumberOfDraws++; 659 }; 660 661 //for bake 662 _p.visit = function(ctx){ 663 if(!this._isBaked){ 664 cc.Node.prototype.visit.call(this, ctx); 665 return; 666 } 667 668 var context = ctx || cc._renderContext, i; 669 var _t = this; 670 var children = _t._children; 671 var len = children.length; 672 // quick return if not visible 673 if (!_t._visible) 674 return; 675 676 var locBakeSprite = this._bakeSprite; 677 678 context.save(); 679 _t.transform(context); 680 681 if(this._cacheDirty){ 682 //compute the bounding box of the bake layer. 683 var boundingBox = this._getBoundingBoxForBake(); 684 boundingBox.width = 0 | boundingBox.width; 685 boundingBox.height = 0 | boundingBox.height; 686 var bakeContext = locBakeSprite.getCacheContext(); 687 locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height); 688 var anchor = locBakeSprite.getAnchorPointInPoints(), locPos = this._position; 689 if(this._ignoreAnchorPointForPosition){ 690 bakeContext.translate(0 - boundingBox.x + locPos.x, boundingBox.height + boundingBox.y - locPos.y); 691 //reset the bake sprite's position 692 locBakeSprite.setPosition(anchor.x + boundingBox.x - locPos.x, anchor.y + boundingBox.y - locPos.y); 693 } else { 694 var selfAnchor = this.getAnchorPointInPoints(); 695 var selfPos = {x: locPos.x - selfAnchor.x, y: locPos.y - selfAnchor.y}; 696 bakeContext.translate(0 - boundingBox.x + selfPos.x, boundingBox.height + boundingBox.y - selfPos.y); 697 locBakeSprite.setPosition(anchor.x + boundingBox.x - selfPos.x, anchor.y + boundingBox.y - selfPos.y); 698 } 699 700 var child; 701 //visit for canvas 702 if (len > 0) { 703 _t.sortAllChildren(); 704 // draw children zOrder < 0 705 for (i = 0; i < len; i++) { 706 child = children[i]; 707 if (child._localZOrder < 0) 708 child.visit(bakeContext); 709 else 710 break; 711 } 712 _t.draw(bakeContext); 713 for (; i < len; i++) { 714 children[i].visit(bakeContext); 715 } 716 } else 717 _t.draw(bakeContext); 718 this._cacheDirty = false; 719 } 720 721 //the bakeSprite is drawing 722 locBakeSprite.visit(context); 723 724 _t.arrivalOrder = 0; 725 context.restore(); 726 }; 727 728 _p._getBoundingBoxForBake = function () { 729 //default size 730 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 731 var trans = this.nodeToWorldTransform(); 732 rect = cc.RectApplyAffineTransform(rect, this.nodeToWorldTransform()); 733 734 //query child's BoundingBox 735 if (!this._children || this._children.length === 0) 736 return rect; 737 738 var locChildren = this._children; 739 for (var i = 0; i < locChildren.length; i++) { 740 var child = locChildren[i]; 741 if (child && child._visible) { 742 var childRect = child._getBoundingBoxToCurrentNode(trans); 743 rect = cc.rectUnion(rect, childRect); 744 } 745 } 746 return rect; 747 }; 748 749 //cc.LayerColor define end 750 _p = null; 751 } else { 752 cc.assert(typeof cc._tmp.WebGLLayerColor === "function", cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 753 cc._tmp.WebGLLayerColor(); 754 delete cc._tmp.WebGLLayerColor; 755 } 756 757 cc.assert(typeof cc._tmp.PrototypeLayerColor === "function", cc._LogInfos.MissingFile, "CCLayerPropertyDefine.js"); 758 cc._tmp.PrototypeLayerColor(); 759 delete cc._tmp.PrototypeLayerColor; 760 761 /** 762 * <p> 763 * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/> 764 *<br/> 765 * All features from cc.LayerColor are valid, plus the following new features:<br/> 766 * <ul><li>direction</li> 767 * <li>final color</li> 768 * <li>interpolation mode</li></ul> 769 * <br/> 770 * Color is interpolated between the startColor and endColor along the given<br/> 771 * vector (starting at the origin, ending at the terminus). If no vector is<br/> 772 * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/> 773 * <br/> 774 * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/> 775 * non-cardinal vectors; a smooth gradient implying both end points will be still<br/> 776 * be drawn, however.<br/> 777 *<br/> 778 * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. 779 * </p> 780 * @class 781 * @extends cc.LayerColor 782 * 783 * @property {cc.Color} startColor - Start color of the color gradient 784 * @property {cc.Color} endColor - End color of the color gradient 785 * @property {Number} startOpacity - Start opacity of the color gradient 786 * @property {Number} endOpacity - End opacity of the color gradient 787 * @property {Number} vector - Direction vector of the color gradient 788 * @property {Number} compresseInterpolation - Indicate whether or not the interpolation will be compressed 789 */ 790 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ 791 _startColor: null, 792 _endColor: null, 793 _startOpacity: 255, 794 _endOpacity: 255, 795 _alongVector: null, 796 _compressedInterpolation: false, 797 _gradientStartPoint: null, 798 _gradientEndPoint: null, 799 _className: "LayerGradient", 800 801 /** 802 * Constructor of cc.LayerGradient 803 * @param {cc.Color} start starting color 804 * @param {cc.Color} end 805 * @param {cc.Point|Null} v 806 */ 807 ctor: function (start, end, v) { 808 var _t = this; 809 cc.LayerColor.prototype.ctor.call(_t); 810 811 _t._startColor = cc.color(0, 0, 0, 255); 812 _t._endColor = cc.color(0, 0, 0, 255); 813 _t._alongVector = cc.p(0, -1); 814 _t._startOpacity = 255; 815 _t._endOpacity = 255; 816 _t._gradientStartPoint = cc.p(0, 0); 817 _t._gradientEndPoint = cc.p(0, 0); 818 cc.LayerGradient.prototype.init.call(_t, start, end, v); 819 }, 820 821 /** 822 * @param {cc.Color} start starting color 823 * @param {cc.Color} end 824 * @param {cc.Point|Null} v 825 * @return {Boolean} 826 */ 827 init: function (start, end, v) { 828 start = start || cc.color(0, 0, 0, 255); 829 end = end || cc.color(0, 0, 0, 255); 830 v = v || cc.p(0, -1); 831 var _t = this; 832 833 // Initializes the CCLayer with a gradient between start and end in the direction of v. 834 var locStartColor = _t._startColor, locEndColor = _t._endColor; 835 locStartColor.r = start.r; 836 locStartColor.g = start.g; 837 locStartColor.b = start.b; 838 _t._startOpacity = start.a; 839 840 locEndColor.r = end.r; 841 locEndColor.g = end.g; 842 locEndColor.b = end.b; 843 _t._endOpacity = end.a; 844 845 _t._alongVector = v; 846 _t._compressedInterpolation = true; 847 _t._gradientStartPoint = cc.p(0, 0); 848 _t._gradientEndPoint = cc.p(0, 0); 849 850 cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255)); 851 cc.LayerGradient.prototype._updateColor.call(_t); 852 return true; 853 }, 854 855 /** 856 * Sets the untransformed size of the LayerGradient. 857 * @override 858 * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient. 859 * @param {Number} [height] The untransformed size's height of the LayerGradient. 860 */ 861 setContentSize: function (size, height) { 862 cc.LayerColor.prototype.setContentSize.call(this, size, height); 863 this._updateColor(); 864 }, 865 866 _setWidth: function (width) { 867 cc.LayerColor.prototype._setWidth.call(this, width); 868 this._updateColor(); 869 }, 870 _setHeight: function (height) { 871 cc.LayerColor.prototype._setHeight.call(this, height); 872 this._updateColor(); 873 }, 874 875 /** 876 * get the starting color 877 * @return {cc.Color} 878 */ 879 getStartColor: function () { 880 return this._realColor; 881 }, 882 883 /** 884 * set the starting color 885 * @param {cc.Color} color 886 * @example 887 * // Example 888 * myGradientLayer.setStartColor(cc.color(255,0,0)); 889 * //set the starting gradient to red 890 */ 891 setStartColor: function (color) { 892 this.color = color; 893 }, 894 895 /** 896 * set the end gradient color 897 * @param {cc.Color} color 898 * @example 899 * // Example 900 * myGradientLayer.setEndColor(cc.color(255,0,0)); 901 * //set the ending gradient to red 902 */ 903 setEndColor: function (color) { 904 this._endColor = color; 905 this._updateColor(); 906 }, 907 908 /** 909 * get the end color 910 * @return {cc.Color} 911 */ 912 getEndColor: function () { 913 return this._endColor; 914 }, 915 916 /** 917 * set starting gradient opacity 918 * @param {Number} o from 0 to 255, 0 is transparent 919 */ 920 setStartOpacity: function (o) { 921 this._startOpacity = o; 922 this._updateColor(); 923 }, 924 925 /** 926 * get the starting gradient opacity 927 * @return {Number} 928 */ 929 getStartOpacity: function () { 930 return this._startOpacity; 931 }, 932 933 /** 934 * set the end gradient opacity 935 * @param {Number} o 936 */ 937 setEndOpacity: function (o) { 938 this._endOpacity = o; 939 this._updateColor(); 940 }, 941 942 /** 943 * get the end gradient opacity 944 * @return {Number} 945 */ 946 getEndOpacity: function () { 947 return this._endOpacity; 948 }, 949 950 /** 951 * set vector 952 * @param {cc.Point} Var 953 */ 954 setVector: function (Var) { 955 this._alongVector.x = Var.x; 956 this._alongVector.y = Var.y; 957 this._updateColor(); 958 }, 959 960 /** 961 * @return {cc.Point} 962 */ 963 getVector: function () { 964 return cc.p(this._alongVector.x, this._alongVector.y); 965 }, 966 967 /** is Compressed Interpolation 968 * @return {Boolean} 969 */ 970 isCompressedInterpolation: function () { 971 return this._compressedInterpolation; 972 }, 973 974 /** 975 * @param {Boolean} compress 976 */ 977 setCompressedInterpolation: function (compress) { 978 this._compressedInterpolation = compress; 979 this._updateColor(); 980 }, 981 982 _draw: null, 983 984 _updateColor: null 985 }); 986 987 /** 988 * creates a gradient layer 989 * @param {cc.Color} start starting color 990 * @param {cc.Color} end ending color 991 * @param {cc.Point|Null} v 992 * @return {cc.LayerGradient} 993 */ 994 cc.LayerGradient.create = function (start, end, v) { 995 return new cc.LayerGradient(start, end, v); 996 }; 997 998 999 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 1000 //cc.LayerGradient define start 1001 var _p = cc.LayerGradient.prototype; 1002 _p.draw = function (ctx) { 1003 var context = ctx || cc._renderContext, _t = this; 1004 if (_t._isLighterMode) 1005 context.globalCompositeOperation = 'lighter'; 1006 1007 context.save(); 1008 var locEGLViewer = cc.view, opacityf = _t._displayedOpacity / 255.0; 1009 var tWidth = _t.width * locEGLViewer.getScaleX(), tHeight = _t.height * locEGLViewer.getScaleY(); 1010 var tGradient = context.createLinearGradient(_t._gradientStartPoint.x, _t._gradientStartPoint.y, 1011 _t._gradientEndPoint.x, _t._gradientEndPoint.y); 1012 var locDisplayedColor = _t._displayedColor, locEndColor = _t._endColor; 1013 tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + "," 1014 + Math.round(locDisplayedColor.b) + "," + (opacityf * (_t._startOpacity / 255)).toFixed(4) + ")"); 1015 tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + "," 1016 + Math.round(locEndColor.b) + "," + (opacityf * (_t._endOpacity / 255)).toFixed(4) + ")"); 1017 context.fillStyle = tGradient; 1018 context.fillRect(0, 0, tWidth, -tHeight); 1019 1020 if (_t._rotation != 0) 1021 context.rotate(_t._rotationRadians); 1022 context.restore(); 1023 }; 1024 _p._updateColor = function () { 1025 var _t = this; 1026 var locAlongVector = _t._alongVector, tWidth = _t.width * 0.5, tHeight = _t.height * 0.5; 1027 1028 _t._gradientStartPoint.x = tWidth * (-locAlongVector.x) + tWidth; 1029 _t._gradientStartPoint.y = tHeight * locAlongVector.y - tHeight; 1030 _t._gradientEndPoint.x = tWidth * locAlongVector.x + tWidth; 1031 _t._gradientEndPoint.y = tHeight * (-locAlongVector.y) - tHeight; 1032 }; 1033 //cc.LayerGradient define end 1034 _p = null; 1035 } else { 1036 cc.assert(typeof cc._tmp.WebGLLayerGradient === "function", cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 1037 cc._tmp.WebGLLayerGradient(); 1038 delete cc._tmp.WebGLLayerGradient; 1039 } 1040 1041 cc.assert(typeof cc._tmp.PrototypeLayerGradient === "function", cc._LogInfos.MissingFile, "CCLayerPropertyDefine.js"); 1042 cc._tmp.PrototypeLayerGradient(); 1043 delete cc._tmp.PrototypeLayerGradient; 1044 1045 /** 1046 * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/> 1047 * Features:<br/> 1048 * <ul><li>- It supports one or more children</li> 1049 * <li>- Only one children will be active a time</li></ul> 1050 * @class 1051 * @extends cc.Layer 1052 */ 1053 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{ 1054 _enabledLayer: 0, 1055 _layers: null, 1056 _className: "LayerMultiplex", 1057 1058 /** 1059 * Constructor of cc.LayerMultiplex 1060 * @param {Array} layers an array of cc.Layer 1061 */ 1062 ctor: function (layers) { 1063 cc.Layer.prototype.ctor.call(this); 1064 layers && cc.LayerMultiplex.prototype.initWithLayers.call(this, layers); 1065 }, 1066 1067 /** 1068 * @param {Array} layers an array of cc.Layer 1069 * @return {Boolean} 1070 */ 1071 initWithLayers: function (layers) { 1072 if ((layers.length > 0) && (layers[layers.length - 1] == null)) 1073 cc.log(cc._LogInfos.LayerMultiplex_initWithLayers); 1074 1075 this._layers = layers; 1076 this._enabledLayer = 0; 1077 this.addChild(this._layers[this._enabledLayer]); 1078 return true; 1079 }, 1080 1081 /** 1082 * switches to a certain layer indexed by n.<br/> 1083 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 1084 * @param {Number} n the layer index to switch to 1085 */ 1086 switchTo: function (n) { 1087 if (n >= this._layers.length) { 1088 cc.log(cc._LogInfos.LayerMultiplex_switchTo); 1089 return; 1090 } 1091 1092 this.removeChild(this._layers[this._enabledLayer], true); 1093 this._enabledLayer = n; 1094 this.addChild(this._layers[n]); 1095 }, 1096 1097 /** release the current layer and switches to another layer indexed by n.<br/> 1098 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 1099 * @param {Number} n the layer index to switch to 1100 */ 1101 switchToAndReleaseMe: function (n) { 1102 if (n >= this._layers.length) { 1103 cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe); 1104 return; 1105 } 1106 1107 this.removeChild(this._layers[this._enabledLayer], true); 1108 1109 //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]]; 1110 this._layers[this._enabledLayer] = null; 1111 this._enabledLayer = n; 1112 this.addChild(this._layers[n]); 1113 }, 1114 1115 /** 1116 * @param {cc.Layer} layer 1117 */ 1118 addLayer: function (layer) { 1119 if (!layer) { 1120 cc.log(cc._LogInfos.LayerMultiplex_addLayer); 1121 return; 1122 } 1123 this._layers.push(layer); 1124 } 1125 }); 1126 1127 /** 1128 * creates a cc.LayerMultiplex with one or more layers using a variable argument list. 1129 * @return {cc.LayerMultiplex|Null} 1130 * @example 1131 * // Example 1132 * var multiLayer = cc.LayerMultiple.create(layer1, layer2, layer3);//any number of layers 1133 */ 1134 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) { 1135 return new cc.LayerMultiplex(arguments); 1136 }; 1137 1138