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 /** cc.Layer is a subclass of cc.Node that implements the TouchEventsDelegate protocol.<br/>
 28  * All features from cc.Node are valid, plus the following new features:<br/>
 29  * It can receive iPhone Touches<br/>
 30  * It can receive Accelerometer input
 31  * @class
 32  * @extends cc.Node
 33  */
 34 cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{
 35     /**
 36      * init layer
 37      * @return {Boolean}
 38      */
 39     _className:"Layer",
 40 
 41 	/**
 42 	 * @constructor
 43 	 */
 44     ctor: function () {
 45         cc.Node.prototype.ctor.call(this);
 46         this.anchorX = 0.5;
 47         this.anchorY = 0.5;
 48         this._ignoreAnchorPointForPosition = true;
 49         this.setContentSize(cc.winSize);
 50     }
 51 });
 52 
 53 /**
 54  * creates a layer
 55  * @example
 56  * // Example
 57  * var myLayer = cc.Layer.create();
 58  * //Yes! it's that simple
 59  * @return {cc.Layer|Null}
 60  */
 61 cc.Layer.create = function () {
 62     var ret = new cc.Layer();
 63     return ret;
 64 
 65 };
 66 
 67 /**
 68  * <p>
 69  *     CCLayerRGBA is a subclass of CCLayer that implements the CCRGBAProtocol protocol using a solid color as the background.                        <br/>
 70  *     All features from CCLayer are valid, plus the following new features that propagate into children that conform to the CCRGBAProtocol:          <br/>
 71  *       - opacity                                                                                                                                    <br/>
 72  *       - RGB colors
 73  * </p>
 74  * @class
 75  * @extends cc.Layer
 76  *
 77  * @property {Number}       opacity             - Opacity of layer
 78  * @property {Boolean}      opacityModifyRGB    - Indicate whether or not the opacity modify color
 79  * @property {Boolean}      cascadeOpacity      - Indicate whether or not it will set cascade opacity
 80  * @property {cc.Color}     color               - Color of layer
 81  * @property {Boolean}      cascadeColor        - Indicate whether or not it will set cascade color
 82  */
 83 cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{
 84     RGBAProtocol:true,
 85     _displayedOpacity: 255,
 86     _realOpacity: 255,
 87     _displayedColor: null,
 88     _realColor: null,
 89     _cascadeOpacityEnabled: false,
 90     _cascadeColorEnabled: false,
 91     _className:"LayerRGBA",
 92 
 93 	/**
 94 	 * @constructor
 95 	 */
 96     ctor: function () {
 97 		this._displayedColor = cc.color(255, 255, 255, 255);
 98 		this._realColor = cc.color(255, 255, 255, 255);
 99         cc.Layer.prototype.ctor.call(this);
100     },
101 
102     init: function () {
103         if(cc.Layer.prototype.init.call(this)){
104             this.cascadeOpacity = false;
105             this.cascadeColor = false;
106             return true;
107         }
108         return false;
109     },
110 
111     /**
112      * Get the opacity of Layer
113      * @returns {number} opacity
114      */
115     getOpacity: function () {
116         return this._realOpacity;
117     },
118 
119     /**
120      * Get the displayed opacity of Layer
121      * @returns {number} displayed opacity
122      */
123     getDisplayedOpacity: function () {
124         return this._displayedOpacity;
125     },
126 
127     /**
128      * Override synthesized setOpacity to recurse items
129      * @param {Number} opacity
130      */
131     setOpacity: function (opacity) {
132         this._displayedOpacity = this._realOpacity = opacity;
133 
134         var parentOpacity = 255, locParent = this._parent;
135         if (locParent && locParent.RGBAProtocol && locParent.cascadeOpacity)
136             parentOpacity = locParent.getDisplayedOpacity();
137         this.updateDisplayedOpacity(parentOpacity);
138 
139         this._displayedColor.a = this._realColor.a = opacity;
140     },
141 
142     /**
143      * Update displayed opacity of Layer
144      * @param {Number} parentOpacity
145      */
146     updateDisplayedOpacity: function (parentOpacity) {
147         this._displayedOpacity = 0 | (this._realOpacity * parentOpacity / 255.0);
148 
149         if (this._cascadeOpacityEnabled) {
150             var locChildren = this._children;
151             for (var i = 0; i < locChildren.length; i++) {
152                 var selItem = locChildren[i];
153                 if (selItem && selItem.RGBAProtocol)
154                     selItem.updateDisplayedOpacity(this._displayedOpacity);
155             }
156         }
157     },
158 
159     /**
160      * whether or not it will set cascade opacity.
161      * @returns {boolean}
162      */
163     isCascadeOpacityEnabled: function () {
164         return this._cascadeOpacityEnabled;
165     },
166 
167     /**
168      * Enable or disable cascade opacity
169      * @param {boolean} cascadeOpacityEnabled
170      */
171     setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
172         if(this._cascadeOpacityEnabled === cascadeOpacityEnabled)
173             return;
174 
175         this._cascadeOpacityEnabled = cascadeOpacityEnabled;
176         if(cascadeOpacityEnabled)
177             this._enableCascadeOpacity();
178         else
179             this._disableCascadeOpacity();
180     },
181 
182     _enableCascadeOpacity:function(){
183         var parentOpacity = 255, locParent = this._parent;
184         if (locParent && locParent.RGBAProtocol && locParent.cascadeOpacity)
185             parentOpacity = locParent.getDisplayedOpacity();
186         this.updateDisplayedOpacity(parentOpacity);
187     },
188 
189     _disableCascadeOpacity:function(){
190         this._displayedOpacity = this._realOpacity;
191         var selChildren = this._children;
192         for(var i = 0; i< selChildren.length;i++){
193             var item = selChildren[i];
194             if(item && item.RGBAProtocol)
195                 item.updateDisplayedOpacity(255);
196         }
197     },
198 
199     /**
200      * Get the color of Layer
201      * @returns {cc.Color}
202      */
203     getColor: function () {
204         var locRealColor = this._realColor;
205         return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
206     },
207 
208     /**
209      * Get the displayed color of Layer
210      * @returns {cc.Color}
211      */
212     getDisplayedColor: function () {
213         var locDisplayedColor = this._displayedColor;
214         return cc.color(locDisplayedColor.r, locDisplayedColor.g, locDisplayedColor.b);
215     },
216 
217     /**
218      * Set the color of Layer
219      * @param {cc.Color} color
220      */
221     setColor: function (color) {
222         var locDisplayed = this._displayedColor, locRealColor = this._realColor;
223         locDisplayed.r = locRealColor.r = color.r;
224         locDisplayed.g = locRealColor.g = color.g;
225         locDisplayed.b = locRealColor.b = color.b;
226 
227         var parentColor, locParent = this._parent;
228         if (locParent && locParent.RGBAProtocol && locParent.cascadeColor)
229             parentColor = locParent.getDisplayedColor();
230         else
231             parentColor = cc.color.WHITE;
232         this.updateDisplayedColor(parentColor);
233 
234         if (color.a !== undefined && !color.a_undefined) {
235             this.setOpacity(color.a);
236         }
237     },
238 
239     /**
240      * update the displayed color of Node
241      * @param {cc.Color} parentColor
242      */
243     updateDisplayedColor: function (parentColor) {
244         var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
245         locDisplayedColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
246         locDisplayedColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
247         locDisplayedColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
248 
249         if (this._cascadeColorEnabled) {
250             var locChildren = this._children;
251             for (var i = 0; i < locChildren.length; i++) {
252                 var selItem = locChildren[i];
253                 if (selItem && selItem.RGBAProtocol)
254                     selItem.updateDisplayedColor(locDisplayedColor);
255             }
256         }
257     },
258 
259     /**
260      * whether or not it will set cascade color.
261      * @returns {boolean}
262      */
263     isCascadeColorEnabled: function () {
264         return this._cascadeColorEnabled;
265     },
266 
267     /**
268      * Enable or disable cascade color
269      * @param {boolean} cascadeColorEnabled
270      */
271     setCascadeColorEnabled: function (cascadeColorEnabled) {
272         if(this._cascadeColorEnabled === cascadeColorEnabled)
273             return;
274         this._cascadeColorEnabled = cascadeColorEnabled;
275         if(this._cascadeColorEnabled)
276             this._enableCascadeColor();
277         else
278             this._disableCascadeColor();
279     },
280 
281     _enableCascadeColor: function(){
282         var parentColor , locParent =  this._parent;
283         if (locParent && locParent.RGBAProtocol &&  locParent.cascadeColor)
284             parentColor = locParent.getDisplayedColor();
285         else
286             parentColor = cc.color.WHITE;
287         this.updateDisplayedColor(parentColor);
288     },
289 
290     _disableCascadeColor: function(){
291         var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
292         locDisplayedColor.r = locRealColor.r;
293         locDisplayedColor.g = locRealColor.g;
294         locDisplayedColor.b = locRealColor.b;
295 
296         var selChildren = this._children, whiteColor = cc.color.WHITE;
297         for(var i = 0; i< selChildren.length;i++){
298             var item = selChildren[i];
299             if(item && item.RGBAProtocol)
300                 item.updateDisplayedColor(whiteColor);
301         }
302     },
303 
304     /**
305      * add a child to layer
306      * @overried
307      * @param {cc.Node} child  A child node
308      * @param {Number} [zOrder=]  Z order for drawing priority. Please refer to setLocalZOrder(int)
309      * @param {Number} [tag=]  A integer to identify the node easily. Please refer to setTag(int)
310      */
311     addChild:function(child, zOrder, tag){
312         cc.Node.prototype.addChild.call(this, child, zOrder, tag);
313 
314         if(this._cascadeColorEnabled)
315             this._enableCascadeColor();
316         if(this._cascadeOpacityEnabled)
317             this._enableCascadeOpacity();
318     },
319 
320     setOpacityModifyRGB: function (bValue) {
321     },
322 
323     isOpacityModifyRGB: function () {
324         return false;
325     }
326 });
327 
328 window._p = cc.LayerRGBA.prototype;
329 // Extended properties
330 /** @expose */
331 _p.opacityModifyRGB;
332 cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
333 /** @expose */
334 _p.opacity;
335 cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
336 /** @expose */
337 _p.cascadeOpacity;
338 cc.defineGetterSetter(_p, "cascadeOpacity", _p.isCascadeOpacityEnabled, _p.setCascadeOpacityEnabled);
339 /** @expose */
340 _p.color;
341 cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
342 /** @expose */
343 _p.cascadeColor;
344 cc.defineGetterSetter(_p, "cascadeColor", _p.isCascadeColorEnabled, _p.setCascadeColorEnabled);
345 delete window._p;
346 
347 /**
348  * <p>
349  * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.       <br/>
350  *  All features from CCLayer are valid, plus the following new features:                   <br/>
351  * <ul><li>opacity</li>                                                                     <br/>
352  * <li>RGB colors</li></ul>                                                                 <br/>
353  * </p>
354  * @class
355  * @extends cc.LayerRGBA
356  */
357 cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{
358     _blendFunc:null,
359     _className:"LayerColor",
360 
361     /**
362      * blendFunc getter
363      * @return {cc.BlendFunc}
364      */
365     getBlendFunc:function () {
366         return this._blendFunc;
367     },
368 
369     /**
370      * change width and height in Points
371      * @deprecated
372      * @param {Number} w width
373      * @param {Number} h height
374      */
375     changeWidthAndHeight:function (w, h) {
376         this.width = w;
377 	    this.height = h;
378     },
379 
380     /**
381      * change width in Points
382      * @deprecated
383      * @param {Number} w width
384      */
385     changeWidth:function (w) {
386         this.width = w;
387     },
388 
389     /**
390      * change height in Points
391      * @deprecated
392      * @param {Number} h height
393      */
394     changeHeight:function (h) {
395         this.height = h;
396     },
397 
398     /**
399      * set OpacityModifyRGB of cc.LayerColor
400      * @param {Boolean}  value
401      */
402     setOpacityModifyRGB:function (value) {
403     },
404 
405     /**
406      * is OpacityModifyRGB
407      * @return {Boolean}
408      */
409     isOpacityModifyRGB:function () {
410         return false;
411     },
412 
413     setColor:function(color){
414         cc.LayerRGBA.prototype.setColor.call(this, color);
415         this._updateColor();
416     },
417 
418     setOpacity:function(opacity){
419         cc.LayerRGBA.prototype.setOpacity.call(this, opacity);
420         this._updateColor();
421     },
422 
423     _isLighterMode:false,
424     _squareVertices:null,
425     _squareColors:null,
426     _verticesFloat32Buffer:null,
427     _colorsUint8Buffer:null,
428     _squareVerticesAB:null,
429     _squareColorsAB:null,
430 
431 	/**
432 	 * @constructor
433 	 * @function
434 	 * @param {cc.Color} [color=]
435 	 * @param {Number} [width=]
436 	 * @param {Number} [height=]
437 	 */
438 	ctor: null,
439 
440     _ctorForCanvas: function (color, width, height) {
441         cc.LayerRGBA.prototype.ctor.call(this);
442         this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
443 
444 	    cc.LayerColor.prototype.init.call(this, color, width, height);
445     },
446 
447     _ctorForWebGL: function (color, width, height) {
448 	    this._squareVerticesAB = new ArrayBuffer(32);
449 	    this._squareColorsAB = new ArrayBuffer(16);
450 
451 	    var locSquareVerticesAB = this._squareVerticesAB, locSquareColorsAB = this._squareColorsAB;
452 	    var locVertex2FLen = cc.Vertex2F.BYTES_PER_ELEMENT, locColorLen = cc.Color.BYTES_PER_ELEMENT;
453 	    this._squareVertices = [new cc.Vertex2F(0, 0, locSquareVerticesAB, 0),
454 		    new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen),
455 		    new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 2),
456 		    new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 3)];
457 	    this._squareColors = [cc.color(0, 0, 0, 255, locSquareColorsAB, 0),
458 		    cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen),
459 		    cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen * 2),
460 		    cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen * 3)];
461 	    this._verticesFloat32Buffer = cc._renderContext.createBuffer();
462 	    this._colorsUint8Buffer = cc._renderContext.createBuffer();
463 
464 	    cc.LayerRGBA.prototype.ctor.call(this);
465         this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
466 
467 	    cc.LayerColor.prototype.init.call(this, color, width, height);
468     },
469 
470 	/**
471 	 * @param {cc.Color} [color=]
472 	 * @param {Number} [width=]
473 	 * @param {Number} [height=]
474 	 * @return {Boolean}
475 	 */
476 	init: function (color, width, height) {
477 		if(cc._renderType !== cc._RENDER_TYPE_CANVAS)
478 			this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR);
479 
480 		var winSize = cc.director.getWinSize();
481 		color = color ||  cc.color(0, 0, 0, 255);
482 		width = width === undefined ? winSize.width : width;
483 		height = height === undefined ? winSize.height : height;
484 		this.setContentSize(width, height);
485 
486 		var locDisplayedColor = this._displayedColor;
487 		locDisplayedColor.r = color.r;
488 		locDisplayedColor.g = color.g;
489 		locDisplayedColor.b = color.b;
490 
491 		var locRealColor = this._realColor;
492 		locRealColor.r = color.r;
493 		locRealColor.g = color.g;
494 		locRealColor.b = color.b;
495 
496 		this._displayedOpacity = color.a;
497 		this._realOpacity = color.a;
498 
499 		this._updateColor();
500 
501 		return true;
502 	},
503 
504     /**
505      * blendFunc setter
506      * @param {Number} src
507      * @param {Number} dst
508      */
509     setBlendFunc:function (src, dst) {
510         if (dst === undefined)
511             this._blendFunc = src;
512         else
513             this._blendFunc = {src:src, dst:dst};
514         if(cc._renderType === cc._RENDER_TYPE_CANVAS)
515             this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771));
516     },
517 
518     /**
519      * Sets the untransformed size of the LayerColor.
520      * @override
521      * @function
522      * @param {cc.Size|Number} size The untransformed size of the LayerColor or The untransformed size's width of the LayerColor.
523      * @param {Number} [height] The untransformed size's height of the LayerColor.
524      */
525     setContentSize:null,
526 
527     _setContentSizeForWebGL:function (size, height) {
528         var locSquareVertices = this._squareVertices;
529 
530         if (height === undefined) {
531 	        locSquareVertices[1].x = size.width;
532 	        locSquareVertices[2].y = size.height;
533 	        locSquareVertices[3].x = size.width;
534 	        locSquareVertices[3].y = size.height;
535         } else {
536 	        locSquareVertices[1].x = size;
537 	        locSquareVertices[2].y = height;
538 	        locSquareVertices[3].x = size;
539 	        locSquareVertices[3].y = height;
540         }
541 	    this._bindLayerVerticesBufferData();
542 	    cc.Layer.prototype.setContentSize.call(this, size, height);
543     },
544 
545 	_setWidthForWebGL:function (width) {
546 		var locSquareVertices = this._squareVertices;
547 		locSquareVertices[1].x = width;
548 		locSquareVertices[3].x = width;
549 		this._bindLayerVerticesBufferData();
550 		cc.Layer.prototype._setWidth.call(this, width);
551 	},
552 	_setHeightForWebGL:function (height) {
553 		var locSquareVertices = this._squareVertices;
554 		locSquareVertices[2].y = height;
555 		locSquareVertices[3].y = height;
556 		this._bindLayerVerticesBufferData();
557 		cc.Layer.prototype._setHeight.call(this, height);
558 	},
559 
560     _updateColor:null,
561 
562     _updateColorForCanvas:function () {
563     },
564 
565     _updateColorForWebGL:function () {
566         var locDisplayedColor = this._displayedColor;
567         var locDisplayedOpacity = this._displayedOpacity, locSquareColors = this._squareColors;
568         for (var i = 0; i < 4; i++) {
569             locSquareColors[i].r = locDisplayedColor.r;
570             locSquareColors[i].g = locDisplayedColor.g;
571             locSquareColors[i].b = locDisplayedColor.b;
572             locSquareColors[i].a = locDisplayedOpacity;
573         }
574         this._bindLayerColorsBufferData();
575     },
576 
577     updateDisplayedColor:function(parentColor){
578         cc.LayerRGBA.prototype.updateDisplayedColor.call(this, parentColor);
579         this._updateColor();
580     },
581 
582     updateDisplayedOpacity: function(parentOpacity){
583         cc.LayerRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity);
584         this._updateColor();
585     },
586 
587     _bindLayerVerticesBufferData:function () {
588         var glContext = cc._renderContext;
589         glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer);
590         glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW);
591     },
592 
593     _bindLayerColorsBufferData:function () {
594         var glContext = cc._renderContext;
595         glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer);
596         glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW);
597     },
598 
599     /**
600      * Renders the layer
601      * @function
602      * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx
603      */
604     draw:null,
605 
606     _drawForCanvas:function (ctx) {
607         var context = ctx || cc._renderContext;
608 
609         var locEGLViewer = cc.view;
610         var locDisplayedColor = this._displayedColor;
611 
612         context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + ","
613             + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")";
614         context.fillRect(0, 0, this.width * locEGLViewer.getScaleX(), -this.height * locEGLViewer.getScaleY());
615 
616         cc.g_NumberOfDraws++;
617     },
618 
619     _drawForWebGL:function (ctx) {
620         var context = ctx || cc._renderContext;
621 
622         cc.NODE_DRAW_SETUP(this);
623         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR);
624 
625         //
626         // Attributes
627         //
628         context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer);
629         context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, 0, 0);
630 
631         context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer);
632         context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, 0, 0);
633 
634         cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
635         context.drawArrays(context.TRIANGLE_STRIP, 0, 4);
636     }
637 });
638 
639 window._p = cc.LayerColor.prototype;
640 if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
641     _p.ctor = _p._ctorForWebGL;
642     _p.setContentSize = _p._setContentSizeForWebGL;
643 	_p._setWidth = _p._setWidthForWebGL;
644 	_p._setHeight = _p._setHeightForWebGL;
645     _p._updateColor = _p._updateColorForWebGL;
646     _p.draw = _p._drawForWebGL;
647 } else {
648     _p.ctor = _p._ctorForCanvas;
649     _p.setContentSize = cc.LayerRGBA.prototype.setContentSize;
650 	_p._setWidth = cc.LayerRGBA.prototype._setWidth;
651 	_p._setHeight = cc.LayerRGBA.prototype._setHeight;
652     _p._updateColor = _p._updateColorForCanvas;
653     _p.draw = _p._drawForCanvas;
654 }
655 
656 // Override properties
657 cc.defineGetterSetter(_p, "width", _p._getWidth, _p._setWidth);
658 cc.defineGetterSetter(_p, "height", _p._getHeight, _p._setHeight);
659 
660 delete window._p;
661 
662 /**
663  * creates a cc.Layer with color, width and height in Points
664  * @param {cc.Color} color
665  * @param {Number|Null} [width=]
666  * @param {Number|Null} [height=]
667  * @return {cc.LayerColor}
668  * @example
669  * // Example
670  * //Create a yellow color layer as background
671  * var yellowBackground = cc.LayerColor.create(cc.color(255,255,0,255));
672  * //If you didnt pass in width and height, it defaults to the same size as the canvas
673  *
674  * //create a yellow box, 200 by 200 in size
675  * var yellowBox = cc.LayerColor.create(cc.color(255,255,0,255), 200, 200);
676  */
677 cc.LayerColor.create = function (color, width, height) {
678 	return new cc.LayerColor(color, width, height);
679 };
680 
681 /**
682  * <p>
683  * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/>
684  *<br/>
685  * All features from cc.LayerColor are valid, plus the following new features:<br/>
686  * <ul><li>direction</li>
687  * <li>final color</li>
688  * <li>interpolation mode</li></ul>
689  * <br/>
690  * Color is interpolated between the startColor and endColor along the given<br/>
691  * vector (starting at the origin, ending at the terminus).  If no vector is<br/>
692  * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/>
693  * <br/>
694  * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/>
695  * non-cardinal vectors; a smooth gradient implying both end points will be still<br/>
696  * be drawn, however.<br/>
697  *<br/>
698  * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
699  * </p>
700  * @class
701  * @extends cc.LayerColor
702  *
703  * @property {cc.Color} startColor              - Start color of the color gradient
704  * @property {cc.Color} endColor                - End color of the color gradient
705  * @property {Number}   startOpacity            - Start opacity of the color gradient
706  * @property {Number}   endOpacity              - End opacity of the color gradient
707  * @property {Number}   vector                  - Direction vector of the color gradient
708  * @property {Number}   compresseInterpolation  - Indicate whether or not the interpolation will be compressed
709  */
710 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
711     _startColor:null,
712     _endColor:null,
713     _startOpacity:255,
714     _endOpacity:255,
715     _alongVector:null,
716     _compressedInterpolation:false,
717     _gradientStartPoint:null,
718     _gradientEndPoint:null,
719     _className:"LayerGradient",
720 
721 	/**
722 	 * @constructor
723 	 * @param {cc.Color} start starting color
724 	 * @param {cc.Color} end
725 	 * @param {cc.Point|Null} v
726 	 */
727     ctor:function (start, end, v) {
728 		this._startColor =  cc.color(0, 0, 0, 255);
729 		this._endColor =  cc.color(0, 0, 0, 255);
730 		this._alongVector = cc.p(0, -1);
731 		this._startOpacity = 255;
732 		this._endOpacity = 255;
733 		this._gradientStartPoint = cc.p(0, 0);
734 		this._gradientEndPoint = cc.p(0, 0);
735 
736         cc.LayerColor.prototype.ctor.call(this);
737 		cc.LayerGradient.prototype.init.call(this, start, end, v);
738     },
739 
740 	/**
741 	 * @param {cc.Color} start starting color
742 	 * @param {cc.Color} end
743 	 * @param {cc.Point|Null} v
744 	 * @return {Boolean}
745 	 */
746 	init:function (start, end, v) {
747 		start = start || cc.color(0,0,0,255);
748 		end = end || cc.color(0,0,0,255);
749 		v = v || cc.p(0, -1);
750 
751 		// Initializes the CCLayer with a gradient between start and end in the direction of v.
752 		var locStartColor = this._startColor, locEndColor = this._endColor;
753 		locStartColor.r = start.r;
754 		locStartColor.g = start.g;
755 		locStartColor.b = start.b;
756 		this._startOpacity = start.a;
757 
758 		locEndColor.r = end.r;
759 		locEndColor.g = end.g;
760 		locEndColor.b = end.b;
761 		this._endOpacity = end.a;
762 
763 		this._alongVector = v;
764 		this._compressedInterpolation = true;
765 		this._gradientStartPoint = cc.p(0, 0);
766 		this._gradientEndPoint = cc.p(0, 0);
767 
768 		cc.LayerColor.prototype.init.call(this,cc.color(start.r, start.g, start.b, 255));
769 		return true;
770 	},
771 
772     /**
773      * Sets the untransformed size of the LayerGradient.
774      * @override
775      * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient.
776      * @param {Number} [height] The untransformed size's height of the LayerGradient.
777      */
778     setContentSize:function(size, height){
779 	    cc.LayerColor.prototype.setContentSize.call(this,size, height);
780         this._updateColor();
781     },
782 
783 	_setWidth:function(width){
784 		cc.LayerColor.prototype._setWidth.call(this, width);
785 		this._updateColor();
786 	},
787 	_setHeight:function(height){
788 		cc.LayerColor.prototype._setHeight.call(this, height);
789 		this._updateColor();
790 	},
791 
792     /**
793      * get the starting color
794      * @return {cc.Color}
795      */
796     getStartColor:function () {
797         return this._realColor;
798     },
799 
800     /**
801      * set the starting color
802      * @param {cc.Color} color
803      * @example
804      * // Example
805      * myGradientLayer.setStartColor(cc.color(255,0,0));
806      * //set the starting gradient to red
807      */
808     setStartColor:function (color) {
809         this.color = color;
810     },
811 
812     /**
813      * set the end gradient color
814      * @param {cc.Color} color
815      * @example
816      * // Example
817      * myGradientLayer.setEndColor(cc.color(255,0,0));
818      * //set the ending gradient to red
819      */
820     setEndColor:function (color) {
821         this._endColor = color;
822         this._updateColor();
823     },
824 
825     /**
826      * get the end color
827      * @return {cc.Color}
828      */
829     getEndColor:function () {
830         return this._endColor;
831     },
832 
833     /**
834      * set starting gradient opacity
835      * @param {Number} o from 0 to 255, 0 is transparent
836      */
837     setStartOpacity:function (o) {
838         this._startOpacity = o;
839         this._updateColor();
840     },
841 
842     /**
843      * get the starting gradient opacity
844      * @return {Number}
845      */
846     getStartOpacity:function () {
847         return this._startOpacity;
848     },
849 
850     /**
851      * set the end gradient opacity
852      * @param {Number} o
853      */
854     setEndOpacity:function (o) {
855         this._endOpacity = o;
856         this._updateColor();
857     },
858 
859     /**
860      * get the end gradient opacity
861      * @return {Number}
862      */
863     getEndOpacity:function () {
864         return this._endOpacity;
865     },
866 
867     /**
868      * set vector
869      * @param {cc.Point} Var
870      */
871     setVector:function (Var) {
872         this._alongVector.x = Var.x;
873         this._alongVector.y = Var.y;
874         this._updateColor();
875     },
876 
877     /**
878      * @return {cc.Point}
879      */
880     getVector:function () {
881         return cc.p(this._alongVector.x, this._alongVector.y);
882     },
883 
884     /** is Compressed Interpolation
885      * @return {Boolean}
886      */
887     isCompressedInterpolation:function () {
888         return this._compressedInterpolation;
889     },
890 
891     /**
892      * @param {Boolean} compress
893      */
894     setCompressedInterpolation:function (compress) {
895         this._compressedInterpolation = compress;
896         this._updateColor();
897     },
898 
899     draw:function (ctx) {
900         if (cc._renderType === cc._RENDER_TYPE_WEBGL){
901             cc.LayerColor.prototype.draw.call(this, ctx);
902             return;
903         }
904 
905         var context = ctx || cc._renderContext;
906         if (this._isLighterMode)
907             context.globalCompositeOperation = 'lighter';
908 
909         context.save();
910         var locEGLViewer = cc.view, opacityf = this._displayedOpacity / 255.0;
911         var tWidth = this.width * locEGLViewer.getScaleX();
912         var tHeight = this.height * locEGLViewer.getScaleY();
913         var tGradient = context.createLinearGradient(this._gradientStartPoint.x, this._gradientStartPoint.y,
914             this._gradientEndPoint.x, this._gradientEndPoint.y);
915         var locDisplayedColor = this._displayedColor;
916         var locEndColor = this._endColor;
917         tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + ","
918             + Math.round(locDisplayedColor.b) + "," + (opacityf * (this._startOpacity / 255)).toFixed(4) + ")");
919         tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
920             + Math.round(locEndColor.b) + "," + (opacityf * (this._endOpacity / 255)).toFixed(4) + ")");
921         context.fillStyle = tGradient;
922         context.fillRect(0, 0, tWidth, -tHeight);
923 
924         if (this._rotation != 0)
925             context.rotate(this._rotationRadians);
926         context.restore();
927     },
928 
929     _updateColor:function () {
930         var locAlongVector = this._alongVector;
931         if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
932             var tWidth = this.width * 0.5;
933             var tHeight = this.height * 0.5;
934 
935             this._gradientStartPoint.x = tWidth * (-locAlongVector.x) + tWidth;
936             this._gradientStartPoint.y = tHeight * locAlongVector.y - tHeight;
937             this._gradientEndPoint.x = tWidth * locAlongVector.x + tWidth;
938             this._gradientEndPoint.y = tHeight * (-locAlongVector.y) - tHeight;
939         } else {
940             var h = cc.pLength(locAlongVector);
941             if (h === 0)
942                 return;
943 
944             var c = Math.sqrt(2.0);
945             var u = cc.p(locAlongVector.x / h, locAlongVector.y / h);
946 
947             // Compressed Interpolation mode
948             if (this._compressedInterpolation) {
949                 var h2 = 1 / ( Math.abs(u.x) + Math.abs(u.y) );
950                 u = cc.pMult(u, h2 * c);
951             }
952 
953             var opacityf = this._displayedOpacity / 255.0;
954             var locDisplayedColor = this._displayedColor, locEndColor = this._endColor;
955             var S = { r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: this._startOpacity * opacityf};
956             var E = {r: locEndColor.r, g: locEndColor.g, b: locEndColor.b, a: this._endOpacity * opacityf};
957 
958             // (-1, -1)
959             var locSquareColors = this._squareColors;
960             var locSquareColor0 = locSquareColors[0], locSquareColor1 = locSquareColors[1], locSquareColor2 = locSquareColors[2],locSquareColor3 = locSquareColors[3];
961             locSquareColor0.r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c))));
962             locSquareColor0.g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c))));
963             locSquareColor0.b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c))));
964             locSquareColor0.a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c))));
965             // (1, -1)
966             locSquareColor1.r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c))));
967             locSquareColor1.g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c))));
968             locSquareColor1.b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c))));
969             locSquareColor1.a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c))));
970             // (-1, 1)
971             locSquareColor2.r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c))));
972             locSquareColor2.g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c))));
973             locSquareColor2.b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c))));
974             locSquareColor2.a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c))));
975             // (1, 1)
976             locSquareColor3.r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c))));
977             locSquareColor3.g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c))));
978             locSquareColor3.b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c))));
979             locSquareColor3.a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c))));
980 
981             this._bindLayerColorsBufferData();
982         }
983     }
984 });
985 
986 window._p = cc.LayerGradient.prototype;
987 
988 // Extended properties
989 /** @expose */
990 _p.startColor;
991 cc.defineGetterSetter(_p, "startColor", _p.getStartColor, _p.setStartColor);
992 /** @expose */
993 _p.endColor;
994 cc.defineGetterSetter(_p, "endColor", _p.getEndColor, _p.setEndColor);
995 /** @expose */
996 _p.startOpacity;
997 cc.defineGetterSetter(_p, "startOpacity", _p.getStartOpacity, _p.setStartOpacity);
998 /** @expose */
999 _p.endOpacity;
1000 cc.defineGetterSetter(_p, "endOpacity", _p.getEndOpacity, _p.setEndOpacity);
1001 /** @expose */
1002 _p.vector;
1003 cc.defineGetterSetter(_p, "vector", _p.getVector, _p.setVector);
1004 
1005 delete window._p;
1006 
1007 /**
1008  * creates a gradient layer
1009  * @param {cc.Color} start starting color
1010  * @param {cc.Color} end ending color
1011  * @param {cc.Point|Null} v
1012  * @return {cc.LayerGradient}
1013  */
1014 cc.LayerGradient.create = function (start, end, v) {
1015     return new cc.LayerGradient(start, end, v);
1016 };
1017 
1018 /**
1019  * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/>
1020  * Features:<br/>
1021  *  <ul><li>- It supports one or more children</li>
1022  *  <li>- Only one children will be active a time</li></ul>
1023  *  @class
1024  *  @extends cc.Layer
1025  */
1026 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{
1027     _enabledLayer:0,
1028     _layers:null,
1029     _className:"LayerMultiplex",
1030 
1031 	/**
1032 	 * @constructor
1033 	 * @param {Array} layers an array of cc.Layer
1034 	 */
1035 	ctor: function (layers) {
1036 		cc.Layer.prototype.ctor.call(this);
1037 		layers && cc.LayerMultiplex.prototype.initWithLayers.call(this, layers);
1038 	},
1039 
1040     /**
1041      * @param {Array} layers an array of cc.Layer
1042      * @return {Boolean}
1043      */
1044     initWithLayers:function (layers) {
1045 	    if((layers.length > 0) && (layers[layers.length-1] == null))
1046 		    cc.log("parameters should not be ending with null in Javascript");
1047 
1048         this._layers = layers;
1049         this._enabledLayer = 0;
1050         this.addChild(this._layers[this._enabledLayer]);
1051         return true;
1052     },
1053 
1054     /**
1055      * switches to a certain layer indexed by n.<br/>
1056      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
1057      * @param {Number} n the layer index to switch to
1058      */
1059     switchTo:function (n) {
1060         if(n >= this._layers.length){
1061             cc.log("cc.LayerMultiplex.switchTo():Invalid index in MultiplexLayer switchTo message");
1062             return;
1063         }
1064 
1065         this.removeChild(this._layers[this._enabledLayer], true);
1066         this._enabledLayer = n;
1067         this.addChild(this._layers[n]);
1068     },
1069 
1070     /** release the current layer and switches to another layer indexed by n.<br/>
1071      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
1072      * @param {Number} n the layer index to switch to
1073      */
1074     switchToAndReleaseMe:function (n) {
1075         if(n >= this._layers.length){
1076             cc.log("cc.LayerMultiplex.switchToAndReleaseMe():Invalid index in MultiplexLayer switchTo message");
1077             return;
1078         }
1079 
1080         this.removeChild(this._layers[this._enabledLayer], true);
1081 
1082         //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]];
1083         this._layers[this._enabledLayer] = null;
1084         this._enabledLayer = n;
1085         this.addChild(this._layers[n]);
1086     },
1087 
1088     /**
1089      * @param {cc.Layer} layer
1090      */
1091     addLayer:function (layer) {
1092         if(!layer){
1093             cc.log("cc.Layer.addLayer(): layer should be non-null");
1094             return;
1095         }
1096         this._layers.push(layer);
1097     }
1098 });
1099 
1100 /**
1101  * creates a cc.LayerMultiplex with one or more layers using a variable argument list.
1102  * @return {cc.LayerMultiplex|Null}
1103  * @example
1104  * // Example
1105  * var multiLayer = cc.LayerMultiple.create(layer1, layer2, layer3);//any number of layers
1106  */
1107 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) {
1108     return new cc.LayerMultiplex(arguments);
1109 };
1110 
1111