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 bake feature: Baked layer can cache a static layer to improve performance 29 * @class 30 * @extends cc.Node 31 */ 32 cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ 33 _isBaked: false, 34 _bakeSprite: null, 35 _className: "Layer", 36 37 /** 38 * <p>Constructor of cc.Layer, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.</p> 39 */ 40 ctor: function () { 41 var nodep = cc.Node.prototype; 42 nodep.ctor.call(this); 43 this._ignoreAnchorPointForPosition = true; 44 nodep.setAnchorPoint.call(this, 0.5, 0.5); 45 nodep.setContentSize.call(this, cc.winSize); 46 }, 47 48 /** 49 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 50 */ 51 init: function(){ 52 var _t = this; 53 _t._ignoreAnchorPointForPosition = true; 54 _t.setAnchorPoint(0.5, 0.5); 55 _t.setContentSize(cc.winSize); 56 _t.cascadeOpacity = false; 57 _t.cascadeColor = false; 58 return true; 59 }, 60 61 /** 62 * Sets the layer to cache all of children to a bake sprite, and draw itself by bake sprite. recommend using it in UI.<br/> 63 * This is useful only in html5 engine 64 * @function 65 * @see cc.Layer#unbake 66 */ 67 bake: null, 68 69 /** 70 * Cancel the layer to cache all of children to a bake sprite.<br/> 71 * This is useful only in html5 engine 72 * @function 73 * @see cc.Layer#bake 74 */ 75 unbake: null, 76 77 /** 78 * Determines if the layer is baked. 79 * @function 80 * @returns {boolean} 81 * @see cc.Layer#bake and cc.Layer#unbake 82 */ 83 isBaked: function(){ 84 return this._isBaked; 85 }, 86 87 visit: null 88 }); 89 90 /** 91 * Creates a layer 92 * @deprecated since v3.0, please use the new construction instead 93 * @see cc.Layer 94 * @return {cc.Layer|Null} 95 */ 96 cc.Layer.create = function () { 97 return new cc.Layer(); 98 }; 99 100 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 101 var p = cc.Layer.prototype; 102 p.bake = function(){ 103 if (!this._isBaked) { 104 //limit: 1. its children's blendfunc are invalid. 105 this._isBaked = this._cacheDirty = true; 106 107 this._cachedParent = this; 108 var children = this._children; 109 for(var i = 0, len = children.length; i < len; i++) 110 children[i]._setCachedParent(this); 111 112 if (!this._bakeSprite) 113 this._bakeSprite = new cc.BakeSprite(); 114 } 115 }; 116 117 p.unbake = function(){ 118 if (this._isBaked) { 119 this._isBaked = false; 120 this._cacheDirty = true; 121 122 this._cachedParent = null; 123 var children = this._children; 124 for(var i = 0, len = children.length; i < len; i++) 125 children[i]._setCachedParent(null); 126 } 127 }; 128 129 p.addChild = function(child, localZOrder, tag){ 130 cc.Node.prototype.addChild.call(this, child, localZOrder, tag); 131 if(child._parent == this && this._isBaked) 132 child._setCachedParent(this); 133 }; 134 135 p.visit = function(ctx){ 136 if(!this._isBaked){ 137 cc.Node.prototype.visit.call(this, ctx); 138 return; 139 } 140 141 var context = ctx || cc._renderContext, i; 142 var _t = this; 143 var children = _t._children; 144 var len = children.length; 145 // quick return if not visible 146 if (!_t._visible || len === 0) 147 return; 148 149 var locBakeSprite = this._bakeSprite; 150 151 context.save(); 152 _t.transform(context); 153 154 if(this._cacheDirty){ 155 //compute the bounding box of the bake layer. 156 var boundingBox = this._getBoundingBoxForBake(); 157 boundingBox.width = 0 | boundingBox.width; 158 boundingBox.height = 0 | boundingBox.height; 159 var bakeContext = locBakeSprite.getCacheContext(); 160 locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height); 161 bakeContext.translate(0 - boundingBox.x, boundingBox.height + boundingBox.y); 162 163 //reset the bake sprite's position 164 var anchor = locBakeSprite.getAnchorPointInPoints(); 165 locBakeSprite.setPosition(anchor.x + boundingBox.x, anchor.y + boundingBox.y); 166 167 //visit for canvas 168 _t.sortAllChildren(); 169 cc.view._setScaleXYForRenderTexture(); 170 for (i = 0; i < len; i++) { 171 children[i].visit(bakeContext); 172 } 173 cc.view._resetScale(); 174 this._cacheDirty = false; 175 } 176 177 //the bakeSprite is drawing 178 locBakeSprite.visit(context); 179 180 _t.arrivalOrder = 0; 181 context.restore(); 182 }; 183 184 p._getBoundingBoxForBake = function () { 185 var rect = null; 186 187 //query child's BoundingBox 188 if (!this._children || this._children.length === 0) 189 return cc.rect(0, 0, 10, 10); 190 191 var locChildren = this._children; 192 for (var i = 0; i < locChildren.length; i++) { 193 var child = locChildren[i]; 194 if (child && child._visible) { 195 if(rect){ 196 var childRect = child._getBoundingBoxToCurrentNode(); 197 if (childRect) 198 rect = cc.rectUnion(rect, childRect); 199 }else{ 200 rect = child._getBoundingBoxToCurrentNode(); 201 } 202 } 203 } 204 return rect; 205 }; 206 p = null; 207 }else{ 208 cc.assert(cc.isFunction(cc._tmp.LayerDefineForWebGL), cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 209 cc._tmp.LayerDefineForWebGL(); 210 delete cc._tmp.LayerDefineForWebGL; 211 } 212 213 /** 214 * <p> 215 * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. <br/> 216 * All features from CCLayer are valid, plus the following new features: <br/> 217 * - opacity <br/> 218 * - RGB colors </p> 219 * @class 220 * @extends cc.Layer 221 * 222 * @param {cc.Color} [color=] The color of the layer 223 * @param {Number} [width=] The width of the layer 224 * @param {Number} [height=] The height of the layer 225 * 226 * @example 227 * // Example 228 * //Create a yellow color layer as background 229 * var yellowBackground = new cc.LayerColor(cc.color(255,255,0,255)); 230 * //If you didnt pass in width and height, it defaults to the same size as the canvas 231 * 232 * //create a yellow box, 200 by 200 in size 233 * var yellowBox = new cc.LayerColor(cc.color(255,255,0,255), 200, 200); 234 */ 235 cc.LayerColor = cc.Layer.extend(/** @lends cc.LayerColor# */{ 236 _blendFunc: null, 237 _className: "LayerColor", 238 239 /** 240 * Returns the blend function 241 * @return {cc.BlendFunc} 242 */ 243 getBlendFunc: function () { 244 return this._blendFunc; 245 }, 246 247 /** 248 * Changes width and height 249 * @deprecated since v3.0 please use setContentSize instead 250 * @see cc.Node#setContentSize 251 * @param {Number} w width 252 * @param {Number} h height 253 */ 254 changeWidthAndHeight: function (w, h) { 255 this.width = w; 256 this.height = h; 257 }, 258 259 /** 260 * Changes width in Points 261 * @deprecated since v3.0 please use setContentSize instead 262 * @see cc.Node#setContentSize 263 * @param {Number} w width 264 */ 265 changeWidth: function (w) { 266 this.width = w; 267 }, 268 269 /** 270 * change height in Points 271 * @deprecated since v3.0 please use setContentSize instead 272 * @see cc.Node#setContentSize 273 * @param {Number} h height 274 */ 275 changeHeight: function (h) { 276 this.height = h; 277 }, 278 279 setOpacityModifyRGB: function (value) { 280 }, 281 282 isOpacityModifyRGB: function () { 283 return false; 284 }, 285 286 setColor: function (color) { 287 cc.Layer.prototype.setColor.call(this, color); 288 this._updateColor(); 289 }, 290 291 setOpacity: function (opacity) { 292 cc.Layer.prototype.setOpacity.call(this, opacity); 293 this._updateColor(); 294 }, 295 296 _blendFuncStr: "source", 297 298 /** 299 * Constructor of cc.LayerColor 300 * @function 301 * @param {cc.Color} [color=] 302 * @param {Number} [width=] 303 * @param {Number} [height=] 304 */ 305 ctor: null, 306 307 /** 308 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 309 * @param {cc.Color} [color=] 310 * @param {Number} [width=] 311 * @param {Number} [height=] 312 * @return {Boolean} 313 */ 314 init: function (color, width, height) { 315 if (cc._renderType !== cc._RENDER_TYPE_CANVAS) 316 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR); 317 318 var winSize = cc.director.getWinSize(); 319 color = color || cc.color(0, 0, 0, 255); 320 width = width === undefined ? winSize.width : width; 321 height = height === undefined ? winSize.height : height; 322 323 var locDisplayedColor = this._displayedColor; 324 locDisplayedColor.r = color.r; 325 locDisplayedColor.g = color.g; 326 locDisplayedColor.b = color.b; 327 328 var locRealColor = this._realColor; 329 locRealColor.r = color.r; 330 locRealColor.g = color.g; 331 locRealColor.b = color.b; 332 333 this._displayedOpacity = color.a; 334 this._realOpacity = color.a; 335 336 var proto = cc.LayerColor.prototype; 337 proto.setContentSize.call(this, width, height); 338 proto._updateColor.call(this); 339 return true; 340 }, 341 342 /** 343 * Sets the blend func, you can pass either a cc.BlendFunc object or source and destination value separately 344 * @param {Number|cc.BlendFunc} src 345 * @param {Number} [dst] 346 */ 347 setBlendFunc: function (src, dst) { 348 var _t = this, locBlendFunc = this._blendFunc; 349 if (dst === undefined) { 350 locBlendFunc.src = src.src; 351 locBlendFunc.dst = src.dst; 352 } else { 353 locBlendFunc.src = src; 354 locBlendFunc.dst = dst; 355 } 356 if (cc._renderType === cc._RENDER_TYPE_CANVAS) 357 _t._blendFuncStr = cc._getCompositeOperationByBlendFunc(locBlendFunc); 358 }, 359 360 _setWidth: null, 361 362 _setHeight: null, 363 364 _updateColor: null, 365 366 updateDisplayedColor: function (parentColor) { 367 cc.Layer.prototype.updateDisplayedColor.call(this, parentColor); 368 this._updateColor(); 369 }, 370 371 updateDisplayedOpacity: function (parentOpacity) { 372 cc.Layer.prototype.updateDisplayedOpacity.call(this, parentOpacity); 373 this._updateColor(); 374 }, 375 376 draw: null 377 }); 378 379 /** 380 * Creates a cc.Layer with color, width and height in Points 381 * @deprecated since v3.0 please use the new construction instead 382 * @see cc.LayerColor 383 * @param {cc.Color} color 384 * @param {Number|Null} [width=] 385 * @param {Number|Null} [height=] 386 * @return {cc.LayerColor} 387 */ 388 cc.LayerColor.create = function (color, width, height) { 389 return new cc.LayerColor(color, width, height); 390 }; 391 392 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 393 //cc.LayerColor define start 394 var _p = cc.LayerColor.prototype; 395 _p.ctor = function (color, width, height) { 396 cc.Layer.prototype.ctor.call(this); 397 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 398 cc.LayerColor.prototype.init.call(this, color, width, height); 399 }; 400 _p._setWidth = cc.Layer.prototype._setWidth; 401 _p._setHeight = cc.Layer.prototype._setHeight; 402 _p._updateColor = function () { 403 }; 404 _p.draw = function (ctx) { 405 var context = ctx || cc._renderContext, _t = this; 406 var locEGLViewer = cc.view, locDisplayedColor = _t._displayedColor; 407 408 context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + "," 409 + (0 | locDisplayedColor.b) + "," + _t._displayedOpacity / 255 + ")"; 410 context.fillRect(0, 0, _t.width * locEGLViewer.getScaleX(), -_t.height * locEGLViewer.getScaleY()); 411 cc.g_NumberOfDraws++; 412 }; 413 414 //for bake 415 _p.visit = function(ctx){ 416 if(!this._isBaked){ 417 cc.Node.prototype.visit.call(this, ctx); 418 return; 419 } 420 421 var context = ctx || cc._renderContext, i; 422 var _t = this; 423 var children = _t._children; 424 var len = children.length; 425 // quick return if not visible 426 if (!_t._visible) 427 return; 428 429 var locBakeSprite = this._bakeSprite; 430 431 context.save(); 432 _t.transform(context); 433 434 if(this._cacheDirty){ 435 //compute the bounding box of the bake layer. 436 var boundingBox = this._getBoundingBoxForBake(); 437 boundingBox.width = 0 | boundingBox.width; 438 boundingBox.height = 0 | boundingBox.height; 439 var bakeContext = locBakeSprite.getCacheContext(); 440 locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height); 441 var anchor = locBakeSprite.getAnchorPointInPoints(), locPos = this._position; 442 if(this._ignoreAnchorPointForPosition){ 443 bakeContext.translate(0 - boundingBox.x + locPos.x, boundingBox.height + boundingBox.y - locPos.y); 444 //reset the bake sprite's position 445 locBakeSprite.setPosition(anchor.x + boundingBox.x - locPos.x, anchor.y + boundingBox.y - locPos.y); 446 } else { 447 var selfAnchor = this.getAnchorPointInPoints(); 448 var selfPos = {x: locPos.x - selfAnchor.x, y: locPos.y - selfAnchor.y}; 449 bakeContext.translate(0 - boundingBox.x + selfPos.x, boundingBox.height + boundingBox.y - selfPos.y); 450 locBakeSprite.setPosition(anchor.x + boundingBox.x - selfPos.x, anchor.y + boundingBox.y - selfPos.y); 451 } 452 453 var child; 454 cc.view._setScaleXYForRenderTexture(); 455 //visit for canvas 456 if (len > 0) { 457 _t.sortAllChildren(); 458 // draw children zOrder < 0 459 for (i = 0; i < len; i++) { 460 child = children[i]; 461 if (child._localZOrder < 0) 462 child.visit(bakeContext); 463 else 464 break; 465 } 466 _t.draw(bakeContext); 467 for (; i < len; i++) { 468 children[i].visit(bakeContext); 469 } 470 } else 471 _t.draw(bakeContext); 472 cc.view._resetScale(); 473 this._cacheDirty = false; 474 } 475 476 //the bakeSprite is drawing 477 locBakeSprite.visit(context); 478 479 _t.arrivalOrder = 0; 480 context.restore(); 481 }; 482 483 _p._getBoundingBoxForBake = function () { 484 //default size 485 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 486 var trans = this.nodeToWorldTransform(); 487 rect = cc.rectApplyAffineTransform(rect, this.nodeToWorldTransform()); 488 489 //query child's BoundingBox 490 if (!this._children || this._children.length === 0) 491 return rect; 492 493 var locChildren = this._children; 494 for (var i = 0; i < locChildren.length; i++) { 495 var child = locChildren[i]; 496 if (child && child._visible) { 497 var childRect = child._getBoundingBoxToCurrentNode(trans); 498 rect = cc.rectUnion(rect, childRect); 499 } 500 } 501 return rect; 502 }; 503 504 //cc.LayerColor define end 505 _p = null; 506 } else { 507 cc.assert(cc.isFunction(cc._tmp.WebGLLayerColor), cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 508 cc._tmp.WebGLLayerColor(); 509 delete cc._tmp.WebGLLayerColor; 510 } 511 512 cc.assert(cc.isFunction(cc._tmp.PrototypeLayerColor), cc._LogInfos.MissingFile, "CCLayerPropertyDefine.js"); 513 cc._tmp.PrototypeLayerColor(); 514 delete cc._tmp.PrototypeLayerColor; 515 516 /** 517 * <p> 518 * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/> 519 *<br/> 520 * All features from cc.LayerColor are valid, plus the following new features:<br/> 521 * <ul><li>direction</li> 522 * <li>final color</li> 523 * <li>interpolation mode</li></ul> 524 * <br/> 525 * Color is interpolated between the startColor and endColor along the given<br/> 526 * vector (starting at the origin, ending at the terminus). If no vector is<br/> 527 * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/> 528 * <br/> 529 * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/> 530 * non-cardinal vectors; a smooth gradient implying both end points will be still<br/> 531 * be drawn, however.<br/> 532 *<br/> 533 * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. 534 * </p> 535 * @class 536 * @extends cc.LayerColor 537 * 538 * @param {cc.Color} start Starting color 539 * @param {cc.Color} end Ending color 540 * @param {cc.Point} [v=cc.p(0, -1)] A vector defines the gradient direction, default direction is from top to bottom 541 * 542 * @property {cc.Color} startColor - Start color of the color gradient 543 * @property {cc.Color} endColor - End color of the color gradient 544 * @property {Number} startOpacity - Start opacity of the color gradient 545 * @property {Number} endOpacity - End opacity of the color gradient 546 * @property {Number} vector - Direction vector of the color gradient 547 * @property {Number} compresseInterpolation - Indicate whether or not the interpolation will be compressed 548 */ 549 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ 550 _startColor: null, 551 _endColor: null, 552 _startOpacity: 255, 553 _endOpacity: 255, 554 _alongVector: null, 555 _compressedInterpolation: false, 556 _gradientStartPoint: null, 557 _gradientEndPoint: null, 558 _className: "LayerGradient", 559 560 /** 561 * Constructor of cc.LayerGradient 562 * @param {cc.Color} start 563 * @param {cc.Color} end 564 * @param {cc.Point} [v=cc.p(0, -1)] 565 */ 566 ctor: function (start, end, v) { 567 var _t = this; 568 cc.LayerColor.prototype.ctor.call(_t); 569 570 _t._startColor = cc.color(0, 0, 0, 255); 571 _t._endColor = cc.color(0, 0, 0, 255); 572 _t._alongVector = cc.p(0, -1); 573 _t._startOpacity = 255; 574 _t._endOpacity = 255; 575 _t._gradientStartPoint = cc.p(0, 0); 576 _t._gradientEndPoint = cc.p(0, 0); 577 cc.LayerGradient.prototype.init.call(_t, start, end, v); 578 }, 579 580 /** 581 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 582 * @param {cc.Color} start starting color 583 * @param {cc.Color} end 584 * @param {cc.Point|Null} v 585 * @return {Boolean} 586 */ 587 init: function (start, end, v) { 588 start = start || cc.color(0, 0, 0, 255); 589 end = end || cc.color(0, 0, 0, 255); 590 v = v || cc.p(0, -1); 591 var _t = this; 592 593 // Initializes the CCLayer with a gradient between start and end in the direction of v. 594 var locStartColor = _t._startColor, locEndColor = _t._endColor; 595 locStartColor.r = start.r; 596 locStartColor.g = start.g; 597 locStartColor.b = start.b; 598 _t._startOpacity = start.a; 599 600 locEndColor.r = end.r; 601 locEndColor.g = end.g; 602 locEndColor.b = end.b; 603 _t._endOpacity = end.a; 604 605 _t._alongVector = v; 606 _t._compressedInterpolation = true; 607 _t._gradientStartPoint = cc.p(0, 0); 608 _t._gradientEndPoint = cc.p(0, 0); 609 610 cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255)); 611 cc.LayerGradient.prototype._updateColor.call(_t); 612 return true; 613 }, 614 615 /** 616 * Sets the untransformed size of the LayerGradient. 617 * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient. 618 * @param {Number} [height] The untransformed size's height of the LayerGradient. 619 */ 620 setContentSize: function (size, height) { 621 cc.LayerColor.prototype.setContentSize.call(this, size, height); 622 this._updateColor(); 623 }, 624 625 _setWidth: function (width) { 626 cc.LayerColor.prototype._setWidth.call(this, width); 627 this._updateColor(); 628 }, 629 _setHeight: function (height) { 630 cc.LayerColor.prototype._setHeight.call(this, height); 631 this._updateColor(); 632 }, 633 634 /** 635 * Returns the starting color 636 * @return {cc.Color} 637 */ 638 getStartColor: function () { 639 return this._realColor; 640 }, 641 642 /** 643 * Sets the starting color 644 * @param {cc.Color} color 645 * @example 646 * // Example 647 * myGradientLayer.setStartColor(cc.color(255,0,0)); 648 * //set the starting gradient to red 649 */ 650 setStartColor: function (color) { 651 this.color = color; 652 }, 653 654 /** 655 * Sets the end gradient color 656 * @param {cc.Color} color 657 * @example 658 * // Example 659 * myGradientLayer.setEndColor(cc.color(255,0,0)); 660 * //set the ending gradient to red 661 */ 662 setEndColor: function (color) { 663 this._endColor = color; 664 this._updateColor(); 665 }, 666 667 /** 668 * Returns the end color 669 * @return {cc.Color} 670 */ 671 getEndColor: function () { 672 return this._endColor; 673 }, 674 675 /** 676 * Sets starting gradient opacity 677 * @param {Number} o from 0 to 255, 0 is transparent 678 */ 679 setStartOpacity: function (o) { 680 this._startOpacity = o; 681 this._updateColor(); 682 }, 683 684 /** 685 * Returns the starting gradient opacity 686 * @return {Number} 687 */ 688 getStartOpacity: function () { 689 return this._startOpacity; 690 }, 691 692 /** 693 * Sets the end gradient opacity 694 * @param {Number} o 695 */ 696 setEndOpacity: function (o) { 697 this._endOpacity = o; 698 this._updateColor(); 699 }, 700 701 /** 702 * Returns the end gradient opacity 703 * @return {Number} 704 */ 705 getEndOpacity: function () { 706 return this._endOpacity; 707 }, 708 709 /** 710 * Sets the direction vector of the gradient 711 * @param {cc.Point} Var 712 */ 713 setVector: function (Var) { 714 this._alongVector.x = Var.x; 715 this._alongVector.y = Var.y; 716 this._updateColor(); 717 }, 718 719 /** 720 * Returns the direction vector of the gradient 721 * @return {cc.Point} 722 */ 723 getVector: function () { 724 return cc.p(this._alongVector.x, this._alongVector.y); 725 }, 726 727 /** 728 * Returns whether compressed interpolation is enabled 729 * @return {Boolean} 730 */ 731 isCompressedInterpolation: function () { 732 return this._compressedInterpolation; 733 }, 734 735 /** 736 * Sets whether compressed interpolation is enabled 737 * @param {Boolean} compress 738 */ 739 setCompressedInterpolation: function (compress) { 740 this._compressedInterpolation = compress; 741 this._updateColor(); 742 }, 743 744 _draw: null, 745 746 _updateColor: null 747 }); 748 749 /** 750 * Creates a gradient layer 751 * @deprecated since v3.0, please use the new construction instead 752 * @see cc.layerGradient 753 * @param {cc.Color} start starting color 754 * @param {cc.Color} end ending color 755 * @param {cc.Point|Null} v 756 * @return {cc.LayerGradient} 757 */ 758 cc.LayerGradient.create = function (start, end, v) { 759 return new cc.LayerGradient(start, end, v); 760 }; 761 762 763 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 764 //cc.LayerGradient define start 765 var _p = cc.LayerGradient.prototype; 766 _p.draw = function (ctx) { 767 var context = ctx || cc._renderContext, _t = this; 768 if (_t._blendFuncStr != "source") 769 context.globalCompositeOperation = _t._blendFuncStr; 770 771 context.save(); 772 var opacityf = _t._displayedOpacity / 255.0; 773 var scaleX = cc.view.getScaleX(), scaleY = cc.view.getScaleY(); 774 var tWidth = _t.width * scaleX, tHeight = _t.height * scaleY; 775 var tGradient = context.createLinearGradient(_t._gradientStartPoint.x * scaleX, _t._gradientStartPoint.y * scaleY, 776 _t._gradientEndPoint.x * scaleX, _t._gradientEndPoint.y * scaleY); 777 var locDisplayedColor = _t._displayedColor, locEndColor = _t._endColor; 778 tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + "," 779 + Math.round(locDisplayedColor.b) + "," + (opacityf * (_t._startOpacity / 255)).toFixed(4) + ")"); 780 tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + "," 781 + Math.round(locEndColor.b) + "," + (opacityf * (_t._endOpacity / 255)).toFixed(4) + ")"); 782 context.fillStyle = tGradient; 783 context.fillRect(0, 0, tWidth, -tHeight); 784 785 if (_t._rotation != 0) 786 context.rotate(_t._rotationRadians); 787 context.restore(); 788 cc.g_NumberOfDraws++; 789 }; 790 _p._updateColor = function () { 791 var _t = this; 792 var locAlongVector = _t._alongVector, tWidth = _t.width * 0.5, tHeight = _t.height * 0.5; 793 794 _t._gradientStartPoint.x = tWidth * (-locAlongVector.x) + tWidth; 795 _t._gradientStartPoint.y = tHeight * locAlongVector.y - tHeight; 796 _t._gradientEndPoint.x = tWidth * locAlongVector.x + tWidth; 797 _t._gradientEndPoint.y = tHeight * (-locAlongVector.y) - tHeight; 798 }; 799 //cc.LayerGradient define end 800 _p = null; 801 } else { 802 cc.assert(cc.isFunction(cc._tmp.WebGLLayerGradient), cc._LogInfos.MissingFile, "CCLayerWebGL.js"); 803 cc._tmp.WebGLLayerGradient(); 804 delete cc._tmp.WebGLLayerGradient; 805 } 806 807 cc.assert(cc.isFunction(cc._tmp.PrototypeLayerGradient), cc._LogInfos.MissingFile, "CCLayerPropertyDefine.js"); 808 cc._tmp.PrototypeLayerGradient(); 809 delete cc._tmp.PrototypeLayerGradient; 810 811 /** 812 * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/> 813 * Features:<br/> 814 * <ul><li>- It supports one or more children</li> 815 * <li>- Only one children will be active a time</li></ul> 816 * @class 817 * @extends cc.Layer 818 * @param {Array} layers an array of cc.Layer 819 * @example 820 * // Example 821 * var multiLayer = new cc.LayerMultiple(layer1, layer2, layer3);//any number of layers 822 */ 823 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{ 824 _enabledLayer: 0, 825 _layers: null, 826 _className: "LayerMultiplex", 827 828 /** 829 * Constructor of cc.LayerMultiplex 830 * @param {Array} layers an array of cc.Layer 831 */ 832 ctor: function (layers) { 833 cc.Layer.prototype.ctor.call(this); 834 if (layers instanceof Array) 835 cc.LayerMultiplex.prototype.initWithLayers.call(this, layers); 836 else 837 cc.LayerMultiplex.prototype.initWithLayers.call(this, Array.prototype.slice.call(arguments)); 838 }, 839 840 /** 841 * Initialization of the layer multiplex, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer multiplex 842 * @param {Array} layers an array of cc.Layer 843 * @return {Boolean} 844 */ 845 initWithLayers: function (layers) { 846 if ((layers.length > 0) && (layers[layers.length - 1] == null)) 847 cc.log(cc._LogInfos.LayerMultiplex_initWithLayers); 848 849 this._layers = layers; 850 this._enabledLayer = 0; 851 this.addChild(this._layers[this._enabledLayer]); 852 return true; 853 }, 854 855 /** 856 * Switches to a certain layer indexed by n.<br/> 857 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 858 * @param {Number} n the layer index to switch to 859 */ 860 switchTo: function (n) { 861 if (n >= this._layers.length) { 862 cc.log(cc._LogInfos.LayerMultiplex_switchTo); 863 return; 864 } 865 866 this.removeChild(this._layers[this._enabledLayer], true); 867 this._enabledLayer = n; 868 this.addChild(this._layers[n]); 869 }, 870 871 /** 872 * Release the current layer and switches to another layer indexed by n.<br/> 873 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 874 * @param {Number} n the layer index to switch to 875 */ 876 switchToAndReleaseMe: function (n) { 877 if (n >= this._layers.length) { 878 cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe); 879 return; 880 } 881 882 this.removeChild(this._layers[this._enabledLayer], true); 883 884 //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]]; 885 this._layers[this._enabledLayer] = null; 886 this._enabledLayer = n; 887 this.addChild(this._layers[n]); 888 }, 889 890 /** 891 * Add a layer to the multiplex layers list 892 * @param {cc.Layer} layer 893 */ 894 addLayer: function (layer) { 895 if (!layer) { 896 cc.log(cc._LogInfos.LayerMultiplex_addLayer); 897 return; 898 } 899 this._layers.push(layer); 900 } 901 }); 902 903 /** 904 * Creates a cc.LayerMultiplex with one or more layers using a variable argument list. 905 * @deprecated since v3.0, please use new construction instead 906 * @see cc.LayerMultiplex 907 * @return {cc.LayerMultiplex|Null} 908 */ 909 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) { 910 return new cc.LayerMultiplex(Array.prototype.slice.call(arguments)); 911 };