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 _className: "Layer", 34 35 /** 36 * <p>Constructor of cc.Layer, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.</p> 37 */ 38 ctor: function () { 39 var nodep = cc.Node.prototype; 40 nodep.ctor.call(this); 41 this._ignoreAnchorPointForPosition = true; 42 nodep.setAnchorPoint.call(this, 0.5, 0.5); 43 nodep.setContentSize.call(this, cc.winSize); 44 }, 45 46 /** 47 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 48 */ 49 init: function(){ 50 var _t = this; 51 _t._ignoreAnchorPointForPosition = true; 52 _t.setAnchorPoint(0.5, 0.5); 53 _t.setContentSize(cc.winSize); 54 _t._cascadeColorEnabled = false; 55 _t._cascadeOpacityEnabled = false; 56 return true; 57 }, 58 59 /** 60 * Sets the layer to cache all of children to a bake sprite, and draw itself by bake sprite. recommend using it in UI.<br/> 61 * This is useful only in html5 engine 62 * @function 63 * @see cc.Layer#unbake 64 */ 65 bake: function(){ 66 this._renderCmd.bake(); 67 }, 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: function(){ 76 this._renderCmd.unbake(); 77 }, 78 79 /** 80 * Determines if the layer is baked. 81 * @function 82 * @returns {boolean} 83 * @see cc.Layer#bake and cc.Layer#unbake 84 */ 85 isBaked: function(){ 86 return this._isBaked; 87 }, 88 89 addChild: function(child, localZOrder, tag){ 90 cc.Node.prototype.addChild.call(this, child, localZOrder, tag); 91 this._renderCmd._bakeForAddChild(child); 92 }, 93 94 _createRenderCmd: function(){ 95 if (cc._renderType === cc._RENDER_TYPE_CANVAS) 96 return new cc.Layer.CanvasRenderCmd(this); 97 else 98 return new cc.Layer.WebGLRenderCmd(this); 99 } 100 }); 101 102 /** 103 * Creates a layer 104 * @deprecated since v3.0, please use the new construction instead 105 * @see cc.Layer 106 * @return {cc.Layer|Null} 107 */ 108 cc.Layer.create = function () { 109 return new cc.Layer(); 110 }; 111 112 /** 113 * <p> 114 * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. <br/> 115 * All features from CCLayer are valid, plus the following new features: <br/> 116 * - opacity <br/> 117 * - RGB colors </p> 118 * @class 119 * @extends cc.Layer 120 * 121 * @param {cc.Color} [color=] The color of the layer 122 * @param {Number} [width=] The width of the layer 123 * @param {Number} [height=] The height of the layer 124 * 125 * @example 126 * // Example 127 * //Create a yellow color layer as background 128 * var yellowBackground = new cc.LayerColor(cc.color(255,255,0,255)); 129 * //If you didn't pass in width and height, it defaults to the same size as the canvas 130 * 131 * //create a yellow box, 200 by 200 in size 132 * var yellowBox = new cc.LayerColor(cc.color(255,255,0,255), 200, 200); 133 */ 134 cc.LayerColor = cc.Layer.extend(/** @lends cc.LayerColor# */{ 135 _blendFunc: null, 136 _className: "LayerColor", 137 138 /** 139 * Returns the blend function 140 * @return {cc.BlendFunc} 141 */ 142 getBlendFunc: function () { 143 return this._blendFunc; 144 }, 145 146 /** 147 * Changes width and height 148 * @deprecated since v3.0 please use setContentSize instead 149 * @see cc.Node#setContentSize 150 * @param {Number} w width 151 * @param {Number} h height 152 */ 153 changeWidthAndHeight: function (w, h) { 154 this.width = w; 155 this.height = h; 156 }, 157 158 /** 159 * Changes width in Points 160 * @deprecated since v3.0 please use setContentSize instead 161 * @see cc.Node#setContentSize 162 * @param {Number} w width 163 */ 164 changeWidth: function (w) { 165 this.width = w; 166 }, 167 168 /** 169 * change height in Points 170 * @deprecated since v3.0 please use setContentSize instead 171 * @see cc.Node#setContentSize 172 * @param {Number} h height 173 */ 174 changeHeight: function (h) { 175 this.height = h; 176 }, 177 178 setOpacityModifyRGB: function (value) { 179 }, 180 181 isOpacityModifyRGB: function () { 182 return false; 183 }, 184 185 /** 186 * Constructor of cc.LayerColor 187 * @function 188 * @param {cc.Color} [color=] 189 * @param {Number} [width=] 190 * @param {Number} [height=] 191 */ 192 ctor: function(color, width, height){ 193 cc.Layer.prototype.ctor.call(this); 194 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 195 cc.LayerColor.prototype.init.call(this, color, width, height); 196 }, 197 198 /** 199 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 200 * @param {cc.Color} [color=] 201 * @param {Number} [width=] 202 * @param {Number} [height=] 203 * @return {Boolean} 204 */ 205 init: function (color, width, height) { 206 if (cc._renderType !== cc._RENDER_TYPE_CANVAS) 207 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR); 208 209 var winSize = cc.director.getWinSize(); 210 color = color || cc.color(0, 0, 0, 255); 211 width = width === undefined ? winSize.width : width; 212 height = height === undefined ? winSize.height : height; 213 214 var locRealColor = this._realColor; 215 locRealColor.r = color.r; 216 locRealColor.g = color.g; 217 locRealColor.b = color.b; 218 this._realOpacity = color.a; 219 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty); 220 221 cc.LayerColor.prototype.setContentSize.call(this, width, height); 222 return true; 223 }, 224 225 /** 226 * Sets the blend func, you can pass either a cc.BlendFunc object or source and destination value separately 227 * @param {Number|cc.BlendFunc} src 228 * @param {Number} [dst] 229 */ 230 setBlendFunc: function (src, dst) { 231 var locBlendFunc = this._blendFunc; 232 if (dst === undefined) { 233 locBlendFunc.src = src.src; 234 locBlendFunc.dst = src.dst; 235 } else { 236 locBlendFunc.src = src; 237 locBlendFunc.dst = dst; 238 } 239 this._renderCmd.updateBlendFunc(locBlendFunc); 240 }, 241 242 _setWidth: function(width){ 243 cc.Node.prototype._setWidth.call(this, width); 244 this._renderCmd._updateSquareVerticesWidth(width); 245 }, 246 247 _setHeight: function(height){ 248 cc.Node.prototype._setHeight.call(this, height); 249 this._renderCmd._updateSquareVerticesHeight(height); 250 }, 251 252 setContentSize: function(size, height){ 253 cc.Layer.prototype.setContentSize.call(this, size, height); 254 this._renderCmd._updateSquareVertices(size, height); 255 }, 256 257 _createRenderCmd: function(){ 258 if (cc._renderType === cc._RENDER_TYPE_CANVAS) 259 return new cc.LayerColor.CanvasRenderCmd(this); 260 else 261 return new cc.LayerColor.WebGLRenderCmd(this); 262 } 263 }); 264 265 /** 266 * Creates a cc.Layer with color, width and height in Points 267 * @deprecated since v3.0 please use the new construction instead 268 * @see cc.LayerColor 269 * @param {cc.Color} color 270 * @param {Number|Null} [width=] 271 * @param {Number|Null} [height=] 272 * @return {cc.LayerColor} 273 */ 274 cc.LayerColor.create = function (color, width, height) { 275 return new cc.LayerColor(color, width, height); 276 }; 277 278 //LayerColor - Getter Setter 279 (function(){ 280 var proto = cc.LayerColor.prototype; 281 cc.defineGetterSetter(proto, "width", proto._getWidth, proto._setWidth); 282 cc.defineGetterSetter(proto, "height", proto._getHeight, proto._setHeight); 283 })(); 284 285 /** 286 * <p> 287 * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/> 288 *<br/> 289 * All features from cc.LayerColor are valid, plus the following new features:<br/> 290 * <ul><li>direction</li> 291 * <li>final color</li> 292 * <li>interpolation mode</li></ul> 293 * <br/> 294 * Color is interpolated between the startColor and endColor along the given<br/> 295 * vector (starting at the origin, ending at the terminus). If no vector is<br/> 296 * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/> 297 * <br/> 298 * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/> 299 * non-cardinal vectors; a smooth gradient implying both end points will be still<br/> 300 * be drawn, however.<br/> 301 *<br/> 302 * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. 303 * </p> 304 * @class 305 * @extends cc.LayerColor 306 * 307 * @param {cc.Color} start Starting color 308 * @param {cc.Color} end Ending color 309 * @param {cc.Point} [v=cc.p(0, -1)] A vector defines the gradient direction, default direction is from top to bottom 310 * 311 * @property {cc.Color} startColor - Start color of the color gradient 312 * @property {cc.Color} endColor - End color of the color gradient 313 * @property {Number} startOpacity - Start opacity of the color gradient 314 * @property {Number} endOpacity - End opacity of the color gradient 315 * @property {Number} vector - Direction vector of the color gradient 316 * @property {Number} compresseInterpolation - Indicate whether or not the interpolation will be compressed 317 */ 318 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ 319 _endColor: null, 320 _startOpacity: 255, 321 _endOpacity: 255, 322 _alongVector: null, 323 _compressedInterpolation: false, 324 _className: "LayerGradient", 325 326 /** 327 * Constructor of cc.LayerGradient 328 * @param {cc.Color} start 329 * @param {cc.Color} end 330 * @param {cc.Point} [v=cc.p(0, -1)] 331 */ 332 ctor: function (start, end, v) { 333 var _t = this; 334 cc.LayerColor.prototype.ctor.call(_t); 335 _t._endColor = cc.color(0, 0, 0, 255); 336 _t._alongVector = cc.p(0, -1); 337 _t._startOpacity = 255; 338 _t._endOpacity = 255; 339 cc.LayerGradient.prototype.init.call(_t, start, end, v); 340 }, 341 342 /** 343 * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer 344 * @param {cc.Color} start starting color 345 * @param {cc.Color} end 346 * @param {cc.Point|Null} v 347 * @return {Boolean} 348 */ 349 init: function (start, end, v) { 350 start = start || cc.color(0, 0, 0, 255); 351 end = end || cc.color(0, 0, 0, 255); 352 v = v || cc.p(0, -1); 353 var _t = this; 354 355 // Initializes the CCLayer with a gradient between start and end in the direction of v. 356 var locEndColor = _t._endColor; 357 _t._startOpacity = start.a; 358 359 locEndColor.r = end.r; 360 locEndColor.g = end.g; 361 locEndColor.b = end.b; 362 _t._endOpacity = end.a; 363 364 _t._alongVector = v; 365 _t._compressedInterpolation = true; 366 367 cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255)); 368 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty); 369 return true; 370 }, 371 372 /** 373 * Sets the untransformed size of the LayerGradient. 374 * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient. 375 * @param {Number} [height] The untransformed size's height of the LayerGradient. 376 */ 377 setContentSize: function (size, height) { 378 cc.LayerColor.prototype.setContentSize.call(this, size, height); 379 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty); 380 }, 381 382 _setWidth: function (width) { 383 cc.LayerColor.prototype._setWidth.call(this, width); 384 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty); 385 }, 386 _setHeight: function (height) { 387 cc.LayerColor.prototype._setHeight.call(this, height); 388 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty); 389 }, 390 391 /** 392 * Returns the starting color 393 * @return {cc.Color} 394 */ 395 getStartColor: function () { 396 return this._realColor; 397 }, 398 399 /** 400 * Sets the starting color 401 * @param {cc.Color} color 402 * @example 403 * // Example 404 * myGradientLayer.setStartColor(cc.color(255,0,0)); 405 * //set the starting gradient to red 406 */ 407 setStartColor: function (color) { 408 this.color = color; 409 }, 410 411 /** 412 * Sets the end gradient color 413 * @param {cc.Color} color 414 * @example 415 * // Example 416 * myGradientLayer.setEndColor(cc.color(255,0,0)); 417 * //set the ending gradient to red 418 */ 419 setEndColor: function (color) { 420 this._endColor = color; 421 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty); 422 }, 423 424 /** 425 * Returns the end color 426 * @return {cc.Color} 427 */ 428 getEndColor: function () { 429 return this._endColor; 430 }, 431 432 /** 433 * Sets starting gradient opacity 434 * @param {Number} o from 0 to 255, 0 is transparent 435 */ 436 setStartOpacity: function (o) { 437 this._startOpacity = o; 438 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty); 439 }, 440 441 /** 442 * Returns the starting gradient opacity 443 * @return {Number} 444 */ 445 getStartOpacity: function () { 446 return this._startOpacity; 447 }, 448 449 /** 450 * Sets the end gradient opacity 451 * @param {Number} o 452 */ 453 setEndOpacity: function (o) { 454 this._endOpacity = o; 455 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty); 456 }, 457 458 /** 459 * Returns the end gradient opacity 460 * @return {Number} 461 */ 462 getEndOpacity: function () { 463 return this._endOpacity; 464 }, 465 466 /** 467 * Sets the direction vector of the gradient 468 * @param {cc.Point} Var 469 */ 470 setVector: function (Var) { 471 this._alongVector.x = Var.x; 472 this._alongVector.y = Var.y; 473 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty); 474 }, 475 476 /** 477 * Returns the direction vector of the gradient 478 * @return {cc.Point} 479 */ 480 getVector: function () { 481 return cc.p(this._alongVector.x, this._alongVector.y); 482 }, 483 484 /** 485 * Returns whether compressed interpolation is enabled 486 * @return {Boolean} 487 */ 488 isCompressedInterpolation: function () { 489 return this._compressedInterpolation; 490 }, 491 492 /** 493 * Sets whether compressed interpolation is enabled 494 * @param {Boolean} compress 495 */ 496 setCompressedInterpolation: function (compress) { 497 this._compressedInterpolation = compress; 498 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty); 499 }, 500 501 _createRenderCmd: function(){ 502 if (cc._renderType === cc._RENDER_TYPE_CANVAS) 503 return new cc.LayerGradient.CanvasRenderCmd(this); 504 else 505 return new cc.LayerGradient.WebGLRenderCmd(this); 506 } 507 }); 508 509 /** 510 * Creates a gradient layer 511 * @deprecated since v3.0, please use the new construction instead 512 * @see cc.layerGradient 513 * @param {cc.Color} start starting color 514 * @param {cc.Color} end ending color 515 * @param {cc.Point|Null} v 516 * @return {cc.LayerGradient} 517 */ 518 cc.LayerGradient.create = function (start, end, v) { 519 return new cc.LayerGradient(start, end, v); 520 }; 521 //LayerGradient - Getter Setter 522 (function(){ 523 var proto = cc.LayerGradient.prototype; 524 // Extended properties 525 /** @expose */ 526 proto.startColor; 527 cc.defineGetterSetter(proto, "startColor", proto.getStartColor, proto.setStartColor); 528 /** @expose */ 529 proto.endColor; 530 cc.defineGetterSetter(proto, "endColor", proto.getEndColor, proto.setEndColor); 531 /** @expose */ 532 proto.startOpacity; 533 cc.defineGetterSetter(proto, "startOpacity", proto.getStartOpacity, proto.setStartOpacity); 534 /** @expose */ 535 proto.endOpacity; 536 cc.defineGetterSetter(proto, "endOpacity", proto.getEndOpacity, proto.setEndOpacity); 537 /** @expose */ 538 proto.vector; 539 cc.defineGetterSetter(proto, "vector", proto.getVector, proto.setVector); 540 })(); 541 542 /** 543 * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/> 544 * Features:<br/> 545 * <ul><li>- It supports one or more children</li> 546 * <li>- Only one children will be active a time</li></ul> 547 * @class 548 * @extends cc.Layer 549 * @param {Array} layers an array of cc.Layer 550 * @example 551 * // Example 552 * var multiLayer = new cc.LayerMultiple(layer1, layer2, layer3);//any number of layers 553 */ 554 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{ 555 _enabledLayer: 0, 556 _layers: null, 557 _className: "LayerMultiplex", 558 559 /** 560 * Constructor of cc.LayerMultiplex 561 * @param {Array} layers an array of cc.Layer 562 */ 563 ctor: function (layers) { 564 cc.Layer.prototype.ctor.call(this); 565 if (layers instanceof Array) 566 cc.LayerMultiplex.prototype.initWithLayers.call(this, layers); 567 else 568 cc.LayerMultiplex.prototype.initWithLayers.call(this, Array.prototype.slice.call(arguments)); 569 }, 570 571 /** 572 * 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 573 * @param {Array} layers an array of cc.Layer 574 * @return {Boolean} 575 */ 576 initWithLayers: function (layers) { 577 if ((layers.length > 0) && (layers[layers.length - 1] == null)) 578 cc.log(cc._LogInfos.LayerMultiplex_initWithLayers); 579 580 this._layers = layers; 581 this._enabledLayer = 0; 582 this.addChild(this._layers[this._enabledLayer]); 583 return true; 584 }, 585 586 /** 587 * Switches to a certain layer indexed by n.<br/> 588 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 589 * @param {Number} n the layer index to switch to 590 */ 591 switchTo: function (n) { 592 if (n >= this._layers.length) { 593 cc.log(cc._LogInfos.LayerMultiplex_switchTo); 594 return; 595 } 596 597 this.removeChild(this._layers[this._enabledLayer], true); 598 this._enabledLayer = n; 599 this.addChild(this._layers[n]); 600 }, 601 602 /** 603 * Release the current layer and switches to another layer indexed by n.<br/> 604 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 605 * @param {Number} n the layer index to switch to 606 */ 607 switchToAndReleaseMe: function (n) { 608 if (n >= this._layers.length) { 609 cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe); 610 return; 611 } 612 613 this.removeChild(this._layers[this._enabledLayer], true); 614 615 //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]]; 616 this._layers[this._enabledLayer] = null; 617 this._enabledLayer = n; 618 this.addChild(this._layers[n]); 619 }, 620 621 /** 622 * Add a layer to the multiplex layers list 623 * @param {cc.Layer} layer 624 */ 625 addLayer: function (layer) { 626 if (!layer) { 627 cc.log(cc._LogInfos.LayerMultiplex_addLayer); 628 return; 629 } 630 this._layers.push(layer); 631 } 632 }); 633 634 /** 635 * Creates a cc.LayerMultiplex with one or more layers using a variable argument list. 636 * @deprecated since v3.0, please use new construction instead 637 * @see cc.LayerMultiplex 638 * @return {cc.LayerMultiplex|Null} 639 */ 640 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) { 641 return new cc.LayerMultiplex(Array.prototype.slice.call(arguments)); 642 };