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