1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga 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 /** Layer will receive all the touches at once The onTouchesXXX API will be called 28 */ 29 cc.TOUCH_ALL_AT_ONCE = 0; 30 31 /** Layer will receive only one touch at the time. The onTouchXXX API will be called */ 32 cc.TOUCH_ONE_BY_ONE = 1; 33 34 /** cc.Layer is a subclass of cc.Node that implements the TouchEventsDelegate protocol.<br/> 35 * All features from cc.Node are valid, plus the following new features:<br/> 36 * It can receive iPhone Touches<br/> 37 * It can receive Accelerometer input 38 * @class 39 * @extends cc.Node 40 */ 41 cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ 42 _isTouchEnabled:false, 43 _isAccelerometerEnabled:false, 44 _isKeyboardEnabled:false, 45 _touchPriority:0, 46 _touchMode:cc.TOUCH_ALL_AT_ONCE, 47 _isMouseEnabled:false, 48 _mousePriority:0, 49 50 ctor: function () { 51 cc.Node.prototype.ctor.call(this); 52 this._isTouchEnabled = false; 53 this._isAccelerometerEnabled = false; 54 this._isKeyboardEnabled = false; 55 this._touchPriority = 0; 56 this._touchMode = cc.TOUCH_ALL_AT_ONCE; 57 this._isMouseEnabled = false; 58 this._mousePriority = 0; 59 }, 60 61 _initLayer:function () { 62 this.setAnchorPoint(cc.p(0.5, 0.5)); 63 this._ignoreAnchorPointForPosition = true; 64 65 var director = cc.Director.getInstance(); 66 this.setContentSize(director.getWinSize()); 67 }, 68 69 /** 70 * 71 * @return {Boolean} 72 */ 73 init:function () { 74 cc.Node.prototype.init.call(this); 75 this._initLayer(); 76 return true; 77 }, 78 79 /** 80 * If isTouchEnabled, this method is called onEnter. 81 */ 82 registerWithTouchDispatcher:function () { 83 if (this._touchMode === cc.TOUCH_ALL_AT_ONCE) 84 cc.registerStandardDelegate(this,this._touchPriority); 85 else 86 cc.registerTargetedDelegate(this._touchPriority, true, this); 87 }, 88 89 isMouseEnabled:function () { 90 return this._isMouseEnabled; 91 }, 92 93 setMouseEnabled:function (enabled) { 94 if(!cc.MouseDispatcher) 95 throw "cc.MouseDispatcher is undefined, maybe it has been removed from js loading list."; 96 97 if (this._isMouseEnabled != enabled) { 98 this._isMouseEnabled = enabled; 99 if (this._running) { 100 if (enabled) 101 cc.Director.getInstance().getMouseDispatcher().addMouseDelegate(this, this._mousePriority); 102 else 103 cc.Director.getInstance().getMouseDispatcher().removeMouseDelegate(this); 104 } 105 } 106 }, 107 108 setMousePriority:function (priority) { 109 if(!cc.MouseDispatcher) 110 throw "cc.MouseDispatcher is undefined, maybe it has been removed from js loading list."; 111 112 if (this._mousePriority !== priority) { 113 this._mousePriority = priority; 114 // Update touch priority with handler 115 if (this._isMouseEnabled) { 116 this.setMouseEnabled(false); 117 this.setMouseEnabled(true); 118 } 119 } 120 }, 121 122 getMousePriority:function () { 123 return this._mousePriority; 124 }, 125 126 /** 127 * whether or not it will receive Touch events.<br/> 128 * You can enable / disable touch events with this property.<br/> 129 * Only the touches of this node will be affected. This "method" is not propagated to it's children.<br/> 130 * @return {Boolean} 131 */ 132 isTouchEnabled:function () { 133 return this._isTouchEnabled; 134 }, 135 136 /** 137 * Enable touch events 138 * @param {Boolean} enabled 139 */ 140 setTouchEnabled:function (enabled) { 141 if (this._isTouchEnabled !== enabled) { 142 this._isTouchEnabled = enabled; 143 144 if (this._running) { 145 if (enabled) { 146 this.registerWithTouchDispatcher(); 147 } else { 148 // have problems? 149 cc.unregisterTouchDelegate(this); 150 } 151 } 152 } 153 }, 154 155 /** returns the priority of the touch event handler 156 * @return {Number} 157 */ 158 getTouchPriority:function () { 159 return this._touchPriority; 160 }, 161 162 /** Sets the touch event handler priority. Default is 0. 163 * @param {Number} priority 164 */ 165 setTouchPriority:function (priority) { 166 if (this._touchPriority !== priority) { 167 this._touchPriority = priority; 168 // Update touch priority with handler 169 if (this._isTouchEnabled) { 170 this.setTouchEnabled(false); 171 this.setTouchEnabled(true); 172 } 173 } 174 }, 175 176 /** returns the touch mode. 177 * @return {Number} 178 */ 179 getTouchMode:function () { 180 return this._touchMode; 181 }, 182 183 /** Sets the touch mode. 184 * @param {Number} mode 185 */ 186 setTouchMode:function (mode) { 187 if (this._touchMode !== mode) { 188 this._touchMode = mode; 189 // update the mode with handler 190 if (this._isTouchEnabled) { 191 this.setTouchEnabled(false); 192 this.setTouchEnabled(true); 193 } 194 } 195 }, 196 197 /** 198 * whether or not it will receive Accelerometer events<br/> 199 * You can enable / disable accelerometer events with this property. 200 * @return {Boolean} 201 */ 202 isAccelerometerEnabled:function () { 203 return this._isAccelerometerEnabled; 204 }, 205 206 /** 207 * isAccelerometerEnabled setter 208 * @param {Boolean} enabled 209 */ 210 setAccelerometerEnabled:function (enabled) { 211 if(!cc.Accelerometer) 212 throw "cc.Accelerometer is undefined, maybe it has been removed from js loading list."; 213 if (enabled !== this._isAccelerometerEnabled) { 214 this._isAccelerometerEnabled = enabled; 215 if (this._running) { 216 var director = cc.Director.getInstance(); 217 if (enabled) 218 director.getAccelerometer().setDelegate(this); 219 else 220 director.getAccelerometer().setDelegate(null); 221 } 222 } 223 }, 224 225 /** 226 * accelerometerInterval setter 227 * @param {Number} interval 228 */ 229 setAccelerometerInterval:function (interval) { 230 if (this._isAccelerometerEnabled && cc.Accelerometer) 231 cc.Director.getInstance().getAccelerometer().setAccelerometerInterval(interval); 232 }, 233 234 onAccelerometer:function (accelerationValue) { 235 cc.log("onAccelerometer event should be handled.") 236 }, 237 238 /** 239 * whether or not it will receive keyboard events<br/> 240 * You can enable / disable accelerometer events with this property.<br/> 241 * it's new in cocos2d-x 242 * @return {Boolean} 243 */ 244 isKeyboardEnabled:function () { 245 return this._isKeyboardEnabled; 246 }, 247 248 /** 249 * Enable Keyboard interaction 250 * @param {Boolean} enabled 251 */ 252 setKeyboardEnabled:function (enabled) { 253 if(!cc.KeyboardDispatcher) 254 throw "cc.KeyboardDispatcher is undefined, maybe it has been removed from js loading list."; 255 256 if (enabled !== this._isKeyboardEnabled) { 257 this._isKeyboardEnabled = enabled; 258 if (this._running) { 259 var director = cc.Director.getInstance(); 260 if (enabled) { 261 director.getKeyboardDispatcher().addDelegate(this); 262 } else { 263 director.getKeyboardDispatcher().removeDelegate(this); 264 } 265 } 266 } 267 }, 268 269 /** 270 * This is run when ever a layer just become visible 271 */ 272 onEnter:function () { 273 var director = cc.Director.getInstance(); 274 // register 'parent' nodes first 275 // since events are propagated in reverse order 276 if (this._isTouchEnabled) 277 this.registerWithTouchDispatcher(); 278 279 // then iterate over all the children 280 cc.Node.prototype.onEnter.call(this); 281 282 // add this layer to concern the Accelerometer Sensor 283 if (this._isAccelerometerEnabled && cc.Accelerometer) 284 director.getAccelerometer().setDelegate(this); 285 286 // add this layer to concern the kaypad msg 287 if (this._isKeyboardEnabled && cc.KeyboardDispatcher) 288 director.getKeyboardDispatcher().addDelegate(this); 289 290 if (this._isMouseEnabled && cc.MouseDispatcher) 291 director.getMouseDispatcher().addMouseDelegate(this, this._mousePriority); 292 }, 293 294 /** 295 * @function 296 */ 297 onExit:function () { 298 var director = cc.Director.getInstance(); 299 if (this._isTouchEnabled) 300 cc.unregisterTouchDelegate(this); 301 302 // remove this layer from the delegates who concern Accelerometer Sensor 303 if (this._isAccelerometerEnabled && cc.Accelerometer) 304 director.getAccelerometer().setDelegate(null); 305 306 // remove this layer from the delegates who concern the kaypad msg 307 if (this._isKeyboardEnabled && cc.KeyboardDispatcher) 308 director.getKeyboardDispatcher().removeDelegate(this); 309 310 if (this._isMouseEnabled && cc.MouseDispatcher) 311 director.getMouseDispatcher().removeMouseDelegate(this); 312 313 cc.Node.prototype.onExit.call(this); 314 }, 315 316 /** 317 * this is called when ever a layer is a child of a scene that just finished a transition 318 */ 319 onEnterTransitionDidFinish:function () { 320 if (this._isAccelerometerEnabled && cc.Accelerometer) 321 cc.Director.getInstance().getAccelerometer().setDelegate(this); 322 cc.Node.prototype.onEnterTransitionDidFinish.call(this); 323 }, 324 325 // ---------------------CCTouchDelegate interface------------------------------ 326 327 /** 328 * default implements are used to call script callback if exist<br/> 329 * you must override these touch functions if you wish to utilize them 330 * @param {cc.Touch} touch 331 * @param {event} event 332 * @return {Boolean} 333 */ 334 onTouchBegan:function (touch, event) { 335 cc.log("onTouchBegan event should be handled."); 336 return true; 337 }, 338 339 /** 340 * callback when a touch event moved 341 * @param {cc.Touch} touch 342 * @param {event} event 343 */ 344 onTouchMoved:function (touch, event) { 345 }, 346 347 /** 348 * callback when a touch event finished 349 * @param {cc.Touch} touch 350 * @param {event} event 351 */ 352 onTouchEnded:function (touch, event) { 353 }, 354 355 /** 356 * @param {cc.Touch} touch 357 * @param {event} event 358 */ 359 onTouchCancelled:function (touch, event) { 360 }, 361 362 /** 363 * Touches is the same as Touch, except this one can handle multi-touch 364 * @param {cc.Touch} touch 365 * @param {event} event 366 */ 367 onTouchesBegan:function (touch, event) { 368 }, 369 370 /** 371 * when a touch moved 372 * @param {cc.Touch} touch 373 * @param {event} event 374 */ 375 onTouchesMoved:function (touch, event) { 376 }, 377 378 /** 379 * when a touch finished 380 * @param {cc.Touch} touch 381 * @param {event} event 382 */ 383 onTouchesEnded:function (touch, event) { 384 }, 385 386 /** 387 * @param touch 388 * @param event 389 */ 390 onTouchesCancelled:function (touch, event) { 391 }, 392 393 // ---------------------CCMouseEventDelegate interface------------------------------ 394 395 /** 396 * <p>called when the "mouseDown" event is received. <br/> 397 * Return YES to avoid propagating the event to other delegates. </p> 398 * @param event 399 * @return {Boolean} 400 */ 401 onMouseDown:function (event) { 402 return false; 403 }, 404 405 /** 406 * <p>called when the "mouseDragged" event is received. <br/> 407 * Return YES to avoid propagating the event to other delegates.</p> 408 * @param event 409 * @return {Boolean} 410 */ 411 onMouseDragged:function (event) { 412 return false; 413 }, 414 415 /** 416 * <p> called when the "mouseMoved" event is received. <br/> 417 * Return YES to avoid propagating the event to other delegates. </p> 418 * @param event 419 * @return {Boolean} 420 */ 421 onMouseMoved:function (event) { 422 return false; 423 }, 424 425 /** 426 * <p> called when the "mouseUp" event is received. <br/> 427 * Return YES to avoid propagating the event to other delegates. </p> 428 * @param event 429 * @return {Boolean} 430 */ 431 onMouseUp:function (event) { 432 return false; 433 }, 434 435 //right 436 /** 437 * <p> called when the "rightMouseDown" event is received. <br/> 438 * Return YES to avoid propagating the event to other delegates. </p> 439 * @param event 440 * @return {Boolean} 441 */ 442 onRightMouseDown:function (event) { 443 return false; 444 }, 445 446 /** 447 * <p> called when the "rightMouseDragged" event is received. <br/> 448 * Return YES to avoid propagating the event to other delegates. </p> 449 * @param event 450 * @return {Boolean} 451 */ 452 onRightMouseDragged:function (event) { 453 return false; 454 }, 455 456 /** 457 * <p> called when the "rightMouseUp" event is received. <br/> 458 * Return YES to avoid propagating the event to other delegates. </p> 459 * @param event 460 * @return {Boolean} 461 */ 462 onRightMouseUp:function (event) { 463 return false; 464 }, 465 466 //other 467 /** 468 * <p>called when the "otherMouseDown" event is received. <br/> 469 * Return YES to avoid propagating the event to other delegates. </p> 470 * @param event 471 * @return {Boolean} 472 */ 473 onOtherMouseDown:function (event) { 474 return false; 475 }, 476 477 /** 478 * <p> called when the "otherMouseDragged" event is received. <br/> 479 * Return YES to avoid propagating the event to other delegates. </p> 480 * @param event 481 * @return {Boolean} 482 */ 483 onOtherMouseDragged:function (event) { 484 return false; 485 }, 486 487 /** 488 * <p> called when the "otherMouseUp" event is received. <br/> 489 * Return YES to avoid propagating the event to other delegates. </p> 490 * @param event 491 * @return {Boolean} 492 */ 493 onOtherMouseUp:function (event) { 494 return false; 495 }, 496 497 //scroll wheel 498 /** 499 * <p> called when the "scrollWheel" event is received. <br/> 500 * Return YES to avoid propagating the event to other delegates. </p> 501 * @param event 502 * @return {Boolean} 503 */ 504 onScrollWheel:function (event) { 505 return false; 506 }, 507 508 // enter / exit 509 /** 510 * <p> called when the "mouseEntered" event is received. <br/> 511 * Return YES to avoid propagating the event to other delegates. </p> 512 * @param theEvent 513 * @return {Boolean} 514 */ 515 onMouseEntered:function (theEvent) { 516 return false; 517 }, 518 519 /** 520 * <p> called when the "mouseExited" event is received. <br/> 521 * Return YES to avoid propagating the event to other delegates. </p> 522 * @param theEvent 523 * @return {Boolean} 524 */ 525 onMouseExited:function (theEvent) { 526 return false; 527 }, 528 529 // ---------------------CCKeyboardDelegate interface------------------------------ 530 531 /** 532 * Call back when a key is pressed down 533 * @param {Number} keyCode 534 * @example 535 * // example 536 * if(keyCode == cc.KEY.w){} 537 */ 538 onKeyDown:function (keyCode) { 539 }, 540 541 /** 542 * Call back when a key is released 543 * @param {Number} keyCode 544 * @example 545 * // example 546 * if(keyCode == cc.KEY.w){} 547 */ 548 onKeyUp:function (keyCode) { 549 } 550 }); 551 552 /** 553 * creates a layer 554 * @example 555 * // Example 556 * var myLayer = cc.Layer.create(); 557 * //Yes! it's that simple 558 * @return {cc.Layer|Null} 559 */ 560 cc.Layer.create = function () { 561 var ret = new cc.Layer(); 562 if (ret && ret.init()) 563 return ret; 564 return null; 565 }; 566 567 /** 568 * <p> 569 * CCLayerRGBA is a subclass of CCLayer that implements the CCRGBAProtocol protocol using a solid color as the background. <br/> 570 * All features from CCLayer are valid, plus the following new features that propagate into children that conform to the CCRGBAProtocol: <br/> 571 * - opacity <br/> 572 * - RGB colors 573 * </p> 574 * @class 575 * @extends cc.Layer 576 */ 577 cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{ 578 RGBAProtocol:true, 579 _displayedOpacity: 0, 580 _realOpacity: 0, 581 _displayedColor: null, 582 _realColor: null, 583 _cascadeOpacityEnabled: false, 584 _cascadeColorEnabled: false, 585 586 ctor: function () { 587 cc.Layer.prototype.ctor.call(this); 588 this.RGBAProtocol = true; 589 this._displayedOpacity = 255; 590 this._realOpacity = 255; 591 this._displayedColor = cc.white(); 592 this._realColor = cc.white(); 593 this._cascadeOpacityEnabled = false; 594 this._cascadeColorEnabled = false; 595 }, 596 597 init: function () { 598 if(cc.Layer.prototype.init.call(this)){ 599 this.setCascadeOpacityEnabled(false); 600 this.setCascadeColorEnabled(false); 601 return true; 602 } 603 return false; 604 }, 605 606 /** 607 * 608 * @returns {number} 609 */ 610 getOpacity: function () { 611 return this._realOpacity; 612 }, 613 614 /** 615 * 616 * @returns {number} 617 */ 618 getDisplayedOpacity: function () { 619 return this._displayedOpacity; 620 }, 621 622 /** 623 * Override synthesized setOpacity to recurse items 624 * @param {Number} opacity 625 */ 626 setOpacity: function (opacity) { 627 this._displayedOpacity = this._realOpacity = opacity; 628 629 var parentOpacity = 255, locParent = this._parent; 630 if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled()) 631 parentOpacity = locParent.getDisplayedOpacity(); 632 this.updateDisplayedOpacity(parentOpacity); 633 }, 634 635 /** 636 * 637 * @param {Number} parentOpacity 638 */ 639 updateDisplayedOpacity: function (parentOpacity) { 640 this._displayedOpacity = 0 | (this._realOpacity * parentOpacity / 255.0); 641 642 if (this._cascadeOpacityEnabled) { 643 var locChildren = this._children; 644 for (var i = 0; i < locChildren.length; i++) { 645 var selItem = locChildren[i]; 646 if (selItem && selItem.RGBAProtocol) 647 selItem.updateDisplayedOpacity(this._displayedOpacity); 648 } 649 } 650 }, 651 652 isCascadeOpacityEnabled: function () { 653 return this._cascadeOpacityEnabled; 654 }, 655 656 setCascadeOpacityEnabled: function (cascadeOpacityEnabled) { 657 if(this._cascadeOpacityEnabled === cascadeOpacityEnabled) 658 return; 659 660 this._cascadeOpacityEnabled = cascadeOpacityEnabled; 661 if(cascadeOpacityEnabled) 662 this._enableCascadeOpacity(); 663 else 664 this._disableCascadeOpacity(); 665 }, 666 667 _enableCascadeOpacity:function(){ 668 var parentOpacity = 255, locParent = this._parent; 669 if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled()) 670 parentOpacity = locParent.getDisplayedOpacity(); 671 this.updateDisplayedOpacity(parentOpacity); 672 }, 673 674 _disableCascadeOpacity:function(){ 675 this._displayedOpacity = this._realOpacity; 676 var selChildren = this._children; 677 for(var i = 0; i< selChildren.length;i++){ 678 var item = selChildren[i]; 679 if(item && item.RGBAProtocol && item._disableCascadeOpacity) 680 item._disableCascadeOpacity(); 681 } 682 }, 683 684 getColor: function () { 685 var locRealColor = this._realColor; 686 return cc.c3b(locRealColor.r, locRealColor.g, locRealColor.b); 687 }, 688 689 getDisplayedColor: function () { 690 var locDisplayedColor = this._displayedColor; 691 return cc.c3b(locDisplayedColor.r, locDisplayedColor.g, locDisplayedColor.b); 692 }, 693 694 setColor: function (color) { 695 var locDisplayed = this._displayedColor, locRealColor = this._realColor; 696 locDisplayed.r = locRealColor.r = color.r; 697 locDisplayed.g = locRealColor.g = color.g; 698 locDisplayed.b = locRealColor.b = color.b; 699 700 var parentColor, locParent = this._parent; 701 if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) 702 parentColor = locParent.getDisplayedColor(); 703 else 704 parentColor = cc.white(); 705 this.updateDisplayedColor(parentColor); 706 }, 707 708 updateDisplayedColor: function (parentColor) { 709 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 710 locDisplayedColor.r = 0 | (locRealColor.r * parentColor.r / 255.0); 711 locDisplayedColor.g = 0 | (locRealColor.g * parentColor.g / 255.0); 712 locDisplayedColor.b = 0 | (locRealColor.b * parentColor.b / 255.0); 713 714 if (this._cascadeColorEnabled) { 715 var locChildren = this._children; 716 for (var i = 0; i < locChildren.length; i++) { 717 var selItem = locChildren[i]; 718 if (selItem && selItem.RGBAProtocol) 719 selItem.updateDisplayedColor(locDisplayedColor); 720 } 721 } 722 }, 723 724 isCascadeColorEnabled: function () { 725 return this._cascadeColorEnabled; 726 }, 727 728 setCascadeColorEnabled: function (cascadeColorEnabled) { 729 if(this._cascadeColorEnabled === cascadeColorEnabled) 730 return; 731 this._cascadeColorEnabled = cascadeColorEnabled; 732 if(this._cascadeColorEnabled) 733 this._enableCascadeColor(); 734 else 735 this._disableCascadeColor(); 736 }, 737 738 _enableCascadeColor: function(){ 739 var parentColor , locParent = this._parent; 740 if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) 741 parentColor = locParent.getDisplayedColor(); 742 else 743 parentColor = cc.white(); 744 this.updateDisplayedColor(parentColor); 745 }, 746 747 _disableCascadeColor: function(){ 748 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 749 locDisplayedColor.r = locRealColor.r; 750 locDisplayedColor.g = locRealColor.g; 751 locDisplayedColor.b = locRealColor.b; 752 753 var selChildren = this._children; 754 for(var i = 0; i< selChildren.length;i++){ 755 var item = selChildren[i]; 756 if(item && item.RGBAProtocol && item._disableCascadeColor) 757 item._disableCascadeColor(); 758 } 759 }, 760 761 addChild:function(child, zOrder, tag){ 762 cc.Node.prototype.addChild.call(this, child, zOrder, tag); 763 764 if(this._cascadeColorEnabled) 765 this._enableCascadeColor(); 766 if(this._cascadeOpacityEnabled) 767 this._enableCascadeOpacity(); 768 }, 769 770 setOpacityModifyRGB: function (bValue) { 771 }, 772 773 isOpacityModifyRGB: function () { 774 return false; 775 } 776 }); 777 778 /** 779 * <p> 780 * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. <br/> 781 * All features from CCLayer are valid, plus the following new features: <br/> 782 * <ul><li>opacity</li> <br/> 783 * <li>RGB colors</li></ul> <br/> 784 * </p> 785 * @class 786 * @extends cc.Layer 787 */ 788 cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{ 789 _blendFunc:null, 790 791 /** 792 * blendFunc getter 793 * @return {cc.BlendFunc} 794 */ 795 getBlendFunc:function () { 796 return this._blendFunc; 797 }, 798 799 /** 800 * change width and height in Points 801 * @param {Number} w width 802 * @param {Number} h height 803 */ 804 changeWidthAndHeight:function (w, h) { 805 this.setContentSize(cc.size(w, h)); 806 }, 807 808 /** 809 * change width in Points 810 * @param {Number} w width 811 */ 812 changeWidth:function (w) { 813 this.setContentSize(cc.size(w, this._contentSize.height)); 814 }, 815 816 /** 817 * change height in Points 818 * @param {Number} h height 819 */ 820 changeHeight:function (h) { 821 this.setContentSize(cc.size(this._contentSize.width, h)); 822 }, 823 824 /** 825 * set OpacityModifyRGB of cc.LayerColor 826 * @param {Boolean} value 827 */ 828 setOpacityModifyRGB:function (value) { 829 }, 830 831 /** 832 * is OpacityModifyRGB 833 * @return {Boolean} 834 */ 835 isOpacityModifyRGB:function () { 836 return false; 837 }, 838 839 setColor:function(color){ 840 cc.LayerRGBA.prototype.setColor.call(this, color); 841 this._updateColor(); 842 }, 843 844 setOpacity:function(opacity){ 845 cc.LayerRGBA.prototype.setOpacity.call(this, opacity); 846 this._updateColor(); 847 }, 848 849 _isLighterMode:false, 850 _squareVertices:null, 851 _squareColors:null, 852 _verticesFloat32Buffer:null, 853 _colorsUint8Buffer:null, 854 _squareVerticesAB:null, 855 _squareColorsAB:null, 856 857 _ctorForCanvas: function () { 858 cc.LayerRGBA.prototype.ctor.call(this); 859 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 860 }, 861 862 _ctorForWebGL: function () { 863 cc.LayerRGBA.prototype.ctor.call(this); 864 this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); 865 866 this._squareVerticesAB = new ArrayBuffer(32); 867 this._squareColorsAB = new ArrayBuffer(64); 868 869 var locSquareVerticesAB = this._squareVerticesAB, locSquareColorsAB = this._squareColorsAB; 870 var locVertex2FLen = cc.Vertex2F.BYTES_PER_ELEMENT, locColor4FLen = cc.Color4F.BYTES_PER_ELEMENT; 871 this._squareVertices = [new cc.Vertex2F(0, 0, locSquareVerticesAB, 0), 872 new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen), 873 new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 2), 874 new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 3)]; 875 this._squareColors = [new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, 0), 876 new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen), 877 new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 2), 878 new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 3)]; 879 this._verticesFloat32Buffer = cc.renderContext.createBuffer(); 880 this._colorsUint8Buffer = cc.renderContext.createBuffer(); 881 }, 882 883 /** 884 * blendFunc setter 885 * @param {Number} src 886 * @param {Number} dst 887 */ 888 setBlendFunc:function (src, dst) { 889 if (arguments.length == 1) 890 this._blendFunc = src; 891 else 892 this._blendFunc = {src:src, dst:dst}; 893 if(cc.renderContextType === cc.CANVAS) 894 this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771)); 895 }, 896 897 /** 898 * @param {cc.Color4B} [color=] 899 * @param {Number} [width=] 900 * @param {Number} [height=] 901 * @return {Boolean} 902 */ 903 init:function (color, width, height) { 904 if(!cc.Layer.prototype.init.call(this)) 905 return false; 906 907 if(cc.renderContextType !== cc.CANVAS) 908 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); 909 910 var winSize = cc.Director.getInstance().getWinSize(); 911 color = color || new cc.Color4B(0, 0, 0, 255); 912 width = width || winSize.width; 913 height = height || winSize.height; 914 915 var locDisplayedColor = this._displayedColor; 916 locDisplayedColor.r = color.r; 917 locDisplayedColor.g = color.g; 918 locDisplayedColor.b = color.b; 919 920 var locRealColor = this._realColor; 921 locRealColor.r = color.r; 922 locRealColor.g = color.g; 923 locRealColor.b = color.b; 924 925 this._displayedOpacity = color.a; 926 this._realOpacity = color.a; 927 928 this.setContentSize(cc.size(width, height)); 929 this._updateColor(); 930 return true; 931 }, 932 933 /** 934 * override contentSize 935 * @param {cc.Size} size 936 */ 937 setContentSize:null, 938 939 _setContentSizeForWebGL:function (size) { 940 var locSquareVertices = this._squareVertices; 941 locSquareVertices[1].x = size.width; 942 locSquareVertices[2].y = size.height; 943 locSquareVertices[3].x = size.width; 944 locSquareVertices[3].y = size.height; 945 this._bindLayerVerticesBufferData(); 946 cc.Layer.prototype.setContentSize.call(this,size); 947 }, 948 949 _updateColor:null, 950 951 _updateColorForCanvas:function () { 952 }, 953 954 _updateColorForWebGL:function () { 955 var locDisplayedColor = this._displayedColor; 956 var locDisplayedOpacity = this._displayedOpacity, locSquareColors = this._squareColors; 957 for (var i = 0; i < 4; i++) { 958 locSquareColors[i].r = locDisplayedColor.r / 255; 959 locSquareColors[i].g = locDisplayedColor.g / 255; 960 locSquareColors[i].b = locDisplayedColor.b / 255; 961 locSquareColors[i].a = locDisplayedOpacity / 255; 962 } 963 this._bindLayerColorsBufferData(); 964 }, 965 966 updateDisplayedColor:function(parentColor){ 967 cc.LayerRGBA.prototype.updateDisplayedColor.call(this, parentColor); 968 this._updateColor(); 969 }, 970 971 updateDisplayedOpacity: function(parentOpacity){ 972 cc.LayerRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 973 this._updateColor(); 974 }, 975 976 _bindLayerVerticesBufferData:function () { 977 var glContext = cc.renderContext; 978 glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer); 979 glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW); 980 }, 981 982 _bindLayerColorsBufferData:function () { 983 var glContext = cc.renderContext; 984 glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer); 985 glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW); 986 }, 987 988 /** 989 * renders the layer 990 * @param {CanvasRenderingContext2D|Null} ctx 991 */ 992 draw:null, 993 994 _drawForCanvas:function (ctx) { 995 var context = ctx || cc.renderContext; 996 997 var locContentSize = this.getContentSize(), locEGLViewer = cc.EGLView.getInstance(); 998 999 var locDisplayedColor = this._displayedColor; 1000 1001 context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + "," 1002 + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")"; 1003 context.fillRect(0, 0, locContentSize.width * locEGLViewer.getScaleX(), -locContentSize.height * locEGLViewer.getScaleY()); 1004 1005 cc.g_NumberOfDraws++; 1006 }, 1007 1008 _drawForWebGL:function (ctx) { 1009 var context = ctx || cc.renderContext; 1010 1011 cc.NODE_DRAW_SETUP(this); 1012 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR); 1013 1014 // 1015 // Attributes 1016 // 1017 context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer); 1018 context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, 0, 0); 1019 1020 context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer); 1021 context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.FLOAT, false, 0, 0); 1022 1023 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 1024 context.drawArrays(context.TRIANGLE_STRIP, 0, 4); 1025 } 1026 }); 1027 1028 if(cc.Browser.supportWebGL){ 1029 cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForWebGL; 1030 cc.LayerColor.prototype.setContentSize = cc.LayerColor.prototype._setContentSizeForWebGL; 1031 cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForWebGL; 1032 cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForWebGL; 1033 } else { 1034 cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForCanvas; 1035 cc.LayerColor.prototype.setContentSize = cc.LayerRGBA.prototype.setContentSize; 1036 cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForCanvas; 1037 cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForCanvas; 1038 } 1039 1040 1041 /** 1042 * creates a cc.Layer with color, width and height in Points 1043 * @param {cc.Color4B} color 1044 * @param {Number|Null} [width=] 1045 * @param {Number|Null} [height=] 1046 * @return {cc.LayerColor} 1047 * @example 1048 * // Example 1049 * //Create a yellow color layer as background 1050 * var yellowBackground = cc.LayerColor.create(cc.c4b(255,255,0,255)); 1051 * //If you didnt pass in width and height, it defaults to the same size as the canvas 1052 * 1053 * //create a yellow box, 200 by 200 in size 1054 * var yellowBox = cc.LayerColor.create(cc.c4b(255,255,0,255), 200, 200); 1055 */ 1056 cc.LayerColor.create = function (color, width, height) { 1057 var ret = new cc.LayerColor(); 1058 switch (arguments.length) { 1059 case 0: 1060 ret.init(); 1061 break; 1062 case 1: 1063 ret.init(color); 1064 break; 1065 case 3: 1066 ret.init(color, width, height); 1067 break; 1068 default : 1069 ret.init(); 1070 break; 1071 } 1072 return ret; 1073 }; 1074 1075 /** 1076 * <p> 1077 * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/> 1078 *<br/> 1079 * All features from cc.LayerColor are valid, plus the following new features:<br/> 1080 * <ul><li>direction</li> 1081 * <li>final color</li> 1082 * <li>interpolation mode</li></ul> 1083 * <br/> 1084 * Color is interpolated between the startColor and endColor along the given<br/> 1085 * vector (starting at the origin, ending at the terminus). If no vector is<br/> 1086 * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/> 1087 * <br/> 1088 * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/> 1089 * non-cardinal vectors; a smooth gradient implying both end points will be still<br/> 1090 * be drawn, however.<br/> 1091 *<br/> 1092 * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. 1093 * </p> 1094 * @class 1095 * @extends cc.LayerColor 1096 */ 1097 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ 1098 _startColor:null, 1099 _endColor:null, 1100 _startOpacity:null, 1101 _endOpacity:null, 1102 _alongVector:null, 1103 _compressedInterpolation:false, 1104 _gradientStartPoint:null, 1105 _gradientEndPoint:null, 1106 1107 /** 1108 * Constructor 1109 * @function 1110 */ 1111 ctor:function () { 1112 cc.LayerColor.prototype.ctor.call(this); 1113 1114 this._startColor = new cc.Color3B(0, 0, 0); 1115 this._endColor = new cc.Color3B(0, 0, 0); 1116 this._alongVector = cc.p(0, -1); 1117 this._startOpacity = 255; 1118 this._endOpacity = 255; 1119 this._gradientStartPoint = cc.p(0, 0); 1120 this._gradientEndPoint = cc.p(0, 0); 1121 }, 1122 1123 /** 1124 * override contentSize 1125 * @param {cc.Size} size 1126 */ 1127 setContentSize:function(size){ 1128 cc.LayerColor.prototype.setContentSize.call(this,size); 1129 this._updateColor(); 1130 }, 1131 1132 /** 1133 * get the starting color 1134 * @return {cc.Color3B} 1135 */ 1136 getStartColor:function () { 1137 return this._realColor; 1138 }, 1139 1140 /** 1141 * set the starting color 1142 * @param {cc.Color3B} color 1143 * @example 1144 * // Example 1145 * myGradientLayer.setStartColor(cc.c3b(255,0,0)); 1146 * //set the starting gradient to red 1147 */ 1148 setStartColor:function (color) { 1149 this.setColor(color); 1150 }, 1151 1152 /** 1153 * set the end gradient color 1154 * @param {cc.Color3B} color 1155 * @example 1156 * // Example 1157 * myGradientLayer.setEndColor(cc.c3b(255,0,0)); 1158 * //set the ending gradient to red 1159 */ 1160 setEndColor:function (color) { 1161 this._endColor = color; 1162 this._updateColor(); 1163 }, 1164 1165 /** 1166 * get the end color 1167 * @return {cc.Color3B} 1168 */ 1169 getEndColor:function () { 1170 return this._endColor; 1171 }, 1172 1173 /** 1174 * set starting gradient opacity 1175 * @param {Number} o from 0 to 255, 0 is transparent 1176 */ 1177 setStartOpacity:function (o) { 1178 this._startOpacity = o; 1179 this._updateColor(); 1180 }, 1181 1182 /** 1183 * get the starting gradient opacity 1184 * @return {Number} 1185 */ 1186 getStartOpacity:function () { 1187 return this._startOpacity; 1188 }, 1189 1190 /** 1191 * set the end gradient opacity 1192 * @param {Number} o 1193 */ 1194 setEndOpacity:function (o) { 1195 this._endOpacity = o; 1196 this._updateColor(); 1197 }, 1198 1199 /** 1200 * get the end gradient opacity 1201 * @return {Number} 1202 */ 1203 getEndOpacity:function () { 1204 return this._endOpacity; 1205 }, 1206 1207 /** 1208 * set vector 1209 * @param {cc.Point} Var 1210 */ 1211 setVector:function (Var) { 1212 this._alongVector.x = Var.x; 1213 this._alongVector.y = Var.y; 1214 this._updateColor(); 1215 }, 1216 1217 /** 1218 * @return {cc.Point} 1219 */ 1220 getVector:function () { 1221 return cc.p(this._alongVector.x, this._alongVector.y); 1222 }, 1223 1224 /** is Compressed Interpolation 1225 * @return {Boolean} 1226 */ 1227 isCompressedInterpolation:function () { 1228 return this._compressedInterpolation; 1229 }, 1230 1231 /** 1232 * @param {Boolean} compress 1233 */ 1234 setCompressedInterpolation:function (compress) { 1235 this._compressedInterpolation = compress; 1236 this._updateColor(); 1237 }, 1238 1239 /** 1240 * @param {cc.Color4B} start starting color 1241 * @param {cc.Color4B} end 1242 * @param {cc.Point|Null} v 1243 * @return {Boolean} 1244 */ 1245 init:function (start, end, v) { 1246 start = start || cc.c4(0,0,0,255); 1247 end = end || cc.c4(0,0,0,255); 1248 v = v || cc.p(0, -1); 1249 1250 // Initializes the CCLayer with a gradient between start and end in the direction of v. 1251 var locStartColor = this._startColor, locEndColor = this._endColor; 1252 locStartColor.r = start.r; 1253 locStartColor.g = start.g; 1254 locStartColor.b = start.b; 1255 this._startOpacity = start.a; 1256 1257 locEndColor.r = end.r; 1258 locEndColor.g = end.g; 1259 locEndColor.b = end.b; 1260 this._endOpacity = end.a; 1261 1262 this._alongVector = v; 1263 this._compressedInterpolation = true; 1264 1265 cc.LayerColor.prototype.init.call(this,cc.c4b(start.r, start.g, start.b, 255)); 1266 return true; 1267 }, 1268 1269 draw:function (ctx) { 1270 if (cc.renderContextType === cc.WEBGL){ 1271 cc.LayerColor.prototype.draw.call(this, ctx); 1272 return; 1273 } 1274 1275 var context = ctx || cc.renderContext; 1276 if (this._isLighterMode) 1277 context.globalCompositeOperation = 'lighter'; 1278 1279 context.save(); 1280 var locEGLViewer = cc.EGLView.getInstance(), opacityf = this._displayedOpacity / 255.0; 1281 var tWidth = this.getContentSize().width * locEGLViewer.getScaleX(); 1282 var tHeight = this.getContentSize().height * locEGLViewer.getScaleY(); 1283 var tGradient = context.createLinearGradient(this._gradientStartPoint.x, this._gradientStartPoint.y, 1284 this._gradientEndPoint.x, this._gradientEndPoint.y); 1285 var locDisplayedColor = this._displayedColor; 1286 var locEndColor = this._endColor; 1287 tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + "," 1288 + Math.round(locDisplayedColor.b) + "," + (opacityf * (this._startOpacity / 255)).toFixed(4) + ")"); 1289 tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + "," 1290 + Math.round(locEndColor.b) + "," + (opacityf * (this._endOpacity / 255)).toFixed(4) + ")"); 1291 context.fillStyle = tGradient; 1292 context.fillRect(0, 0, tWidth, -tHeight); 1293 1294 if (this._rotation != 0) 1295 context.rotate(this._rotationRadians); 1296 context.restore(); 1297 }, 1298 1299 _updateColor:function () { 1300 var locAlongVector = this._alongVector; 1301 if (cc.renderContextType === cc.CANVAS) { 1302 var tWidth = this.getContentSize().width * 0.5; 1303 var tHeight = this.getContentSize().height * 0.5; 1304 1305 this._gradientStartPoint = cc.p(tWidth * (-locAlongVector.x) + tWidth, tHeight * locAlongVector.y - tHeight); 1306 this._gradientEndPoint = cc.p(tWidth * locAlongVector.x + tWidth, tHeight * (-locAlongVector.y) - tHeight); 1307 } else { 1308 var h = cc.pLength(locAlongVector); 1309 if (h === 0) 1310 return; 1311 1312 var c = Math.sqrt(2.0); 1313 var u = cc.p(locAlongVector.x / h, locAlongVector.y / h); 1314 1315 // Compressed Interpolation mode 1316 if (this._compressedInterpolation) { 1317 var h2 = 1 / ( Math.abs(u.x) + Math.abs(u.y) ); 1318 u = cc.pMult(u, h2 * c); 1319 } 1320 1321 var opacityf = this._displayedOpacity / 255.0; 1322 var locDisplayedColor = this._displayedColor, locEndColor = this._endColor; 1323 var S = { r: locDisplayedColor.r / 255, g: locDisplayedColor.g / 255, b: locDisplayedColor.b / 255, a: (this._startOpacity * opacityf) / 255}; 1324 var E = {r: locEndColor.r / 255, g: locEndColor.g / 255, b: locEndColor.b / 255, a: (this._endOpacity * opacityf) / 255}; 1325 1326 // (-1, -1) 1327 var locSquareColors = this._squareColors; 1328 var locSquareColor0 = locSquareColors[0], locSquareColor1 = locSquareColors[1], locSquareColor2 = locSquareColors[2],locSquareColor3 = locSquareColors[3]; 1329 locSquareColor0.r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c)))); 1330 locSquareColor0.g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c)))); 1331 locSquareColor0.b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c)))); 1332 locSquareColor0.a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c)))); 1333 // (1, -1) 1334 locSquareColor1.r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c)))); 1335 locSquareColor1.g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c)))); 1336 locSquareColor1.b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c)))); 1337 locSquareColor1.a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c)))); 1338 // (-1, 1) 1339 locSquareColor2.r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c)))); 1340 locSquareColor2.g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c)))); 1341 locSquareColor2.b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c)))); 1342 locSquareColor2.a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c)))); 1343 // (1, 1) 1344 locSquareColor3.r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c)))); 1345 locSquareColor3.g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c)))); 1346 locSquareColor3.b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c)))); 1347 locSquareColor3.a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c)))); 1348 1349 this._bindLayerColorsBufferData(); 1350 } 1351 } 1352 }); 1353 1354 /** 1355 * creates a gradient layer 1356 * @param {cc.Color3B} start starting color 1357 * @param {cc.Color3B} end ending color 1358 * @param {cc.Point|Null} v 1359 * @return {cc.LayerGradient} 1360 */ 1361 cc.LayerGradient.create = function (start, end, v) { 1362 var layer = new cc.LayerGradient(); 1363 switch (arguments.length) { 1364 case 2: 1365 /** Creates a full-screen CCLayer with a gradient between start and end. */ 1366 if (layer && layer.init(start, end)) 1367 return layer; 1368 break; 1369 case 3: 1370 /** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */ 1371 if (layer && layer.init(start, end, v)) 1372 return layer; 1373 break; 1374 case 0: 1375 if (layer && layer.init()) 1376 return layer; 1377 break; 1378 default: 1379 throw "Arguments error "; 1380 break; 1381 } 1382 return null; 1383 }; 1384 1385 /** 1386 * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/> 1387 * Features:<br/> 1388 * <ul><li>- It supports one or more children</li> 1389 * <li>- Only one children will be active a time</li></ul> 1390 * @class 1391 * @extends cc.Layer 1392 */ 1393 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{ 1394 _enabledLayer:0, 1395 _layers:null, 1396 1397 /** 1398 * @param {cc.Layer} layer 1399 * @deprecated merged with initWithLayers 1400 * @return {Boolean} 1401 */ 1402 initWithLayer:function (layer) { 1403 this._layers = []; 1404 this._layers.push(layer); 1405 this._enabledLayer = 0; 1406 this.addChild(layer); 1407 return true; 1408 }, 1409 1410 /** 1411 * @param {Array} args an array of cc.Layer 1412 * @return {Boolean} 1413 */ 1414 initWithLayers:function (args) { 1415 this._layers = args; 1416 this._enabledLayer = 0; 1417 this.addChild(this._layers[this._enabledLayer]); 1418 return true; 1419 }, 1420 1421 /** 1422 * switches to a certain layer indexed by n.<br/> 1423 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 1424 * @param {Number} n the layer index to switch to 1425 */ 1426 switchTo:function (n) { 1427 if(n >= this._layers.length){ 1428 cc.log("cc.LayerMultiplex.switchTo():Invalid index in MultiplexLayer switchTo message"); 1429 return; 1430 } 1431 1432 this.removeChild(this._layers[this._enabledLayer], true); 1433 this._enabledLayer = n; 1434 this.addChild(this._layers[n]); 1435 }, 1436 1437 /** release the current layer and switches to another layer indexed by n.<br/> 1438 * The current (old) layer will be removed from it's parent with 'cleanup:YES'. 1439 * @param {Number} n the layer index to switch to 1440 */ 1441 switchToAndReleaseMe:function (n) { 1442 if(n >= this._layers.length){ 1443 cc.log("cc.LayerMultiplex.switchToAndReleaseMe():Invalid index in MultiplexLayer switchTo message"); 1444 return; 1445 } 1446 1447 this.removeChild(this._layers[this._enabledLayer], true); 1448 1449 //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]]; 1450 this._layers[this._enabledLayer] = null; 1451 this._enabledLayer = n; 1452 this.addChild(this._layers[n]); 1453 }, 1454 1455 /** 1456 * @param {cc.Layer} layer 1457 */ 1458 addLayer:function (layer) { 1459 if(!layer){ 1460 cc.log("cc.Layer.addLayer(): layer should be non-null"); 1461 return; 1462 } 1463 this._layers.push(layer); 1464 } 1465 }); 1466 1467 /** 1468 * creates a cc.LayerMultiplex with one or more layers using a variable argument list. 1469 * @return {cc.LayerMultiplex|Null} 1470 * @example 1471 * // Example 1472 * var multiLayer = cc.LayerMultiple.create(layer1, layer2, layer3);//any number of layers 1473 */ 1474 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) { 1475 if((arguments.length > 0) && (arguments[arguments.length-1] == null)) 1476 cc.log("parameters should not be ending with null in Javascript"); 1477 var multiplexLayer = new cc.LayerMultiplex(); 1478 if (multiplexLayer.initWithLayers(arguments)) { 1479 return multiplexLayer; 1480 } 1481 return null; 1482 }; 1483 1484