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