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