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(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      * Get the opacity of Layer
608      * @returns {number} opacity
609      */
610     getOpacity: function () {
611         return this._realOpacity;
612     },
613 
614     /**
615      * Get the displayed opacity of Layer
616      * @returns {number} displayed opacity
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      * Update displayed opacity of Layer
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     /**
653      * whether or not it will set cascade opacity.
654      * @returns {boolean}
655      */
656     isCascadeOpacityEnabled: function () {
657         return this._cascadeOpacityEnabled;
658     },
659 
660     /**
661      * Enable or disable cascade opacity
662      * @param {boolean} cascadeOpacityEnabled
663      */
664     setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
665         if(this._cascadeOpacityEnabled === cascadeOpacityEnabled)
666             return;
667 
668         this._cascadeOpacityEnabled = cascadeOpacityEnabled;
669         if(cascadeOpacityEnabled)
670             this._enableCascadeOpacity();
671         else
672             this._disableCascadeOpacity();
673     },
674 
675     _enableCascadeOpacity:function(){
676         var parentOpacity = 255, locParent = this._parent;
677         if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
678             parentOpacity = locParent.getDisplayedOpacity();
679         this.updateDisplayedOpacity(parentOpacity);
680     },
681 
682     _disableCascadeOpacity:function(){
683         this._displayedOpacity = this._realOpacity;
684         var selChildren = this._children;
685         for(var i = 0; i< selChildren.length;i++){
686             var item = selChildren[i];
687             if(item && item.RGBAProtocol)
688                 item.updateDisplayedOpacity(255);
689         }
690     },
691 
692     /**
693      * Get the color of Layer
694      * @returns {cc.Color3B}
695      */
696     getColor: function () {
697         var locRealColor = this._realColor;
698         return cc.c3b(locRealColor.r, locRealColor.g, locRealColor.b);
699     },
700 
701     /**
702      * Get the displayed color of Layer
703      * @returns {cc.Color3B}
704      */
705     getDisplayedColor: function () {
706         var locDisplayedColor = this._displayedColor;
707         return cc.c3b(locDisplayedColor.r, locDisplayedColor.g, locDisplayedColor.b);
708     },
709 
710     /**
711      * Set the color of Layer
712      * @param {cc.Color3B} color
713      */
714     setColor: function (color) {
715         var locDisplayed = this._displayedColor, locRealColor = this._realColor;
716         locDisplayed.r = locRealColor.r = color.r;
717         locDisplayed.g = locRealColor.g = color.g;
718         locDisplayed.b = locRealColor.b = color.b;
719 
720         var parentColor, locParent = this._parent;
721         if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled())
722             parentColor = locParent.getDisplayedColor();
723         else
724             parentColor = cc.white();
725         this.updateDisplayedColor(parentColor);
726     },
727 
728     /**
729      * update the displayed color of Node
730      * @param {cc.Color3B} parentColor
731      */
732     updateDisplayedColor: function (parentColor) {
733         var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
734         locDisplayedColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
735         locDisplayedColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
736         locDisplayedColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
737 
738         if (this._cascadeColorEnabled) {
739             var locChildren = this._children;
740             for (var i = 0; i < locChildren.length; i++) {
741                 var selItem = locChildren[i];
742                 if (selItem && selItem.RGBAProtocol)
743                     selItem.updateDisplayedColor(locDisplayedColor);
744             }
745         }
746     },
747 
748     /**
749      * whether or not it will set cascade color.
750      * @returns {boolean}
751      */
752     isCascadeColorEnabled: function () {
753         return this._cascadeColorEnabled;
754     },
755 
756     /**
757      * Enable or disable cascade color
758      * @param {boolean} cascadeColorEnabled
759      */
760     setCascadeColorEnabled: function (cascadeColorEnabled) {
761         if(this._cascadeColorEnabled === cascadeColorEnabled)
762             return;
763         this._cascadeColorEnabled = cascadeColorEnabled;
764         if(this._cascadeColorEnabled)
765             this._enableCascadeColor();
766         else
767             this._disableCascadeColor();
768     },
769 
770     _enableCascadeColor: function(){
771         var parentColor , locParent =  this._parent;
772         if (locParent && locParent.RGBAProtocol &&  locParent.isCascadeColorEnabled())
773             parentColor = locParent.getDisplayedColor();
774         else
775             parentColor = cc.white();
776         this.updateDisplayedColor(parentColor);
777     },
778 
779     _disableCascadeColor: function(){
780         var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
781         locDisplayedColor.r = locRealColor.r;
782         locDisplayedColor.g = locRealColor.g;
783         locDisplayedColor.b = locRealColor.b;
784 
785         var selChildren = this._children, whiteColor = cc.white();
786         for(var i = 0; i< selChildren.length;i++){
787             var item = selChildren[i];
788             if(item && item.RGBAProtocol)
789                 item.updateDisplayedColor(whiteColor);
790         }
791     },
792 
793     /**
794      * add a child to layer
795      * @overried
796      * @param {cc.Node} child  A child node
797      * @param {Number} [zOrder=]  Z order for drawing priority. Please refer to setZOrder(int)
798      * @param {Number} [tag=]  A integer to identify the node easily. Please refer to setTag(int)
799      */
800     addChild:function(child, zOrder, tag){
801         cc.Node.prototype.addChild.call(this, child, zOrder, tag);
802 
803         if(this._cascadeColorEnabled)
804             this._enableCascadeColor();
805         if(this._cascadeOpacityEnabled)
806             this._enableCascadeOpacity();
807     },
808 
809     setOpacityModifyRGB: function (bValue) {
810     },
811 
812     isOpacityModifyRGB: function () {
813         return false;
814     }
815 });
816 
817 /**
818  * <p>
819  * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.       <br/>
820  *  All features from CCLayer are valid, plus the following new features:                   <br/>
821  * <ul><li>opacity</li>                                                                     <br/>
822  * <li>RGB colors</li></ul>                                                                 <br/>
823  * </p>
824  * @class
825  * @extends cc.LayerRGBA
826  */
827 cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{
828     _blendFunc:null,
829 
830     /**
831      * blendFunc getter
832      * @return {cc.BlendFunc}
833      */
834     getBlendFunc:function () {
835         return this._blendFunc;
836     },
837 
838     /**
839      * change width and height in Points
840      * @param {Number} w width
841      * @param {Number} h height
842      */
843     changeWidthAndHeight:function (w, h) {
844         this.setContentSize(w, h);
845     },
846 
847     /**
848      * change width in Points
849      * @param {Number} w width
850      */
851     changeWidth:function (w) {
852         this.setContentSize(w, this._contentSize._height);
853     },
854 
855     /**
856      * change height in Points
857      * @param {Number} h height
858      */
859     changeHeight:function (h) {
860         this.setContentSize(this._contentSize._width, h);
861     },
862 
863     /**
864      * set OpacityModifyRGB of cc.LayerColor
865      * @param {Boolean}  value
866      */
867     setOpacityModifyRGB:function (value) {
868     },
869 
870     /**
871      * is OpacityModifyRGB
872      * @return {Boolean}
873      */
874     isOpacityModifyRGB:function () {
875         return false;
876     },
877 
878     setColor:function(color){
879         cc.LayerRGBA.prototype.setColor.call(this, color);
880         this._updateColor();
881     },
882 
883     setOpacity:function(opacity){
884         cc.LayerRGBA.prototype.setOpacity.call(this, opacity);
885         this._updateColor();
886     },
887 
888     _isLighterMode:false,
889     _squareVertices:null,
890     _squareColors:null,
891     _verticesFloat32Buffer:null,
892     _colorsUint8Buffer:null,
893     _squareVerticesAB:null,
894     _squareColorsAB:null,
895 
896     _ctorForCanvas: function () {
897         cc.LayerRGBA.prototype.ctor.call(this);
898         this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
899     },
900 
901     _ctorForWebGL: function () {
902         cc.LayerRGBA.prototype.ctor.call(this);
903         this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
904 
905         this._squareVerticesAB = new ArrayBuffer(32);
906         this._squareColorsAB = new ArrayBuffer(64);
907 
908         var locSquareVerticesAB = this._squareVerticesAB, locSquareColorsAB = this._squareColorsAB;
909         var locVertex2FLen = cc.Vertex2F.BYTES_PER_ELEMENT, locColor4FLen = cc.Color4F.BYTES_PER_ELEMENT;
910         this._squareVertices = [new cc.Vertex2F(0, 0, locSquareVerticesAB, 0),
911             new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen),
912             new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 2),
913             new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 3)];
914         this._squareColors = [new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, 0),
915             new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen),
916             new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 2),
917             new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 3)];
918         this._verticesFloat32Buffer = cc.renderContext.createBuffer();
919         this._colorsUint8Buffer = cc.renderContext.createBuffer();
920     },
921 
922     /**
923      * blendFunc setter
924      * @param {Number} src
925      * @param {Number} dst
926      */
927     setBlendFunc:function (src, dst) {
928         if (arguments.length == 1)
929             this._blendFunc = src;
930         else
931             this._blendFunc = {src:src, dst:dst};
932         if(cc.renderContextType === cc.CANVAS)
933             this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771));
934     },
935 
936     /**
937      * @param {cc.Color4B} [color=]
938      * @param {Number} [width=]
939      * @param {Number} [height=]
940      * @return {Boolean}
941      */
942     init:function (color, width, height) {
943         if(!cc.Layer.prototype.init.call(this))
944             return false;
945 
946         if(cc.renderContextType !== cc.CANVAS)
947             this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR));
948 
949         var winSize = cc.Director.getInstance().getWinSize();
950         color = color || new cc.Color4B(0, 0, 0, 255);
951         width = width || winSize.width;
952         height = height || winSize.height;
953 
954         var locDisplayedColor = this._displayedColor;
955         locDisplayedColor.r = color.r;
956         locDisplayedColor.g = color.g;
957         locDisplayedColor.b = color.b;
958 
959         var locRealColor = this._realColor;
960         locRealColor.r = color.r;
961         locRealColor.g = color.g;
962         locRealColor.b = color.b;
963 
964         this._displayedOpacity = color.a;
965         this._realOpacity = color.a;
966 
967         this.setContentSize(width, height);
968         this._updateColor();
969         return true;
970     },
971 
972     /**
973      * Sets the untransformed size of the LayerColor.
974      * @override
975      * @param {cc.Size|Number} size The untransformed size of the LayerColor or The untransformed size's width of the LayerColor.
976      * @param {Number} [height] The untransformed size's height of the LayerColor.
977      */
978     setContentSize:null,
979 
980     _setContentSizeForWebGL:function (size, height) {
981         var locSquareVertices = this._squareVertices;
982         if(arguments.length === 2){
983             locSquareVertices[1].x = size;
984             locSquareVertices[2].y = height;
985             locSquareVertices[3].x = size;
986             locSquareVertices[3].y = height;
987             this._bindLayerVerticesBufferData();
988             cc.Layer.prototype.setContentSize.call(this, size, height);
989         }else{
990             locSquareVertices[1].x = size.width;
991             locSquareVertices[2].y = size.height;
992             locSquareVertices[3].x = size.width;
993             locSquareVertices[3].y = size.height;
994             this._bindLayerVerticesBufferData();
995             cc.Layer.prototype.setContentSize.call(this,size);
996         }
997     },
998 
999     _updateColor:null,
1000 
1001     _updateColorForCanvas:function () {
1002     },
1003 
1004     _updateColorForWebGL:function () {
1005         var locDisplayedColor = this._displayedColor;
1006         var locDisplayedOpacity = this._displayedOpacity, locSquareColors = this._squareColors;
1007         for (var i = 0; i < 4; i++) {
1008             locSquareColors[i].r = locDisplayedColor.r / 255;
1009             locSquareColors[i].g = locDisplayedColor.g / 255;
1010             locSquareColors[i].b = locDisplayedColor.b / 255;
1011             locSquareColors[i].a = locDisplayedOpacity / 255;
1012         }
1013         this._bindLayerColorsBufferData();
1014     },
1015 
1016     updateDisplayedColor:function(parentColor){
1017         cc.LayerRGBA.prototype.updateDisplayedColor.call(this, parentColor);
1018         this._updateColor();
1019     },
1020 
1021     updateDisplayedOpacity: function(parentOpacity){
1022         cc.LayerRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity);
1023         this._updateColor();
1024     },
1025 
1026     _bindLayerVerticesBufferData:function () {
1027         var glContext = cc.renderContext;
1028         glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer);
1029         glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW);
1030     },
1031 
1032     _bindLayerColorsBufferData:function () {
1033         var glContext = cc.renderContext;
1034         glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer);
1035         glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW);
1036     },
1037 
1038     /**
1039      * renders the layer
1040      * @param {CanvasRenderingContext2D|Null} ctx
1041      */
1042     draw:null,
1043 
1044     _drawForCanvas:function (ctx) {
1045         var context = ctx || cc.renderContext;
1046 
1047         var locContentSize = this.getContentSize(), locEGLViewer = cc.EGLView.getInstance();
1048 
1049         var locDisplayedColor = this._displayedColor;
1050 
1051         context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + ","
1052             + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")";
1053         context.fillRect(0, 0, locContentSize.width * locEGLViewer.getScaleX(), -locContentSize.height * locEGLViewer.getScaleY());
1054 
1055         cc.g_NumberOfDraws++;
1056     },
1057 
1058     _drawForWebGL:function (ctx) {
1059         var context = ctx || cc.renderContext;
1060 
1061         cc.NODE_DRAW_SETUP(this);
1062         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR);
1063 
1064         //
1065         // Attributes
1066         //
1067         context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer);
1068         context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, 0, 0);
1069 
1070         context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer);
1071         context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.FLOAT, false, 0, 0);
1072 
1073         cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
1074         context.drawArrays(context.TRIANGLE_STRIP, 0, 4);
1075     }
1076 });
1077 
1078 if(cc.Browser.supportWebGL){
1079     cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForWebGL;
1080     cc.LayerColor.prototype.setContentSize = cc.LayerColor.prototype._setContentSizeForWebGL;
1081     cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForWebGL;
1082     cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForWebGL;
1083 } else {
1084     cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForCanvas;
1085     cc.LayerColor.prototype.setContentSize = cc.LayerRGBA.prototype.setContentSize;
1086     cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForCanvas;
1087     cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForCanvas;
1088 }
1089 
1090 
1091 /**
1092  * creates a cc.Layer with color, width and height in Points
1093  * @param {cc.Color4B} color
1094  * @param {Number|Null} [width=]
1095  * @param {Number|Null} [height=]
1096  * @return {cc.LayerColor}
1097  * @example
1098  * // Example
1099  * //Create a yellow color layer as background
1100  * var yellowBackground = cc.LayerColor.create(cc.c4b(255,255,0,255));
1101  * //If you didnt pass in width and height, it defaults to the same size as the canvas
1102  *
1103  * //create a yellow box, 200 by 200 in size
1104  * var yellowBox = cc.LayerColor.create(cc.c4b(255,255,0,255), 200, 200);
1105  */
1106 cc.LayerColor.create = function (color, width, height) {
1107     var ret = new cc.LayerColor();
1108     switch (arguments.length) {
1109         case 0:
1110             ret.init();
1111             break;
1112         case 1:
1113             ret.init(color);
1114             break;
1115         case 3:
1116             ret.init(color, width, height);
1117             break;
1118         default :
1119             ret.init();
1120             break;
1121     }
1122     return ret;
1123 };
1124 
1125 /**
1126  * <p>
1127  * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/>
1128  *<br/>
1129  * All features from cc.LayerColor are valid, plus the following new features:<br/>
1130  * <ul><li>direction</li>
1131  * <li>final color</li>
1132  * <li>interpolation mode</li></ul>
1133  * <br/>
1134  * Color is interpolated between the startColor and endColor along the given<br/>
1135  * vector (starting at the origin, ending at the terminus).  If no vector is<br/>
1136  * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/>
1137  * <br/>
1138  * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/>
1139  * non-cardinal vectors; a smooth gradient implying both end points will be still<br/>
1140  * be drawn, however.<br/>
1141  *<br/>
1142  * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
1143  * </p>
1144  * @class
1145  * @extends cc.LayerColor
1146  */
1147 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
1148     _startColor:null,
1149     _endColor:null,
1150     _startOpacity:null,
1151     _endOpacity:null,
1152     _alongVector:null,
1153     _compressedInterpolation:false,
1154     _gradientStartPoint:null,
1155     _gradientEndPoint:null,
1156 
1157     /**
1158      * Constructor
1159      * @function
1160      */
1161     ctor:function () {
1162         cc.LayerColor.prototype.ctor.call(this);
1163 
1164         this._startColor = new cc.Color3B(0, 0, 0);
1165         this._endColor = new cc.Color3B(0, 0, 0);
1166         this._alongVector = cc.p(0, -1);
1167         this._startOpacity = 255;
1168         this._endOpacity = 255;
1169         this._gradientStartPoint = cc.p(0, 0);
1170         this._gradientEndPoint = cc.p(0, 0);
1171     },
1172 
1173     /**
1174      * Sets the untransformed size of the LayerGradient.
1175      * @override
1176      * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient.
1177      * @param {Number} [height] The untransformed size's height of the LayerGradient.
1178      */
1179     setContentSize:function(size, height){
1180         if(arguments.length === 2)
1181             cc.LayerColor.prototype.setContentSize.call(this,size, height);
1182         else
1183             cc.LayerColor.prototype.setContentSize.call(this,size);
1184         this._updateColor();
1185     },
1186 
1187     /**
1188      * get the starting color
1189      * @return {cc.Color3B}
1190      */
1191     getStartColor:function () {
1192         return this._realColor;
1193     },
1194 
1195     /**
1196      * set the starting color
1197      * @param {cc.Color3B} color
1198      * @example
1199      * // Example
1200      * myGradientLayer.setStartColor(cc.c3b(255,0,0));
1201      * //set the starting gradient to red
1202      */
1203     setStartColor:function (color) {
1204         this.setColor(color);
1205     },
1206 
1207     /**
1208      * set the end gradient color
1209      * @param {cc.Color3B} color
1210      * @example
1211      * // Example
1212      * myGradientLayer.setEndColor(cc.c3b(255,0,0));
1213      * //set the ending gradient to red
1214      */
1215     setEndColor:function (color) {
1216         this._endColor = color;
1217         this._updateColor();
1218     },
1219 
1220     /**
1221      * get the end color
1222      * @return {cc.Color3B}
1223      */
1224     getEndColor:function () {
1225         return this._endColor;
1226     },
1227 
1228     /**
1229      * set starting gradient opacity
1230      * @param {Number} o from 0 to 255, 0 is transparent
1231      */
1232     setStartOpacity:function (o) {
1233         this._startOpacity = o;
1234         this._updateColor();
1235     },
1236 
1237     /**
1238      * get the starting gradient opacity
1239      * @return {Number}
1240      */
1241     getStartOpacity:function () {
1242         return this._startOpacity;
1243     },
1244 
1245     /**
1246      * set the end gradient opacity
1247      * @param {Number} o
1248      */
1249     setEndOpacity:function (o) {
1250         this._endOpacity = o;
1251         this._updateColor();
1252     },
1253 
1254     /**
1255      * get the end gradient opacity
1256      * @return {Number}
1257      */
1258     getEndOpacity:function () {
1259         return this._endOpacity;
1260     },
1261 
1262     /**
1263      * set vector
1264      * @param {cc.Point} Var
1265      */
1266     setVector:function (Var) {
1267         this._alongVector.x = Var.x;
1268         this._alongVector.y = Var.y;
1269         this._updateColor();
1270     },
1271 
1272     /**
1273      * @return {cc.Point}
1274      */
1275     getVector:function () {
1276         return cc.p(this._alongVector.x, this._alongVector.y);
1277     },
1278 
1279     /** is Compressed Interpolation
1280      * @return {Boolean}
1281      */
1282     isCompressedInterpolation:function () {
1283         return this._compressedInterpolation;
1284     },
1285 
1286     /**
1287      * @param {Boolean} compress
1288      */
1289     setCompressedInterpolation:function (compress) {
1290         this._compressedInterpolation = compress;
1291         this._updateColor();
1292     },
1293 
1294     /**
1295      * @param {cc.Color4B} start starting color
1296      * @param {cc.Color4B} end
1297      * @param {cc.Point|Null} v
1298      * @return {Boolean}
1299      */
1300     init:function (start, end, v) {
1301         start = start || cc.c4(0,0,0,255);
1302         end = end || cc.c4(0,0,0,255);
1303         v = v || cc.p(0, -1);
1304 
1305         // Initializes the CCLayer with a gradient between start and end in the direction of v.
1306         var locStartColor = this._startColor, locEndColor = this._endColor;
1307         locStartColor.r = start.r;
1308         locStartColor.g = start.g;
1309         locStartColor.b = start.b;
1310         this._startOpacity = start.a;
1311 
1312         locEndColor.r = end.r;
1313         locEndColor.g = end.g;
1314         locEndColor.b = end.b;
1315         this._endOpacity = end.a;
1316 
1317         this._alongVector = v;
1318         this._compressedInterpolation = true;
1319 
1320         cc.LayerColor.prototype.init.call(this,cc.c4b(start.r, start.g, start.b, 255));
1321         return true;
1322     },
1323 
1324     draw:function (ctx) {
1325         if (cc.renderContextType === cc.WEBGL){
1326             cc.LayerColor.prototype.draw.call(this, ctx);
1327             return;
1328         }
1329 
1330         var context = ctx || cc.renderContext;
1331         if (this._isLighterMode)
1332             context.globalCompositeOperation = 'lighter';
1333 
1334         context.save();
1335         var locEGLViewer = cc.EGLView.getInstance(), opacityf = this._displayedOpacity / 255.0;
1336         var tWidth = this.getContentSize().width * locEGLViewer.getScaleX();
1337         var tHeight = this.getContentSize().height * locEGLViewer.getScaleY();
1338         var tGradient = context.createLinearGradient(this._gradientStartPoint.x, this._gradientStartPoint.y,
1339             this._gradientEndPoint.x, this._gradientEndPoint.y);
1340         var locDisplayedColor = this._displayedColor;
1341         var locEndColor = this._endColor;
1342         tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + ","
1343             + Math.round(locDisplayedColor.b) + "," + (opacityf * (this._startOpacity / 255)).toFixed(4) + ")");
1344         tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
1345             + Math.round(locEndColor.b) + "," + (opacityf * (this._endOpacity / 255)).toFixed(4) + ")");
1346         context.fillStyle = tGradient;
1347         context.fillRect(0, 0, tWidth, -tHeight);
1348 
1349         if (this._rotation != 0)
1350             context.rotate(this._rotationRadians);
1351         context.restore();
1352     },
1353 
1354     _updateColor:function () {
1355         var locAlongVector = this._alongVector;
1356         if (cc.renderContextType === cc.CANVAS) {
1357             var tWidth = this.getContentSize().width * 0.5;
1358             var tHeight = this.getContentSize().height * 0.5;
1359 
1360             this._gradientStartPoint.x = tWidth * (-locAlongVector.x) + tWidth;
1361             this._gradientStartPoint.y = tHeight * locAlongVector.y - tHeight;
1362             this._gradientEndPoint.x = tWidth * locAlongVector.x + tWidth;
1363             this._gradientEndPoint.y = tHeight * (-locAlongVector.y) - tHeight;
1364         } else {
1365             var h = cc.pLength(locAlongVector);
1366             if (h === 0)
1367                 return;
1368 
1369             var c = Math.sqrt(2.0);
1370             var u = cc.p(locAlongVector.x / h, locAlongVector.y / h);
1371 
1372             // Compressed Interpolation mode
1373             if (this._compressedInterpolation) {
1374                 var h2 = 1 / ( Math.abs(u.x) + Math.abs(u.y) );
1375                 u = cc.pMult(u, h2 * c);
1376             }
1377 
1378             var opacityf = this._displayedOpacity / 255.0;
1379             var locDisplayedColor = this._displayedColor, locEndColor = this._endColor;
1380             var S = { r: locDisplayedColor.r / 255, g: locDisplayedColor.g / 255, b: locDisplayedColor.b / 255, a: (this._startOpacity * opacityf) / 255};
1381             var E = {r: locEndColor.r / 255, g: locEndColor.g / 255, b: locEndColor.b / 255, a: (this._endOpacity * opacityf) / 255};
1382 
1383             // (-1, -1)
1384             var locSquareColors = this._squareColors;
1385             var locSquareColor0 = locSquareColors[0], locSquareColor1 = locSquareColors[1], locSquareColor2 = locSquareColors[2],locSquareColor3 = locSquareColors[3];
1386             locSquareColor0.r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c))));
1387             locSquareColor0.g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c))));
1388             locSquareColor0.b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c))));
1389             locSquareColor0.a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c))));
1390             // (1, -1)
1391             locSquareColor1.r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c))));
1392             locSquareColor1.g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c))));
1393             locSquareColor1.b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c))));
1394             locSquareColor1.a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c))));
1395             // (-1, 1)
1396             locSquareColor2.r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c))));
1397             locSquareColor2.g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c))));
1398             locSquareColor2.b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c))));
1399             locSquareColor2.a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c))));
1400             // (1, 1)
1401             locSquareColor3.r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c))));
1402             locSquareColor3.g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c))));
1403             locSquareColor3.b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c))));
1404             locSquareColor3.a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c))));
1405 
1406             this._bindLayerColorsBufferData();
1407         }
1408     }
1409 });
1410 
1411 /**
1412  * creates a gradient layer
1413  * @param {cc.Color3B} start starting color
1414  * @param {cc.Color3B} end ending color
1415  * @param {cc.Point|Null} v
1416  * @return {cc.LayerGradient}
1417  */
1418 cc.LayerGradient.create = function (start, end, v) {
1419     var layer = new cc.LayerGradient();
1420     switch (arguments.length) {
1421         case 2:
1422             /** Creates a full-screen CCLayer with a gradient between start and end. */
1423             if (layer && layer.init(start, end))
1424                 return layer;
1425             break;
1426         case 3:
1427             /** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */
1428             if (layer && layer.init(start, end, v))
1429                 return layer;
1430             break;
1431         case 0:
1432             if (layer && layer.init())
1433                 return layer;
1434             break;
1435         default:
1436             throw "Arguments error ";
1437             break;
1438     }
1439     return null;
1440 };
1441 
1442 /**
1443  * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/>
1444  * Features:<br/>
1445  *  <ul><li>- It supports one or more children</li>
1446  *  <li>- Only one children will be active a time</li></ul>
1447  *  @class
1448  *  @extends cc.Layer
1449  */
1450 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{
1451     _enabledLayer:0,
1452     _layers:null,
1453 
1454     /**
1455      * @param {cc.Layer} layer
1456      * @deprecated merged with initWithLayers
1457      * @return {Boolean}
1458      */
1459     initWithLayer:function (layer) {
1460         this._layers = [];
1461         this._layers.push(layer);
1462         this._enabledLayer = 0;
1463         this.addChild(layer);
1464         return true;
1465     },
1466 
1467     /**
1468      * @param {Array} args an array of cc.Layer
1469      * @return {Boolean}
1470      */
1471     initWithLayers:function (args) {
1472         this._layers = args;
1473         this._enabledLayer = 0;
1474         this.addChild(this._layers[this._enabledLayer]);
1475         return true;
1476     },
1477 
1478     /**
1479      * switches to a certain layer indexed by n.<br/>
1480      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
1481      * @param {Number} n the layer index to switch to
1482      */
1483     switchTo:function (n) {
1484         if(n >= this._layers.length){
1485             cc.log("cc.LayerMultiplex.switchTo():Invalid index in MultiplexLayer switchTo message");
1486             return;
1487         }
1488 
1489         this.removeChild(this._layers[this._enabledLayer], true);
1490         this._enabledLayer = n;
1491         this.addChild(this._layers[n]);
1492     },
1493 
1494     /** release the current layer and switches to another layer indexed by n.<br/>
1495      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
1496      * @param {Number} n the layer index to switch to
1497      */
1498     switchToAndReleaseMe:function (n) {
1499         if(n >= this._layers.length){
1500             cc.log("cc.LayerMultiplex.switchToAndReleaseMe():Invalid index in MultiplexLayer switchTo message");
1501             return;
1502         }
1503 
1504         this.removeChild(this._layers[this._enabledLayer], true);
1505 
1506         //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]];
1507         this._layers[this._enabledLayer] = null;
1508         this._enabledLayer = n;
1509         this.addChild(this._layers[n]);
1510     },
1511 
1512     /**
1513      * @param {cc.Layer} layer
1514      */
1515     addLayer:function (layer) {
1516         if(!layer){
1517             cc.log("cc.Layer.addLayer(): layer should be non-null");
1518             return;
1519         }
1520         this._layers.push(layer);
1521     }
1522 });
1523 
1524 /**
1525  * creates a cc.LayerMultiplex with one or more layers using a variable argument list.
1526  * @return {cc.LayerMultiplex|Null}
1527  * @example
1528  * // Example
1529  * var multiLayer = cc.LayerMultiple.create(layer1, layer2, layer3);//any number of layers
1530  */
1531 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) {
1532     if((arguments.length > 0) && (arguments[arguments.length-1] == null))
1533         cc.log("parameters should not be ending with null in Javascript");
1534     var multiplexLayer = new cc.LayerMultiplex();
1535     if (multiplexLayer.initWithLayers(arguments)) {
1536         return multiplexLayer;
1537     }
1538     return null;
1539 };
1540 
1541