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