1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies 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 bake feature: Baked layer can cache a static layer to improve performance
 29  * @class
 30  * @extends cc.Node
 31  */
 32 cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{
 33     _className: "Layer",
 34 
 35     /**
 36      * <p>Constructor of cc.Layer, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.</p>
 37      */
 38     ctor: function () {
 39         var nodep = cc.Node.prototype;
 40         nodep.ctor.call(this);
 41         this._ignoreAnchorPointForPosition = true;
 42         nodep.setAnchorPoint.call(this, 0.5, 0.5);
 43         nodep.setContentSize.call(this, cc.winSize);
 44     },
 45 
 46     /**
 47      * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer
 48      */
 49     init: function(){
 50         var _t = this;
 51         _t._ignoreAnchorPointForPosition = true;
 52         _t.setAnchorPoint(0.5, 0.5);
 53         _t.setContentSize(cc.winSize);
 54         _t._cascadeColorEnabled = false;
 55         _t._cascadeOpacityEnabled = false;
 56         return true;
 57     },
 58 
 59     /**
 60      * Sets the layer to cache all of children to a bake sprite, and draw itself by bake sprite. recommend using it in UI.<br/>
 61      * This is useful only in html5 engine
 62      * @function
 63      * @see cc.Layer#unbake
 64      */
 65     bake: function(){
 66         this._renderCmd.bake();
 67     },
 68 
 69     /**
 70      * Cancel the layer to cache all of children to a bake sprite.<br/>
 71      * This is useful only in html5 engine
 72      * @function
 73      * @see cc.Layer#bake
 74      */
 75     unbake: function(){
 76         this._renderCmd.unbake();
 77     },
 78 
 79     /**
 80      * Determines if the layer is baked.
 81      * @function
 82      * @returns {boolean}
 83      * @see cc.Layer#bake and cc.Layer#unbake
 84      */
 85     isBaked: function(){
 86         return this._renderCmd._isBaked;
 87     },
 88 
 89     addChild: function(child, localZOrder, tag){
 90         cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
 91         this._renderCmd._bakeForAddChild(child);
 92     },
 93 
 94     _createRenderCmd: function(){
 95         if (cc._renderType === cc._RENDER_TYPE_CANVAS)
 96             return new cc.Layer.CanvasRenderCmd(this);
 97         else
 98             return new cc.Layer.WebGLRenderCmd(this);
 99     }
100 });
101 
102 /**
103  * Creates a layer
104  * @deprecated since v3.0, please use the new construction instead
105  * @see cc.Layer
106  * @return {cc.Layer|Null}
107  */
108 cc.Layer.create = function () {
109     return new cc.Layer();
110 };
111 
112 /**
113  * <p>
114  * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.       <br/>
115  *  All features from CCLayer are valid, plus the following new features:                   <br/>
116  * - opacity                                                                     <br/>
117  * - RGB colors                                                                  </p>
118  * @class
119  * @extends cc.Layer
120  *
121  * @param {cc.Color} [color=] The color of the layer
122  * @param {Number} [width=] The width of the layer
123  * @param {Number} [height=] The height of the layer
124  *
125  * @example
126  * // Example
127  * //Create a yellow color layer as background
128  * var yellowBackground = new cc.LayerColor(cc.color(255,255,0,255));
129  * //If you didn't pass in width and height, it defaults to the same size as the canvas
130  *
131  * //create a yellow box, 200 by 200 in size
132  * var yellowBox = new cc.LayerColor(cc.color(255,255,0,255), 200, 200);
133  */
134 cc.LayerColor = cc.Layer.extend(/** @lends cc.LayerColor# */{
135     _blendFunc: null,
136     _className: "LayerColor",
137 
138     /**
139      * Returns the blend function
140      * @return {cc.BlendFunc}
141      */
142     getBlendFunc: function () {
143         return this._blendFunc;
144     },
145 
146     /**
147      * Changes width and height
148      * @deprecated since v3.0 please use setContentSize instead
149      * @see cc.Node#setContentSize
150      * @param {Number} w width
151      * @param {Number} h height
152      */
153     changeWidthAndHeight: function (w, h) {
154         this.width = w;
155         this.height = h;
156     },
157 
158     /**
159      * Changes width in Points
160      * @deprecated since v3.0 please use setContentSize instead
161      * @see cc.Node#setContentSize
162      * @param {Number} w width
163      */
164     changeWidth: function (w) {
165         this.width = w;
166     },
167 
168     /**
169      * change height in Points
170      * @deprecated since v3.0 please use setContentSize instead
171      * @see cc.Node#setContentSize
172      * @param {Number} h height
173      */
174     changeHeight: function (h) {
175         this.height = h;
176     },
177 
178     setOpacityModifyRGB: function (value) {
179     },
180 
181     isOpacityModifyRGB: function () {
182         return false;
183     },
184 
185     /**
186      * Constructor of cc.LayerColor
187      * @function
188      * @param {cc.Color} [color=]
189      * @param {Number} [width=]
190      * @param {Number} [height=]
191      */
192     ctor: function(color, width, height){
193         cc.Layer.prototype.ctor.call(this);
194         this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
195         cc.LayerColor.prototype.init.call(this, color, width, height);
196     },
197 
198     /**
199      * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer
200      * @param {cc.Color} [color=]
201      * @param {Number} [width=]
202      * @param {Number} [height=]
203      * @return {Boolean}
204      */
205     init: function (color, width, height) {
206         if (cc._renderType !== cc._RENDER_TYPE_CANVAS)
207             this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR);
208 
209         var winSize = cc.director.getWinSize();
210         color = color || cc.color(0, 0, 0, 255);
211         width = width === undefined ? winSize.width : width;
212         height = height === undefined ? winSize.height : height;
213 
214         var locRealColor = this._realColor;
215         locRealColor.r = color.r;
216         locRealColor.g = color.g;
217         locRealColor.b = color.b;
218         this._realOpacity = color.a;
219         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty);
220 
221         cc.LayerColor.prototype.setContentSize.call(this, width, height);
222         return true;
223     },
224 
225     /**
226      * Sets the blend func, you can pass either a cc.BlendFunc object or source and destination value separately
227      * @param {Number|cc.BlendFunc} src
228      * @param {Number} [dst]
229      */
230     setBlendFunc: function (src, dst) {
231         var locBlendFunc = this._blendFunc;
232         if (dst === undefined) {
233             locBlendFunc.src = src.src;
234             locBlendFunc.dst = src.dst;
235         } else {
236             locBlendFunc.src = src;
237             locBlendFunc.dst = dst;
238         }
239         this._renderCmd.updateBlendFunc(locBlendFunc);
240     },
241 
242     _setWidth: function(width){
243         cc.Node.prototype._setWidth.call(this, width);
244         this._renderCmd._updateSquareVerticesWidth(width);
245     },
246 
247     _setHeight: function(height){
248         cc.Node.prototype._setHeight.call(this, height);
249         this._renderCmd._updateSquareVerticesHeight(height);
250     },
251 
252     setContentSize: function(size, height){
253         cc.Layer.prototype.setContentSize.call(this, size, height);
254         this._renderCmd._updateSquareVertices(size, height);
255     },
256 
257     _createRenderCmd: function(){
258         if (cc._renderType === cc._RENDER_TYPE_CANVAS)
259             return new cc.LayerColor.CanvasRenderCmd(this);
260         else
261             return new cc.LayerColor.WebGLRenderCmd(this);
262     }
263 });
264 
265 /**
266  * Creates a cc.Layer with color, width and height in Points
267  * @deprecated since v3.0 please use the new construction instead
268  * @see cc.LayerColor
269  * @param {cc.Color} color
270  * @param {Number|Null} [width=]
271  * @param {Number|Null} [height=]
272  * @return {cc.LayerColor}
273  */
274 cc.LayerColor.create = function (color, width, height) {
275     return new cc.LayerColor(color, width, height);
276 };
277 
278 //LayerColor - Getter Setter
279 (function(){
280     var proto = cc.LayerColor.prototype;
281     cc.defineGetterSetter(proto, "width", proto._getWidth, proto._setWidth);
282     cc.defineGetterSetter(proto, "height", proto._getHeight, proto._setHeight);
283 })();
284 
285 /**
286  * <p>
287  * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.<br/>
288  *<br/>
289  * All features from cc.LayerColor are valid, plus the following new features:<br/>
290  * <ul><li>direction</li>
291  * <li>final color</li>
292  * <li>interpolation mode</li></ul>
293  * <br/>
294  * Color is interpolated between the startColor and endColor along the given<br/>
295  * vector (starting at the origin, ending at the terminus).  If no vector is<br/>
296  * supplied, it defaults to (0, -1) -- a fade from top to bottom.<br/>
297  * <br/>
298  * If 'compressedInterpolation' is disabled, you will not see either the start or end color for<br/>
299  * non-cardinal vectors; a smooth gradient implying both end points will be still<br/>
300  * be drawn, however.<br/>
301  *<br/>
302  * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
303  * </p>
304  * @class
305  * @extends cc.LayerColor
306  *
307  * @param {cc.Color} start Starting color
308  * @param {cc.Color} end Ending color
309  * @param {cc.Point} [v=cc.p(0, -1)] A vector defines the gradient direction, default direction is from top to bottom
310  *
311  * @property {cc.Color} startColor              - Start color of the color gradient
312  * @property {cc.Color} endColor                - End color of the color gradient
313  * @property {Number}   startOpacity            - Start opacity of the color gradient
314  * @property {Number}   endOpacity              - End opacity of the color gradient
315  * @property {Number}   vector                  - Direction vector of the color gradient
316  * @property {Number}   compressedInterpolation  - Indicate whether or not the interpolation will be compressed
317  */
318 cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
319     _endColor: null,
320     _startOpacity: 255,
321     _endOpacity: 255,
322     _alongVector: null,
323     _compressedInterpolation: false,
324     _className: "LayerGradient",
325     _colorStops: [],
326 
327     /**
328      * Constructor of cc.LayerGradient
329      * @param {cc.Color} start
330      * @param {cc.Color} end
331      * @param {cc.Point} [v=cc.p(0, -1)]
332      * @param {Array|Null} stops
333      *
334      * @example Using ColorStops argument:
335      * //startColor & endColor are for default and backward compatibility
336      * var layerGradient = new cc.LayerGradient(cc.color.RED, new cc.Color(255,0,0,0), cc.p(0, -1),
337      *                                          [{p:0, color: cc.color.RED},
338      *                                           {p:.5, color: new cc.Color(0,0,0,0)},
339      *                                           {p:1, color: cc.color.RED}]);
340      * //where p = A value between 0.0 and 1.0 that represents the position between start and end in a gradient
341      *
342      */
343     ctor: function (start, end, v, stops) {
344         cc.LayerColor.prototype.ctor.call(this);
345         this._endColor = cc.color(0, 0, 0, 255);
346         this._alongVector = cc.p(0, -1);
347         this._startOpacity = 255;
348         this._endOpacity = 255;
349 
350         if(stops && stops instanceof Array){
351             this._colorStops = stops;
352             stops.splice(0, 0, {p:0, color: start || cc.color.BLACK});
353             stops.push({p:1, color: end || cc.color.BLACK});
354         } else
355             this._colorStops = [{p:0, color: start || cc.color.BLACK}, {p:1, color: end || cc.color.BLACK}];
356 
357         cc.LayerGradient.prototype.init.call(this, start, end, v, stops);
358     },
359 
360     /**
361      * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer
362      * @param {cc.Color} start starting color
363      * @param {cc.Color} end
364      * @param {cc.Point|Null} v
365      * @param {Array|Null} stops
366      * @return {Boolean}
367      */
368     init: function (start, end, v, stops) {
369         start = start || cc.color(0, 0, 0, 255);
370         end = end || cc.color(0, 0, 0, 255);
371         v = v || cc.p(0, -1);
372         var _t = this;
373 
374         // Initializes the CCLayer with a gradient between start and end in the direction of v.
375         var locEndColor = _t._endColor;
376         _t._startOpacity = start.a;
377 
378         locEndColor.r = end.r;
379         locEndColor.g = end.g;
380         locEndColor.b = end.b;
381         _t._endOpacity = end.a;
382 
383         _t._alongVector = v;
384         _t._compressedInterpolation = true;
385 
386         cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255));
387         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty);
388         return true;
389     },
390 
391     /**
392      * Sets the untransformed size of the LayerGradient.
393      * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient.
394      * @param {Number} [height] The untransformed size's height of the LayerGradient.
395      */
396     setContentSize: function (size, height) {
397         cc.LayerColor.prototype.setContentSize.call(this, size, height);
398         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
399     },
400 
401     _setWidth: function (width) {
402         cc.LayerColor.prototype._setWidth.call(this, width);
403         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
404     },
405     _setHeight: function (height) {
406         cc.LayerColor.prototype._setHeight.call(this, height);
407         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
408     },
409 
410     /**
411      * Returns the starting color
412      * @return {cc.Color}
413      */
414     getStartColor: function () {
415         return cc.color(this._realColor);
416     },
417 
418     /**
419      * Sets the starting color
420      * @param {cc.Color} color
421      * @example
422      * // Example
423      * myGradientLayer.setStartColor(cc.color(255,0,0));
424      * //set the starting gradient to red
425      */
426     setStartColor: function (color) {
427         this.color = color;
428         //update the color stops
429         var stops = this._colorStops;
430         if(stops && stops.length > 0){
431             var selColor = stops[0].color;
432             selColor.r = color.r;
433             selColor.g = color.g;
434             selColor.b = color.b;
435         }
436     },
437 
438     /**
439      * Sets the end gradient color
440      * @param {cc.Color} color
441      * @example
442      * // Example
443      * myGradientLayer.setEndColor(cc.color(255,0,0));
444      * //set the ending gradient to red
445      */
446     setEndColor: function (color) {
447         var locColor = this._endColor;
448         locColor.r = color.r;
449         locColor.g = color.g;
450         locColor.b = color.b;
451         //update the color stops
452         var stops = this._colorStops;
453         if(stops && stops.length > 0){
454             var selColor = stops[stops.length -1].color;
455             selColor.r = color.r;
456             selColor.g = color.g;
457             selColor.b = color.b;
458         }
459         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
460     },
461 
462     /**
463      * Returns the end color
464      * @return {cc.Color}
465      */
466     getEndColor: function () {
467         return cc.color(this._endColor);
468     },
469 
470     /**
471      * Sets starting gradient opacity
472      * @param {Number} o from 0 to 255, 0 is transparent
473      */
474     setStartOpacity: function (o) {
475         this._startOpacity = o;
476         //update the color stops
477         var stops = this._colorStops;
478         if(stops && stops.length > 0)
479             stops[0].color.a = o;
480         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
481     },
482 
483     /**
484      * Returns the starting gradient opacity
485      * @return {Number}
486      */
487     getStartOpacity: function () {
488         return this._startOpacity;
489     },
490 
491     /**
492      * Sets the end gradient opacity
493      * @param {Number} o
494      */
495     setEndOpacity: function (o) {
496         this._endOpacity = o;
497         var stops = this._colorStops;
498         if(stops && stops.length > 0)
499             stops[stops.length -1].color.a = o;
500         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
501     },
502 
503     /**
504      * Returns the end gradient opacity
505      * @return {Number}
506      */
507     getEndOpacity: function () {
508         return this._endOpacity;
509     },
510 
511     /**
512      * Sets the direction vector of the gradient
513      * @param {cc.Point} Var
514      */
515     setVector: function (Var) {
516         this._alongVector.x = Var.x;
517         this._alongVector.y = Var.y;
518         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
519     },
520 
521     /**
522      * Returns the direction vector of the gradient
523      * @return {cc.Point}
524      */
525     getVector: function () {
526         return cc.p(this._alongVector.x, this._alongVector.y);
527     },
528 
529     /**
530      * Returns whether compressed interpolation is enabled
531      * @return {Boolean}
532      */
533     isCompressedInterpolation: function () {
534         return this._compressedInterpolation;
535     },
536 
537     /**
538      * Sets whether compressed interpolation is enabled
539      * @param {Boolean} compress
540      */
541     setCompressedInterpolation: function (compress) {
542         this._compressedInterpolation = compress;
543         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
544     },
545 
546     /**
547      * Return an array of Object representing a colorStop for the gradient, if no stops was specified
548      * start & endColor will be provided as default values
549      * @example
550      * [{p: 0, color: cc.color.RED},{p: 1, color: cc.color.RED},...]
551      * @returns {Array}
552      */
553     getColorStops: function(){
554         return this._colorStops;
555     },
556     /**
557      * Set the colorStops to create the gradient using multiple point & color
558      *
559      * @param colorStops
560      *
561      * @example
562      * //startColor & endColor are for default and backward compatibility
563      * var layerGradient = new cc.LayerGradient(cc.color.RED, new cc.Color(255,0,0,0), cc.p(0, -1));
564      * layerGradient.setColorStops([{p:0, color: cc.color.RED},
565      *                              {p:.5, color: new cc.Color(0,0,0,0)},
566      *                              {p:1, color: cc.color.RED}]);
567      * //where p = A value between 0.0 and 1.0 that represents the position between start and end in a gradient
568      *
569      */
570     setColorStops: function(colorStops){
571         this._colorStops = colorStops;
572         //todo need update  the start color and end color
573         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty);
574     },
575 
576     _createRenderCmd: function(){
577         if (cc._renderType === cc._RENDER_TYPE_CANVAS)
578             return new cc.LayerGradient.CanvasRenderCmd(this);
579         else
580             return new cc.LayerGradient.WebGLRenderCmd(this);
581     }
582 });
583 
584 /**
585  * Creates a gradient layer
586  * @deprecated since v3.0, please use the new construction instead
587  * @see cc.layerGradient
588  * @param {cc.Color} start starting color
589  * @param {cc.Color} end ending color
590  * @param {cc.Point|Null} v
591  * @param {Array|NULL} stops
592  * @return {cc.LayerGradient}
593  */
594 cc.LayerGradient.create = function (start, end, v, stops) {
595     return new cc.LayerGradient(start, end, v, stops);
596 };
597 //LayerGradient - Getter Setter
598 (function(){
599     var proto = cc.LayerGradient.prototype;
600     // Extended properties
601     /** @expose */
602     proto.startColor;
603     cc.defineGetterSetter(proto, "startColor", proto.getStartColor, proto.setStartColor);
604     /** @expose */
605     proto.endColor;
606     cc.defineGetterSetter(proto, "endColor", proto.getEndColor, proto.setEndColor);
607     /** @expose */
608     proto.startOpacity;
609     cc.defineGetterSetter(proto, "startOpacity", proto.getStartOpacity, proto.setStartOpacity);
610     /** @expose */
611     proto.endOpacity;
612     cc.defineGetterSetter(proto, "endOpacity", proto.getEndOpacity, proto.setEndOpacity);
613     /** @expose */
614     proto.vector;
615     cc.defineGetterSetter(proto, "vector", proto.getVector, proto.setVector);
616     /** @expose */
617     proto.colorStops;
618     cc.defineGetterSetter(proto, "colorStops", proto.getColorStops, proto.setColorStops);
619 })();
620 
621 /**
622  * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.<br/>
623  * Features:<br/>
624  *  <ul><li>- It supports one or more children</li>
625  *  <li>- Only one children will be active a time</li></ul>
626  * @class
627  * @extends cc.Layer
628  * @param {Array} layers an array of cc.Layer
629  * @example
630  * // Example
631  * var multiLayer = new cc.LayerMultiple(layer1, layer2, layer3);//any number of layers
632  */
633 cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{
634     _enabledLayer: 0,
635     _layers: null,
636     _className: "LayerMultiplex",
637 
638     /**
639      * Constructor of cc.LayerMultiplex
640      * @param {Array} layers an array of cc.Layer
641      */
642     ctor: function (layers) {
643         cc.Layer.prototype.ctor.call(this);
644         if (layers instanceof Array)
645             cc.LayerMultiplex.prototype.initWithLayers.call(this, layers);
646         else
647             cc.LayerMultiplex.prototype.initWithLayers.call(this, Array.prototype.slice.call(arguments));
648     },
649 
650     /**
651      * Initialization of the layer multiplex, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer multiplex
652      * @param {Array} layers an array of cc.Layer
653      * @return {Boolean}
654      */
655     initWithLayers: function (layers) {
656         if ((layers.length > 0) && (layers[layers.length - 1] == null))
657             cc.log(cc._LogInfos.LayerMultiplex_initWithLayers);
658 
659         this._layers = layers;
660         this._enabledLayer = 0;
661         this.addChild(this._layers[this._enabledLayer]);
662         return true;
663     },
664 
665     /**
666      * Switches to a certain layer indexed by n.<br/>
667      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
668      * @param {Number} n the layer index to switch to
669      */
670     switchTo: function (n) {
671         if (n >= this._layers.length) {
672             cc.log(cc._LogInfos.LayerMultiplex_switchTo);
673             return;
674         }
675 
676         this.removeChild(this._layers[this._enabledLayer], true);
677         this._enabledLayer = n;
678         this.addChild(this._layers[n]);
679     },
680 
681     /**
682      * Release the current layer and switches to another layer indexed by n.<br/>
683      * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
684      * @param {Number} n the layer index to switch to
685      */
686     switchToAndReleaseMe: function (n) {
687         if (n >= this._layers.length) {
688             cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe);
689             return;
690         }
691 
692         this.removeChild(this._layers[this._enabledLayer], true);
693 
694         //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]];
695         this._layers[this._enabledLayer] = null;
696         this._enabledLayer = n;
697         this.addChild(this._layers[n]);
698     },
699 
700     /**
701      * Add a layer to the multiplex layers list
702      * @param {cc.Layer} layer
703      */
704     addLayer: function (layer) {
705         if (!layer) {
706             cc.log(cc._LogInfos.LayerMultiplex_addLayer);
707             return;
708         }
709         this._layers.push(layer);
710     }
711 });
712 
713 /**
714  * Creates a cc.LayerMultiplex with one or more layers using a variable argument list.
715  * @deprecated since v3.0, please use new construction instead
716  * @see cc.LayerMultiplex
717  * @return {cc.LayerMultiplex|Null}
718  */
719 cc.LayerMultiplex.create = function (/*Multiple Arguments*/) {
720     return new cc.LayerMultiplex(Array.prototype.slice.call(arguments));
721 };