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 /**
 28  * Default Node tag
 29  * @constant
 30  * @type Number
 31  */
 32 cc.NODE_TAG_INVALID = -1;
 33 /**
 34  * Node on enter
 35  * @constant
 36  */
 37 cc.NODE_ON_ENTER = null;
 38 /**
 39  * Node on exit
 40  * @constant
 41  */
 42 cc.NODE_ON_EXIT = null;
 43 
 44 /**
 45  *  XXX: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered.
 46  * @type Number
 47  */
 48 cc.s_globalOrderOfArrival = 1;
 49 
 50 /** <p>cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.<br/>
 51  The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.<br/></p>
 52 
 53  <p>The main features of a cc.Node are: <br/>
 54  - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc) <br/>
 55  - They can schedule periodic callback (schedule, unschedule, etc) <br/>
 56  - They can execute actions (runAction, stopAction, etc) <br/></p>
 57 
 58  <p>Some cc.Node nodes provide extra functionality for them or their children.</p>
 59 
 60  <p>Subclassing a cc.Node usually means (one/all) of: <br/>
 61  - overriding init to initialize resources and schedule callbacks  <br/>
 62  - create callbacks to handle the advancement of time <br/>
 63  - overriding draw to render the node   <br/></p>
 64 
 65  <p>Features of cc.Node: <br/>
 66  - position  <br/>
 67  - scale (x, y) <br/>
 68  - rotation (in degrees, clockwise) <br/>
 69  - anchor point<br/>
 70  - size <br/>
 71  - visible<br/>
 72  - z-order <br/>
 73  - openGL z position <br/></P>
 74 
 75  <p> Default values: <br/>
 76  - rotation: 0 <br/>
 77  - position: (x=0,y=0) <br/>
 78  - scale: (x=1,y=1) <br/>
 79  - contentSize: (x=0,y=0)<br/>
 80  - anchorPoint: (x=0,y=0)<br/></p>
 81 
 82  <p> Limitations:<br/>
 83  - A cc.Node is a "void" object. It doesn't have a texture <br/></P>
 84 
 85  <p>Order in transformations with grid disabled <br/>
 86  -# The node will be translated (position)  <br/>
 87  -# The node will be rotated (rotation)<br/>
 88  -# The node will be scaled (scale)  <br/>
 89 
 90  <p>Order in transformations with grid enabled<br/>
 91  -# The node will be translated (position)<br/>
 92  -# The node will be rotated (rotation) <br/>
 93  -# The node will be scaled (scale) <br/>
 94  -# The grid will capture the screen <br/>
 95  -# The node will be moved according to the camera values (camera) <br/>
 96  -# The grid will render the captured screen <br/></P>
 97  * @class
 98  * @extends cc.Class
 99  * @example
100  * // example
101  * cc.Sprite = cc.Node.extend({});
102  * cc.Sprite.initWithImage = function(){
103  * };
104  */
105 cc.Node = cc.Class.extend(/** @lends cc.Node# */{
106     _zOrder:0,
107     _vertexZ:0.0,
108 
109     _rotationX:0,
110     _rotationY:0.0,
111     _scaleX:1.0,
112     _scaleY:1.0,
113     _position:null,
114     _skewX:0.0,
115     _skewY:0.0,
116     // children (lazy allocs),
117     _children:null,
118     // lazy alloc,
119     _visible:true,
120     _anchorPoint:null,
121     _anchorPointInPoints:null,
122     _contentSize:null,
123     _running:false,
124     _parent:null,
125     // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true
126     _ignoreAnchorPointForPosition:false,
127     _tag:cc.NODE_TAG_INVALID,
128     // userData is always inited as nil
129     _userData:null,
130     _userObject:null,
131     _transformDirty:true,
132     _inverseDirty:true,
133     _cacheDirty:true,
134     _transformGLDirty:null,
135     _transform:null,
136     _inverse:null,
137 
138     //since 2.0 api
139     _reorderChildDirty:false,
140     _shaderProgram:null,
141     _orderOfArrival:0,
142 
143     _actionManager:null,
144     _scheduler:null,
145 
146     _initializedNode:false,
147     _additionalTransformDirty:false,
148     _additionalTransform:null,
149     _componentContainer:null,
150     _isTransitionFinished:false,
151 
152     _rotationRadiansX:0,
153     _rotationRadiansY:0,
154 
155     _initNode:function () {
156         this._anchorPoint = cc.p(0, 0);
157         this._anchorPointInPoints = cc.p(0, 0);
158         this._contentSize = cc.size(0, 0);
159         this._position = cc.p(0, 0);
160         this._children = [];
161 
162         var director = cc.Director.getInstance();
163         this._actionManager = director.getActionManager();
164         this._scheduler = director.getScheduler();
165         this._initializedNode = true;
166         this._additionalTransform = cc.AffineTransformMakeIdentity();
167         this._componentContainer = new cc.ComponentContainer(this);
168     },
169 
170     /**
171      * Initializes the instance of cc.Node
172      * @returns {boolean} Whether the initialization was successful.
173      */
174     init:function () {
175         if (this._initializedNode === false)
176             this._initNode();
177         return true;
178     },
179 
180     /**
181      * @param {Array} array
182      * @param {cc.Node.StateCallbackType} callbackType
183      * @private
184      */
185     _arrayMakeObjectsPerformSelector:function (array, callbackType) {
186         if (!array || array.length === 0)
187             return;
188 
189         var i, len = array.length,node;
190         var nodeCallbackType = cc.Node.StateCallbackType;
191         switch (callbackType) {
192             case nodeCallbackType.onEnter:
193                 for (i = 0; i < len; i++) {
194                     node = array[i];
195                     if (node)
196                         node.onEnter();
197                 }
198                 break;
199             case nodeCallbackType.onExit:
200                 for (i = 0; i < len; i++) {
201                     node = array[i];
202                     if (node)
203                         node.onExit();
204                 }
205                 break;
206             case nodeCallbackType.onEnterTransitionDidFinish:
207                 for (i = 0; i < len; i++) {
208                     node = array[i];
209                     if (node)
210                         node.onEnterTransitionDidFinish();
211                 }
212                 break;
213             case nodeCallbackType.cleanup:
214                 for (i = 0; i < len; i++) {
215                     node = array[i];
216                     if (node)
217                         node.cleanup();
218                 }
219                 break;
220             case nodeCallbackType.updateTransform:
221                 for (i = 0; i < len; i++) {
222                     node = array[i];
223                     if (node)
224                         node.updateTransform();
225                 }
226                 break;
227             case nodeCallbackType.onExitTransitionDidStart:
228                 for (i = 0; i < len; i++) {
229                     node = array[i];
230                     if (node)
231                         node.onExitTransitionDidStart();
232                 }
233                 break;
234             case nodeCallbackType.sortAllChildren:
235                 for (i = 0; i < len; i++) {
236                     node = array[i];
237                     if (node)
238                         node.sortAllChildren();
239                 }
240                 break;
241             default :
242                 throw "Unknown callback function";
243                 break;
244         }
245     },
246 
247     /**
248      * set the dirty node
249      */
250     setNodeDirty:null,
251 
252     _setNodeDirtyForCanvas:function () {
253         this._setNodeDirtyForCache();
254         if(this._transformDirty === false)
255             this._transformDirty = this._inverseDirty = true;
256     },
257 
258     _setNodeDirtyForWebGL:function () {
259         if(this._transformDirty === false)
260             this._transformDirty = this._inverseDirty = true;
261     },
262 
263     /**
264      *  <p>get the skew degrees in X </br>
265      *  The X skew angle of the node in degrees.  <br/>
266      *  This angle describes the shear distortion in the X direction.<br/>
267      *  Thus, it is the angle between the Y axis and the left edge of the shape </br>
268      *  The default skewX angle is 0. Positive values distort the node in a CW direction.</br>
269      *  </p>
270      * @return {Number} The X skew angle of the node in degrees.
271      */
272     getSkewX:function () {
273         return this._skewX;
274     },
275 
276     /**
277      * <p>
278      *     Changes the X skew angle of the node in degrees.                                                    <br/>
279      *                                                                                                         <br/>
280      *      This angle describes the shear distortion in the X direction.                                      <br/>
281      *      Thus, it is the angle between the Y axis and the left edge of the shape                            <br/>
282      *      The default skewX angle is 0. Positive values distort the node in a CW direction.
283      * </p>
284      * @param {Number} newSkewX The X skew angle of the node in degrees.
285      */
286     setSkewX:function (newSkewX) {
287         this._skewX = newSkewX;
288         this.setNodeDirty();
289     },
290 
291     /**
292      * <p>get the skew degrees in Y               <br/>
293      * The Y skew angle of the node in degrees.                            <br/>
294      * This angle describes the shear distortion in the Y direction.       <br/>
295      * Thus, it is the angle between the X axis and the bottom edge of the shape       <br/>
296      * The default skewY angle is 0. Positive values distort the node in a CCW direction.    <br/>
297      * </p>
298      * @return {Number} The Y skew angle of the node in degrees.
299      */
300     getSkewY:function () {
301         return this._skewY;
302     },
303 
304     /**
305      * <p>
306      * Changes the Y skew angle of the node in degrees.
307      *
308      * This angle describes the shear distortion in the Y direction.
309      * Thus, it is the angle between the X axis and the bottom edge of the shape
310      * The default skewY angle is 0. Positive values distort the node in a CCW direction.
311      * </p>
312      * @param {Number} newSkewY  The Y skew angle of the node in degrees.
313      */
314     setSkewY:function (newSkewY) {
315         this._skewY = newSkewY;
316         this.setNodeDirty();
317     },
318 
319     /**
320      * zOrder getter
321      * @return {Number}
322      */
323     getZOrder:function () {
324         return this._zOrder;
325     },
326 
327     /**
328      * <p>
329      *     Sets the z order which stands for the drawing order                                                     <br/>
330      *                                                                                                             <br/>
331      *     This is an internal method. Don't call it outside the framework.                                        <br/>
332      *     The difference between setZOrder(int) and _setOrder(int) is:                                            <br/>
333      *        - _setZOrder(int) is a pure setter for m_nZOrder memeber variable                                    <br/>
334      *        - setZOrder(int) firstly changes m_nZOrder, then recorder this node in its parent's chilren array.
335      * </p>
336      * @param {Number} z
337      * @private
338      */
339     _setZOrder:function (z) {
340         this._zOrder = z;
341     },
342 
343     /**
344      * <p>
345      *     Sets the Z order which stands for the drawing order, and reorder this node in its parent's children array.     <br/>
346      *                                                                                                                    <br/>
347      *      The Z order of node is relative to its "brothers": children of the same parent.                               <br/>
348      *      It's nothing to do with OpenGL's z vertex. This one only affects the draw order of nodes in cocos2d.          <br/>
349      *      The larger number it is, the later this node will be drawn in each message loop.                              <br/>
350      *      Please refer to setVertexZ(float) for the difference.
351      * </p>
352      * @param {Number} z Z order of this node.
353      */
354     setZOrder:function (z) {
355         this._setZOrder(z);
356         if (this._parent)
357             this._parent.reorderChild(this, z);
358     },
359 
360     /**
361      * Gets WebGL Z vertex of this node.
362      * @return {Number} WebGL Z vertex of this node
363      */
364     getVertexZ:function () {
365         return this._vertexZ;
366     },
367 
368     /**
369      * <p>
370      *     Sets the real WebGL Z vertex.                                                                          <br/>
371      *                                                                                                            <br/>
372      *      Differences between openGL Z vertex and cocos2d Z order:                                              <br/>
373      *      - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children         <br/>
374      *      - OpenGL Z might require to set 2D projection                                                         <br/>
375      *      - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0            <br/>
376      *                                                                                                            <br/>
377      *      @warning Use it at your own risk since it might break the cocos2d parent-children z order
378      * </p>
379      * @param {Number} Var
380      */
381     setVertexZ:function (Var) {
382         this._vertexZ = Var;
383     },
384 
385     /**
386      * The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW.
387      * @return {Number} The rotation of the node in degrees.
388      */
389     getRotation:function () {
390         cc.Assert(this._rotationX == this._rotationY, "CCNode#rotation. RotationX != RotationY. Don't know which one to return");
391         return this._rotationX;
392     },
393 
394     /**
395      * <p>
396      *     Sets the rotation (angle) of the node in degrees.                                             <br/>
397      *                                                                                                   <br/>
398      *      0 is the default rotation angle.                                                             <br/>
399      *      Positive values rotate node clockwise, and negative values for anti-clockwise.
400      * </p>
401      * @param {Number} newRotation The rotation of the node in degrees.
402      */
403     setRotation:function (newRotation) {
404         this._rotationX = this._rotationY = newRotation;
405         this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180);
406         this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180);
407         this.setNodeDirty();
408     },
409 
410     /**
411      * The rotation (angle) of the node in degrees. 0 is the default rotation angle. <br/>
412      * Positive values rotate node CW. It only modifies the X rotation performing a horizontal rotational skew .
413      * (support only in WebGl rendering mode)
414      * @return {Number} The X rotation in degrees.
415      */
416     getRotationX:function () {
417         return this._rotationX;
418     },
419 
420     /**
421      * <p>
422      *     Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew.        <br/>
423      *                                                                                                            <br/>
424      *     0 is the default rotation angle.                                                                       <br/>
425      *     Positive values rotate node clockwise, and negative values for anti-clockwise.
426      * </p>
427      * @param {Number} rotationX The X rotation in degrees which performs a horizontal rotational skew.
428      */
429     setRotationX:function (rotationX) {
430         this._rotationX = rotationX;
431         this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180);
432         this.setNodeDirty();
433     },
434 
435     /**
436      * The rotation (angle) of the node in degrees. 0 is the default rotation angle.  <br/>
437      * Positive values rotate node CW. It only modifies the Y rotation performing a vertical rotational skew .
438      * @return {Number} The Y rotation in degrees.
439      */
440     getRotationY:function () {
441         return this._rotationY;
442     },
443 
444     /**
445      * <p>
446      *    Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew.         <br/>
447      *                                                                                                          <br/>
448      *      0 is the default rotation angle.                                                                    <br/>
449      *      Positive values rotate node clockwise, and negative values for anti-clockwise.
450      * </p>
451      * @param rotationY The Y rotation in degrees.
452      */
453     setRotationY:function (rotationY) {
454         this._rotationY = rotationY;
455         this._rotationRadiansY = this._rotationY * 0.017453292519943295;  //(Math.PI / 180);
456         this.setNodeDirty();
457     },
458 
459     /** Get the scale factor of the node.
460      * @warning: Assert when _scaleX != _scaleY.
461      * @return {Number}
462      */
463     getScale:function () {
464         cc.Assert(this._scaleX == this._scaleY, "cc.Node#scale. ScaleX != ScaleY. Don't know which one to return");
465         return this._scaleX;
466     },
467 
468     /**
469      * The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time.
470      * @param {Number} scale or scaleX value
471      * @param {Number} [scaleY=]
472      */
473     setScale:function (scale, scaleY) {
474         this._scaleX = scale;
475         this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale;
476         this.setNodeDirty();
477     },
478 
479     /**
480      * Returns the scale factor on X axis of this node
481      * @return {Number} The scale factor on X axis.
482      */
483     getScaleX:function () {
484         return this._scaleX;
485     },
486 
487     /**
488      * <p>
489      *     Changes the scale factor on X axis of this node                                   <br/>
490      *     The deafult value is 1.0 if you haven't changed it before
491      * </p>
492      * @param {Number} newScaleX The scale factor on X axis.
493      */
494     setScaleX:function (newScaleX) {
495         this._scaleX = newScaleX;
496         this.setNodeDirty();
497     },
498 
499     /**
500      * Returns the scale factor on Y axis of this node
501      * @return {Number} The scale factor on Y axis.
502      */
503     getScaleY:function () {
504         return this._scaleY;
505     },
506 
507     /**
508      * <p>
509      *     Changes the scale factor on Y axis of this node                                            <br/>
510      *     The Default value is 1.0 if you haven't changed it before.
511      * </p>
512      * @param {Number} newScaleY The scale factor on Y axis.
513      */
514     setScaleY:function (newScaleY) {
515         this._scaleY = newScaleY;
516         this.setNodeDirty();
517     },
518 
519     /**
520      * <p>
521      *     Changes the position (x,y) of the node in OpenGL coordinates
522      *     Usually we use ccp(x,y) to compose CCPoint object.
523      *     The original point (0,0) is at the left-bottom corner of screen.
524      *     and Passing two numbers (x,y) is much efficient than passing CCPoint object.
525      * </p>
526      * @param {cc.Point|Number} newPosOrxValue The position (x,y) of the node in coordinates or  X coordinate for position
527      * @param {Number} yValue Y coordinate for position
528      * @example
529      *    var size = cc.Director.getInstance().getWinSize();
530      *    node.setPosition( cc.p(size.width/2, size.height/2) )
531      */
532     setPosition:function (newPosOrxValue, yValue) {
533         var locPosition = this._position;
534         if (arguments.length == 2) {
535             locPosition.x = newPosOrxValue;
536             locPosition.y = yValue;
537         } else if (arguments.length == 1) {
538             locPosition.x = newPosOrxValue.x;
539             locPosition.y = newPosOrxValue.y;
540         }
541         this.setNodeDirty();
542     },
543 
544     /**
545      * <p>Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner. </p>
546      * @const
547      * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates
548      */
549     getPosition:function () {
550         return cc.p(this._position.x, this._position.y);
551     },
552 
553     /**
554      * @return {Number}
555      */
556     getPositionX:function () {
557         return this._position.x;
558     },
559 
560     /**
561      * @param {Number} x
562      */
563     setPositionX:function (x) {
564         this._position.x = x;
565         this.setNodeDirty();
566     },
567 
568     /**
569      * @return {Number}
570      */
571     getPositionY:function () {
572         return  this._position.y;
573     },
574 
575     /**
576      * @param {Number} y
577      */
578     setPositionY:function (y) {
579         this._position.y = y;
580         this.setNodeDirty();
581     },
582 
583     /**
584      * Get the amount of children.
585      * @return {Number} The amount of children.
586      */
587     getChildrenCount:function () {
588         return this._children.length;
589     },
590 
591     /**
592      * Return an array of children  <br/>
593      * Composing a "tree" structure is a very important feature of CCNode
594      * @return {Array} An array of children
595      * @example
596      *  //This sample code traverses all children nodes, and set theie position to (0,0)
597      *  var allChildren = parent.getChildren();
598      * for(var i = 0; i< allChildren.length; i++) {
599      *     allChildren[i].setPosition(0,0);
600      * }
601      */
602     getChildren:function () {
603         return this._children;
604     },
605 
606     /**
607      * Determines if the node is visible
608      * @see setVisible(bool)
609      * @return {Boolean} true if the node is visible, false if the node is hidden.
610      */
611     isVisible:function () {
612         return this._visible;
613     },
614 
615     /**
616      * Sets whether the node is visible <br/>
617      * The default value is true, a node is default to visible
618      * @param {Boolean} Var true if the node is visible, false if the node is hidden.
619      */
620     setVisible:function (Var) {
621         this._visible = Var;
622         this.setNodeDirty();
623     },
624 
625     /**
626      *  <p>anchorPoint is the point around which all transformations and positioning manipulations take place.<br/>
627      *  It's like a pin in the node where it is "attached" to its parent. <br/>
628      *  The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/>
629      *  But you can use values higher than (1,1) and lower than (0,0) too.  <br/>
630      *  The default anchorPoint is (0.5,0.5), so it starts in the center of the node. <br/></p>
631      *  @const
632      * @return {cc.Point}  The anchor point of node.
633      */
634     getAnchorPoint:function () {
635         return cc.p(this._anchorPoint.x, this._anchorPoint.y);
636     },
637 
638     /**
639      * <p>
640      *     Sets the anchor point in percent.                                                                                              <br/>
641      *                                                                                                                                    <br/>
642      *     anchorPoint is the point around which all transformations and positioning manipulations take place.                            <br/>
643      *     It's like a pin in the node where it is "attached" to its parent.                                                              <br/>
644      *     The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.     <br/>
645      *     But you can use values higher than (1,1) and lower than (0,0) too.                                                             <br/>
646      *     The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
647      * </p>
648      * @param {cc.Point} point The anchor point of node.
649      */
650     setAnchorPoint:function (point) {
651         var locAnchorPoint = this._anchorPoint;
652         if (!cc.pointEqualToPoint(point, locAnchorPoint)) {
653             locAnchorPoint.x =  point.x;
654             locAnchorPoint.y = point.y;
655             var locAPP = this._anchorPointInPoints, locSize = this._contentSize;
656             locAPP.x = locSize.width * point.x;
657             locAPP.y = locSize.height * point.y;
658             this.setNodeDirty();
659         }
660     },
661 
662     /**
663      *  The anchorPoint in absolute pixels.  <br/>
664      *  you can only read it. If you wish to modify it, use anchorPoint instead
665      *  @see getAnchorPoint()
666      *  @const
667      * @return {cc.Point} The anchor point in absolute pixels.
668      */
669     getAnchorPointInPoints:function () {
670         return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y);
671     },
672 
673     /**
674      * <p>The untransformed size of the node. <br/>
675      * The contentSize remains the same no matter the node is scaled or rotated.<br/>
676      * All nodes has a size. Layer and Scene has the same size of the screen. <br/></p>
677      * @const
678      * @return {cc.Size} The untransformed size of the node.
679      */
680     getContentSize:function () {
681         return cc.size(this._contentSize.width, this._contentSize.height);
682     },
683 
684     /**
685      * <p>
686      *     Sets the untransformed size of the node.                                             <br/>
687      *                                                                                          <br/>
688      *     The contentSize remains the same no matter the node is scaled or rotated.            <br/>
689      *     All nodes has a size. Layer and Scene has the same size of the screen.
690      * </p>
691      * @param {cc.Size} size The untransformed size of the node.
692      */
693     setContentSize:function (size) {
694         var locContentSize = this._contentSize;
695         if (!cc.sizeEqualToSize(size, locContentSize)) {
696             locContentSize.width = size.width;
697             locContentSize.height = size.height;
698             var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint;
699             locAPP.x = locContentSize.width * locAnchorPoint.x;
700             locAPP.y = locContentSize.height * locAnchorPoint.y;
701             this.setNodeDirty();
702         }
703     },
704 
705     /**
706      * <p>
707      *     Returns whether or not the node accepts event callbacks.                                     <br/>
708      *     Running means the node accept event callbacks like onEnter(), onExit(), update()
709      * </p>
710      * @return {Boolean} Whether or not the node is running.
711      */
712     isRunning:function () {
713         return this._running;
714     },
715 
716     /**
717      * Returns a pointer to the parent node
718      * @return {cc.Node} A pointer to the parnet node
719      */
720     getParent:function () {
721         return this._parent;
722     },
723 
724     /**
725      * Sets the parent node
726      * @param {cc.Node} Var A pointer to the parnet node
727      */
728     setParent:function (Var) {
729         this._parent = Var;
730     },
731 
732     /**
733      * Gets whether the anchor point will be (0,0) when you position this node.
734      * @see ignoreAnchorPointForPosition(bool)
735      * @return {Boolean} true if the anchor point will be (0,0) when you position this node.
736      */
737     isIgnoreAnchorPointForPosition:function () {
738         return this._ignoreAnchorPointForPosition;
739     },
740 
741     /**
742      * <p>
743      *     Sets whether the anchor point will be (0,0) when you position this node.                              <br/>
744      *                                                                                                           <br/>
745      *     This is an internal method, only used by CCLayer and CCScene. Don't call it outside framework.        <br/>
746      *     The default value is false, while in CCLayer and CCScene are true
747      * </p>
748      * @param {Boolean} newValue true if anchor point will be (0,0) when you position this node
749      */
750     ignoreAnchorPointForPosition:function (newValue) {
751         if (newValue != this._ignoreAnchorPointForPosition) {
752             this._ignoreAnchorPointForPosition = newValue;
753             this.setNodeDirty();
754         }
755     },
756 
757     /**
758      * Returns a tag that is used to identify the node easily.
759      *
760      * @return {Number} A interger that identifies the node.
761      * @example
762      *  //You can set tags to node then identify them easily.
763      * // set tags
764      * node1.setTag(TAG_PLAYER);
765      * node2.setTag(TAG_MONSTER);
766      * node3.setTag(TAG_BOSS);
767      * parent.addChild(node1);
768      * parent.addChild(node2);
769      * parent.addChild(node3);
770      * // identify by tags
771      * var allChildren = parent.getChildren();
772      * for(var i = 0; i < allChildren.length; i++){
773      *     switch(node.getTag()) {
774      *         case TAG_PLAYER:
775      *             break;
776      *         case TAG_MONSTER:
777      *             break;
778      *         case TAG_BOSS:
779      *             break;
780      *     }
781      * }
782      */
783     getTag:function () {
784         return this._tag;
785     },
786 
787     /**
788      * Changes the tag that is used to identify the node easily. <br/>
789      * Please refer to getTag for the sample code.
790      * @param {Number} Var A interger that indentifies the node.
791      */
792     setTag:function (Var) {
793         this._tag = Var;
794     },
795 
796     /**
797      * <p>
798      *     Returns a custom user data pointer                                                               <br/>
799      *     You can set everything in UserData pointer, a data block, a structure or an object.
800      * </p>
801      * @return {object}  A custom user data pointer
802      */
803     getUserData:function () {
804         return this._userData;
805     },
806 
807     /**
808      * <p>
809      *    Sets a custom user data pointer                                                                   <br/>
810      *    You can set everything in UserData pointer, a data block, a structure or an object, etc.
811      * </p>
812      * @warning Don't forget to relfease the memroy manually,especially before you change this data pointer, and before this node is autoreleased.
813      * @param {object} Var A custom user data
814      */
815     setUserData:function (Var) {
816         this._userData = Var;
817     },
818 
819     /**
820      * Returns a user assigned CCObject.                             <br/>
821      * Similar to userData, but instead of holding a void* it holds an id
822      * @return {object} A user assigned CCObject
823      */
824     getUserObject:function () {
825         return this._userObject;
826     },
827 
828     /**
829      * <p>
830      *      Returns a user assigned CCObject                                                                                       <br/>
831      *      Similar to UserData, but instead of holding a void* it holds an object.                                               <br/>
832      *      The UserObject will be retained once in this method, and the previous UserObject (if existed) will be relese.         <br/>
833      *      The UserObject will be released in CCNode's destructure.
834      * </p>
835      * @param {object} newValue A user assigned CCObject
836      */
837     setUserObject:function (newValue) {
838         if (this._userObject != newValue) {
839             this._userObject = newValue;
840         }
841     },
842 
843 
844     /**
845      * Returns the arrival order, indecates which children is added previously.
846      * @return {Number} The arrival order.
847      */
848     getOrderOfArrival:function () {
849         return this._orderOfArrival;
850     },
851 
852     /**
853      * <p>
854      *     Sets the arrival order when this node has a same ZOrder with other children.                             <br/>
855      *                                                                                                              <br/>
856      *     A node which called addChild subsequently will take a larger arrival order,                              <br/>
857      *     If two children have the same Z order, the child with larger arrival order will be drawn later.
858      * </p>
859      * @warning This method is used internally for zOrder sorting, don't change this manually
860      * @param {Number} Var  The arrival order.
861      */
862     setOrderOfArrival:function (Var) {
863         this._orderOfArrival = Var;
864     },
865 
866     /**
867      * <p>Gets the CCActionManager object that is used by all actions.<br/>
868      * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)</p>
869      * @see setActionManager()
870      * @return {cc.ActionManager} A CCActionManager object.
871      */
872     getActionManager:function () {
873         if (!this._actionManager) {
874             this._actionManager = cc.Director.getInstance().getActionManager();
875         }
876         return this._actionManager;
877     },
878 
879     /**
880      * <p>Sets the cc.ActionManager object that is used by all actions. </p>
881      * @warning If you set a new CCActionManager, then previously created actions will be removed.
882      * @param {cc.ActionManager} actionManager A CCActionManager object that is used by all actions.
883      */
884     setActionManager:function (actionManager) {
885         if (this._actionManager != actionManager) {
886             this.stopAllActions();
887             this._actionManager = actionManager;
888         }
889     },
890 
891     /**
892      * <p>
893      *   cc.Scheduler used to schedule all "updates" and timers.<br/>
894      *   IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed.
895      * </p>
896      * @return {cc.Scheduler} A CCScheduler object.
897      */
898     getScheduler:function () {
899         if (!this._scheduler) {
900             this._scheduler = cc.Director.getInstance().getScheduler();
901         }
902         return this._scheduler;
903     },
904 
905     /**
906      * <p>
907      *   Sets a CCScheduler object that is used to schedule all "updates" and timers.           <br/>
908      * </p>
909      * @warning If you set a new CCScheduler, then previously created timers/update are going to be removed.
910      * @param scheduler A cc.Shdeduler object that is used to schedule all "update" and timers.
911      */
912     setScheduler:function (scheduler) {
913         if (this._scheduler != scheduler) {
914             this.unscheduleAllCallbacks();
915             this._scheduler = scheduler;
916         }
917     },
918 
919     /**
920      * Returns a "local" axis aligned bounding box of the node. <br/>
921      * The returned box is relative only to its parent.
922      * @note This method returns a temporaty variable, so it can't returns const CCRect&
923      * @const
924      * @return {cc.Rect}
925      */
926     getBoundingBox:function () {
927         var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
928         return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform());
929     },
930 
931     /**
932      * Stops all running actions and schedulers
933      */
934     cleanup:function () {
935         // actions
936         this.stopAllActions();
937         this.unscheduleAllCallbacks();
938 
939         // timers
940         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup);
941     },
942 
943     /**
944      * Gets the description string. It makes debugging easier.
945      * @return {String}
946      */
947     description:function () {
948         return "<cc.Node | Tag =" + this._tag + ">";
949     },
950 
951     // composition: GET
952     /**
953      * Gets a child from the container given its tag
954      * @param {Number} aTag An identifier to find the child node.
955      * @return {cc.Node} a CCNode object whose tag equals to the input parameter
956      */
957     getChildByTag:function (aTag) {
958         //cc.Assert(aTag != cc.NODE_TAG_INVALID, "Invalid tag");
959         var __children = this._children;
960         if (__children != null) {
961             for (var i = 0; i < __children.length; i++) {
962                 var node = __children[i];
963                 if (node && node._tag == aTag)
964                     return node;
965             }
966         }
967         //throw "not found";
968         return null;
969     },
970     // composition: ADD
971 
972     /** <p>"add" logic MUST only be on this method <br/> </p>
973      *
974      * <p>If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.</p>
975      *
976      * @param {cc.Node} child  A child node
977      * @param {Number} [zOrder=]  Z order for drawing priority. Please refer to setZOrder(int)
978      * @param {Number} [tag=]  A interger to identify the node easily. Please refer to setTag(int)
979      */
980     addChild:function (child, zOrder, tag) {
981         if (child === this) {
982             console.warn('cc.Node.addChild: An Node can\'t be added as a child of itself.');
983             return;
984         }
985 
986         cc.Assert(child != null, "Argument must be non-nil");
987         if (child._parent !== null) {
988             cc.Assert(child._parent === null, "child already added. It can't be added again");
989             return;
990         }
991 
992         var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder;
993         child._tag = (tag != null) ? tag : child._tag;
994         this._insertChild(child, tmpzOrder);
995         child._parent = this;
996 
997         if (this._running) {
998             child.onEnter();
999             // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter
1000             if(this._isTransitionFinished)
1001                 child.onEnterTransitionDidFinish();
1002         }
1003     },
1004 
1005     // composition: REMOVE
1006     /**
1007      * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks. <br/>
1008      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1009      * If the node orphan, then nothing happens.
1010      * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise.
1011      * @see removeFromParentAndCleanup(bool)
1012      */
1013     removeFromParent:function (cleanup) {
1014         if (this._parent) {
1015             if (cleanup == null)
1016                 cleanup = true;
1017             this._parent.removeChild(this, cleanup);
1018         }
1019     },
1020 
1021     /**
1022      * Removes this node itself from its parent node.  <br/>
1023      * If the node orphan, then nothing happens.
1024      * @deprecated
1025      * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise.
1026      */
1027     removeFromParentAndCleanup:function (cleanup) {
1028         cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead");
1029         this.removeFromParent(cleanup);
1030     },
1031 
1032     /** <p>Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. </p>
1033      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1034      *<p> "remove" logic MUST only be on this method  <br/>
1035      * If a class wants to extend the 'removeChild' behavior it only needs <br/>
1036      * to override this method </p>
1037      *
1038      * @param {cc.Node} child  The child node which will be removed.
1039      * @param {Boolean|null} [cleanup=null]  true if all running actions and callbacks on the child node will be cleanup, false otherwise.
1040      */
1041     removeChild:function (child, cleanup) {
1042         // explicit nil handling
1043         if (this._children.length === 0)
1044             return;
1045 
1046         if (cleanup == null)
1047             cleanup = true;
1048         if (this._children.indexOf(child) > -1)
1049             this._detachChild(child, cleanup);
1050 
1051         this.setNodeDirty();
1052     },
1053 
1054     /**
1055      * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter.
1056      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1057      * @param {Number} tag An integer number that identifies a child node
1058      * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise.
1059      * @see removeChildByTag(int, bool)
1060      */
1061     removeChildByTag:function (tag, cleanup) {
1062         cc.Assert(tag != cc.NODE_TAG_INVALID, "Invalid tag");
1063 
1064         var child = this.getChildByTag(tag);
1065         if (child == null)
1066             cc.log("cocos2d: removeChildByTag(tag = " + tag + "): child not found!");
1067         else
1068             this.removeChild(child, cleanup);
1069     },
1070 
1071     /**
1072      * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
1073      * @deprecated
1074      * @param {Boolean | null } cleanup
1075      */
1076     removeAllChildrenWithCleanup:function (cleanup) {
1077         cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead");
1078         this.removeAllChildren(cleanup);
1079     },
1080 
1081     /**
1082      * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. <br/>
1083      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1084      * @param {Boolean | null } cleanup true if all running actions on all children nodes should be cleanup, false oterwise.
1085      */
1086     removeAllChildren:function (cleanup) {
1087         // not using detachChild improves speed here
1088         var __children = this._children;
1089         if (__children != null) {
1090             if (cleanup == null)
1091                 cleanup = true;
1092             for (var i = 0; i < __children.length; i++) {
1093                 var node = __children[i];
1094                 if (node) {
1095                     // IMPORTANT:
1096                     //  -1st do onExit
1097                     //  -2nd cleanup
1098                     if (this._running) {
1099                         node.onExitTransitionDidStart();
1100                         node.onExit();
1101                     }
1102                     if (cleanup)
1103                         node.cleanup();
1104                     // set parent nil at the end
1105                     node.setParent(null);
1106                 }
1107             }
1108             this._children.length = 0;
1109         }
1110     },
1111 
1112     /**
1113      * @param {cc.Node} child
1114      * @param {Boolean} doCleanup
1115      * @private
1116      */
1117     _detachChild:function (child, doCleanup) {
1118         // IMPORTANT:
1119         //  -1st do onExit
1120         //  -2nd cleanup
1121         if (this._running) {
1122             child.onExitTransitionDidStart();
1123             child.onExit();
1124         }
1125 
1126         // If you don't do cleanup, the child's actions will not get removed and the
1127         // its scheduledSelectors_ dict will not get released!
1128         if (doCleanup)
1129             child.cleanup();
1130 
1131         // set parent nil at the end
1132         child.setParent(null);
1133 
1134         cc.ArrayRemoveObject(this._children, child);
1135     },
1136 
1137     /** helper used by reorderChild & add
1138      * @param {cc.Node} child
1139      * @param {Number} z
1140      * @private
1141      */
1142     _insertChild:function (child, z) {
1143         this._reorderChildDirty = true;
1144         this._children.push(child);
1145         child._setZOrder(z);
1146     },
1147 
1148     /** Reorders a child according to a new z value. <br/>
1149      * The child MUST be already added.
1150      * @param {cc.Node} child An already added child node. It MUST be already added.
1151      * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int)
1152      */
1153     reorderChild:function (child, zOrder) {
1154         cc.Assert(child != null, "Child must be non-nil");
1155         this._reorderChildDirty = true;
1156         child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
1157         child._setZOrder(zOrder);
1158         this.setNodeDirty();
1159     },
1160 
1161     /**
1162      * <p>
1163      *     Sorts the children array once before drawing, instead of every time when a child is added or reordered.    <br/>
1164      *     This appraoch can improves the performance massively.
1165      * </p>
1166      * @note Don't call this manually unless a child added needs to be removed in the same frame
1167      */
1168     sortAllChildren:function () {
1169         if (this._reorderChildDirty) {
1170             var _children = this._children;
1171             var i, j, length = _children.length,tempChild;
1172 
1173             // insertion sort
1174             for (i = 0; i < length; i++) {
1175                 var tempItem = _children[i];
1176                 j = i - 1;
1177                 tempChild =  _children[j];
1178 
1179                 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
1180                 while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder ||
1181                     ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) {
1182                     _children[j + 1] = tempChild;
1183                     j = j - 1;
1184                     tempChild =  _children[j];
1185                 }
1186                 _children[j + 1] = tempItem;
1187             }
1188 
1189             //don't need to check children recursively, that's done in visit of each child
1190             this._reorderChildDirty = false;
1191         }
1192     },
1193 
1194     // draw
1195     /** <p>Override this method to draw your own node. <br/>
1196      * The following GL states will be enabled by default: <br/>
1197      - glEnableClientState(GL_VERTEX_ARRAY);  <br/>
1198      - glEnableClientState(GL_COLOR_ARRAY); <br/>
1199      - glEnableClientState(GL_TEXTURE_COORD_ARRAY); <br/>
1200      - glEnable(GL_TEXTURE_2D); </p>
1201 
1202      <p>AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE</p>
1203 
1204      <p>But if you enable any other GL state, you should disable it after drawing your node. </p>
1205      * @param {CanvasContext} ctx
1206      */
1207     draw:function (ctx) {
1208         //cc.Assert(0);
1209         // override me
1210         // Only use- this function to draw your staff.
1211         // DON'T draw your stuff outside this method
1212     },
1213 
1214     /** performs OpenGL view-matrix transformation of it's ancestors.<br/>
1215      * Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) <br/>
1216      * it's necessary to transform the ancestors again.
1217      */
1218     transformAncestors:function () {
1219         if (this._parent != null) {
1220             this._parent.transformAncestors();
1221             this._parent.transform();
1222         }
1223     },
1224 
1225     //scene managment
1226     /**
1227      * <p>
1228      *     Event callback that is invoked every time when CCNode enters the 'stage'.                                   <br/>
1229      *     If the CCNode enters the 'stage' with a transition, this event is called when the transition starts.        <br/>
1230      *     During onEnter you can't access a "sister/brother" node.                                                    <br/>
1231      *     If you override onEnter, you shall call its parent's one, e.g., CCNode::onEnter().
1232      * </p>
1233      */
1234     onEnter:function () {
1235         this._isTransitionFinished = false;
1236         this._running = true;//should be running before resumeSchedule
1237         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnter);
1238         this.resumeSchedulerAndActions();
1239     },
1240 
1241     /**
1242      * <p>
1243      *     Event callback that is invoked when the CCNode enters in the 'stage'.                                                        <br/>
1244      *     If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes.                       <br/>
1245      *     If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. CCNode::onEnterTransitionDidFinish()
1246      * </p>
1247      */
1248     onEnterTransitionDidFinish:function () {
1249         this._isTransitionFinished = true;
1250         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnterTransitionDidFinish);
1251     },
1252 
1253     /**
1254      * <p>callback that is called every time the cc.Node leaves the 'stage'.  <br/>
1255      * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. </p>
1256      */
1257     onExitTransitionDidStart:function () {
1258         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExitTransitionDidStart);
1259     },
1260 
1261     /**
1262      * <p>
1263      * callback that is called every time the cc.Node leaves the 'stage'.                                         <br/>
1264      * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/>
1265      * During onExit you can't access a sibling node.                                                             <br/>
1266      * If you override onExit, you shall call its parent's one, e.g., CCNode::onExit().
1267      * </p>
1268      */
1269     onExit:function () {
1270         this._running = false;
1271         this.pauseSchedulerAndActions();
1272         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExit);
1273         this._componentContainer.removeAll();
1274     },
1275 
1276     // actions
1277     /**
1278      * Executes an action, and returns the action that is executed.<br/>
1279      * The node becomes the action's target. Refer to CCAction::getTarget()
1280      * @warning Starting from v0.8 actions don't retain their target anymore.
1281      * @param {cc.Action} action
1282      * @return {cc.Action} An Action pointer
1283      */
1284     runAction:function (action) {
1285         cc.Assert(action != null, "Argument must be non-nil");
1286         this.getActionManager().addAction(action, this, !this._running);
1287         return action;
1288     },
1289 
1290     /**
1291      * Stops and removes all actions from the running action list .
1292      */
1293     stopAllActions:function () {
1294         this.getActionManager().removeAllActionsFromTarget(this);
1295     },
1296 
1297     /**
1298      * Stops and removes an action from the running action list.
1299      * @param {cc.Action} action An action object to be removed.
1300      */
1301     stopAction:function (action) {
1302         this.getActionManager().removeAction(action);
1303     },
1304 
1305     /**
1306      * Removes an action from the running action list by its tag.
1307      * @param {Number} tag A tag that indicates the action to be removed.
1308      */
1309     stopActionByTag:function (tag) {
1310         cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag");
1311         this.getActionManager().removeActionByTag(tag, this);
1312     },
1313 
1314     /**
1315      * Gets an action from the running action list by its tag.
1316      * @see setTag(int), getTag().
1317      * @param {Number} tag
1318      * @return {cc.Action} The action object with the given tag.
1319      */
1320     getActionByTag:function (tag) {
1321         cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag");
1322         return this.getActionManager().getActionByTag(tag, this);
1323     },
1324 
1325     /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).<br/>
1326      *    Composable actions are counted as 1 action. Example:<br/>
1327      *    If you are running 1 Sequence of 7 actions, it will return 1. <br/>
1328      *    If you are running 7 Sequences of 2 actions, it will return 7.
1329      * @return {Number} The number of actions that are running plus the ones that are schedule to run
1330      */
1331     numberOfRunningActions:function () {
1332         return this.getActionManager().numberOfRunningActionsInTarget(this);
1333     },
1334 
1335     // cc.Node - Callbacks
1336     // timers
1337     /**
1338      * schedules the "update" method.                                                                           <br/>
1339      * It will use the order number 0. This method will be called every frame.                                  <br/>
1340      * Scheduled methods with a lower order value will be called before the ones that have a higher order value.<br/>
1341      * Only one "update" method could be scheduled per node.
1342      */
1343     scheduleUpdate:function () {
1344         this.scheduleUpdateWithPriority(0);
1345     },
1346 
1347     /**
1348      * <p>
1349      * schedules the "update" callback function with a custom priority.
1350      * This callback function will be called every frame.<br/>
1351      * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.<br/>
1352      * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).<br/>
1353      * </p>
1354      * @param {Number} priority
1355      */
1356     scheduleUpdateWithPriority:function (priority) {
1357         this.getScheduler().scheduleUpdateForTarget(this, priority, !this._running);
1358     },
1359 
1360     /**
1361      * unschedules the "update" method.
1362      * @see scheduleUpdate();
1363      */
1364     unscheduleUpdate:function () {
1365         this.getScheduler().unscheduleUpdateForTarget(this);
1366     },
1367 
1368     /**
1369      * Schedules a custom selector.         <br/>
1370      * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.
1371      *
1372      * @param {function} callback_fn A function wrapped as a selector
1373      * @param {Number} interval  Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead.
1374      * @param {Number} repeat    The selector will be excuted (repeat + 1) times, you can use kCCRepeatForever for tick infinitely.
1375      * @param {Number} delay     The amount of time that the first tick will wait before execution.
1376      */
1377     schedule:function (callback_fn, interval, repeat, delay) {
1378         interval = interval || 0;
1379 
1380         cc.Assert(callback_fn, "Argument must be non-nil");
1381         cc.Assert(interval >= 0, "Argument must be positive");
1382 
1383         repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
1384         delay = delay || 0;
1385 
1386         this.getScheduler().scheduleCallbackForTarget(this, callback_fn, interval, repeat, delay, !this._running);
1387     },
1388 
1389     /**
1390      * Schedules a callback function that runs only once, with a delay of 0 or larger
1391      * @see schedule(SEL_SCHEDULE, float, unsigned int, float)
1392      * @param {function} callback_fn  A function wrapped as a selector
1393      * @param {Number} delay  The amount of time that the first tick will wait before execution.
1394      */
1395     scheduleOnce:function (callback_fn, delay) {
1396         this.schedule(callback_fn, 0.0, 0, delay);
1397     },
1398 
1399     /**
1400      * unschedules a custom callback function.
1401      * @see schedule(SEL_SCHEDULE, float, unsigned int, float)
1402      * @param {function} callback_fn  A function wrapped as a selector
1403      */
1404     unschedule:function (callback_fn) {
1405         // explicit nil handling
1406         if (!callback_fn)
1407             return;
1408 
1409         this.getScheduler().unscheduleCallbackForTarget(this, callback_fn);
1410     },
1411 
1412     /**
1413      * unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.<br/>
1414      * Actions are not affected by this method.
1415      */
1416     unscheduleAllCallbacks:function () {
1417         this.getScheduler().unscheduleAllCallbacksForTarget(this);
1418     },
1419 
1420     /**
1421      * Resumes all scheduled selectors and actions.<br/>
1422      * This method is called internally by onEnter
1423      */
1424     resumeSchedulerAndActions:function () {
1425         this.getScheduler().resumeTarget(this);
1426         this.getActionManager().resumeTarget(this);
1427     },
1428 
1429     /**
1430      * Pauses all scheduled selectors and actions.<br/>
1431      * This method is called internally by onExit
1432      */
1433     pauseSchedulerAndActions:function () {
1434         this.getScheduler().pauseTarget(this);
1435         this.getActionManager().pauseTarget(this);
1436     },
1437 
1438     /**
1439      *<p>  Sets the additional transform.<br/>
1440      *  The additional transform will be concatenated at the end of nodeToParentTransform.<br/>
1441      *  It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).<br/>
1442      *  </p>
1443      *  @example
1444      * // create a batchNode
1445      * var batch= cc.SpriteBatchNode.create("Icon-114.png");
1446      * this.addChild(batch);
1447      *
1448      * // create two sprites, spriteA will be added to batchNode, they are using different textures.
1449      * var spriteA = cc.Sprite.createWithTexture(batch->getTexture());
1450      * var spriteB = cc.Sprite.create("Icon-72.png");
1451      *
1452      * batch.addChild(spriteA);
1453      *
1454      * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer.
1455      * // But we want to simulate `parent-child` relationship for these two node.
1456      * this.addChild(spriteB);
1457      *
1458      * //position
1459      * spriteA.setPosition(ccp(200, 200));
1460      *
1461      * // Gets the spriteA's transform.
1462      * var t = spriteA.nodeToParentTransform();
1463      *
1464      * // Sets the additional transform to spriteB, spriteB's postion will based on its pseudo parent i.e. spriteA.
1465      * spriteB.setAdditionalTransform(t);
1466      *
1467      * //scale
1468      * spriteA.setScale(2);
1469      *
1470      * // Gets the spriteA's transform.
1471      * t = spriteA.nodeToParentTransform();
1472      *
1473      * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA.
1474      * spriteB.setAdditionalTransform(t);
1475      *
1476      * //rotation
1477      * spriteA.setRotation(20);
1478      *
1479      * // Gets the spriteA's transform.
1480      * t = spriteA.nodeToParentTransform();
1481      *
1482      * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA.
1483      * spriteB.setAdditionalTransform(t);
1484      */
1485     setAdditionalTransform:function (additionalTransform) {
1486         this._additionalTransform = additionalTransform;
1487         this._transformDirty = true;
1488         this._additionalTransformDirty = true;
1489     },
1490 
1491     /**
1492      * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.<br/>
1493      * The matrix is in Pixels.
1494      * @return {cc.AffineTransform}
1495      */
1496     parentToNodeTransform:function () {
1497         if (this._inverseDirty) {
1498             this._inverse = cc.AffineTransformInvert(this.nodeToParentTransform());
1499             this._inverseDirty = false;
1500         }
1501         return this._inverse;
1502     },
1503 
1504     /**
1505      *  Returns the world affine transform matrix. The matrix is in Pixels.
1506      * @return {cc.AffineTransform}
1507      */
1508     nodeToWorldTransform:function () {
1509         var t = this.nodeToParentTransform();
1510         for (var p = this._parent; p != null; p = p.getParent())
1511             t = cc.AffineTransformConcat(t, p.nodeToParentTransform());
1512         return t;
1513     },
1514 
1515     /**
1516      * Returns the inverse world affine transform matrix. The matrix is in Pixels.
1517      * @return {cc.AffineTransform}
1518      */
1519     worldToNodeTransform:function () {
1520         return cc.AffineTransformInvert(this.nodeToWorldTransform());
1521     },
1522 
1523     /**
1524      * Converts a Point to node (local) space coordinates. The result is in Points.
1525      * @param {cc.Point} worldPoint
1526      * @return {cc.Point}
1527      */
1528     convertToNodeSpace:function (worldPoint) {
1529         return cc.PointApplyAffineTransform(worldPoint, this.worldToNodeTransform());
1530     },
1531 
1532     /**
1533      * Converts a Point to world space coordinates. The result is in Points.
1534      * @param {cc.Point} nodePoint
1535      * @return {cc.Point}
1536      */
1537     convertToWorldSpace:function (nodePoint) {
1538         return cc.PointApplyAffineTransform(nodePoint, this.nodeToWorldTransform());
1539     },
1540 
1541     /**
1542      * Converts a Point to node (local) space coordinates. The result is in Points.<br/>
1543      * treating the returned/received node point as anchor relative.
1544      * @param {cc.Point} worldPoint
1545      * @return {cc.Point}
1546      */
1547     convertToNodeSpaceAR:function (worldPoint) {
1548         return cc.pSub(this.convertToNodeSpace(worldPoint), this._anchorPointInPoints);
1549     },
1550 
1551     /**
1552      * Converts a local Point to world space coordinates.The result is in Points.<br/>
1553      * treating the returned/received node point as anchor relative.
1554      * @param {cc.Point} nodePoint
1555      * @return {cc.Point}
1556      */
1557     convertToWorldSpaceAR:function (nodePoint) {
1558         var pt = cc.pAdd(nodePoint, this._anchorPointInPoints);
1559         return this.convertToWorldSpace(pt);
1560     },
1561 
1562     _convertToWindowSpace:function (nodePoint) {
1563         var worldPoint = this.convertToWorldSpace(nodePoint);
1564         return cc.Director.getInstance().convertToUI(worldPoint);
1565     },
1566 
1567     /** convenience methods which take a cc.Touch instead of cc.Point
1568      * @param {cc.Touch} touch
1569      * @return {cc.Point}
1570      */
1571     convertTouchToNodeSpace:function (touch) {
1572         var point = touch.getLocation();
1573         //TODO This point needn't convert to GL in HTML5
1574         //point = cc.Director.getInstance().convertToGL(point);
1575         return this.convertToNodeSpace(point);
1576     },
1577 
1578     /**
1579      * converts a cc.Touch (world coordinates) into a local coordiante. This method is AR (Anchor Relative).
1580      * @param {cc.Touch}touch
1581      * @return {cc.Point}
1582      */
1583     convertTouchToNodeSpaceAR:function (touch) {
1584         var point = touch.getLocation();
1585         point = cc.Director.getInstance().convertToGL(point);
1586         return this.convertToNodeSpaceAR(point);
1587     },
1588 
1589     /**
1590      * Update will be called automatically every frame if "scheduleUpdate" is called, and the node is "live" <br/>
1591      * (override me)
1592      * @param {Number} dt deltaTime
1593      */
1594     update:function (dt) {
1595         if(this._componentContainer && !this._componentContainer.isEmpty())
1596             this._componentContainer.visit(dt);
1597     },
1598 
1599     /**
1600      * <p>
1601      * Calls children's updateTransform() method recursively.                                        <br/>
1602      *                                                                                               <br/>
1603      * This method is moved from CCSprite, so it's no longer specific to CCSprite.                   <br/>
1604      * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode.            <br/>
1605      * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before.
1606      * </p>
1607      */
1608     updateTransform:function () {
1609         // Recursively iterate over children
1610         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
1611     },
1612 
1613     /**
1614      * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
1615      * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
1616      * This is a hack, and should be removed once JSB fixes the retain/release bug
1617      */
1618     retain:function () {
1619     },
1620     release:function () {
1621     },
1622 
1623     /**
1624      * gets a component by its name
1625      * @param {String} name
1626      * @return {cc.Component} gets a component by its name
1627      */
1628     getComponent:function(name){
1629         return this._componentContainer.getComponent(name);
1630     },
1631 
1632     /**
1633      * adds a component
1634      * @param {cc.Component} component
1635      */
1636     addComponent:function(component){
1637         this._componentContainer.add(component);
1638     },
1639 
1640     /**
1641      * removes a component by its name
1642      * @param {String} name
1643      */
1644     removeComponent:function(name){
1645         return this._componentContainer.remove(name);
1646     },
1647 
1648     /**
1649      * removes all components
1650      */
1651     removeAllComponents:function(){
1652         this._componentContainer.removeAll();
1653     },
1654 
1655     _transform4x4:null,
1656     _stackMatrix:null,
1657     _glServerState:null,
1658     _camera:null,
1659     _grid:null,
1660 
1661     /**
1662      * Constructor
1663      */
1664     ctor: null,
1665 
1666     _ctorForCanvas: function () {
1667         this._initNode();
1668     },
1669 
1670     _ctorForWebGL: function () {
1671         this._initNode();
1672 
1673         //WebGL
1674         var mat4 = new cc.kmMat4();
1675         mat4.mat[2] = mat4.mat[3] = mat4.mat[6] = mat4.mat[7] = mat4.mat[8] = mat4.mat[9] = mat4.mat[11] = mat4.mat[14] = 0.0;
1676         mat4.mat[10] = mat4.mat[15] = 1.0;
1677         this._transform4x4 = mat4;
1678         this._glServerState = 0;
1679         this._stackMatrix = new cc.kmMat4();
1680     },
1681 
1682     /**
1683      * recursive method that visit its children and draw them
1684      * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx
1685      */
1686     visit:null,
1687 
1688     _visitForCanvas:function (ctx) {
1689         // quick return if not visible
1690         if (!this._visible)
1691             return;
1692 
1693         //visit for canvas
1694         var context = ctx || cc.renderContext, i;
1695         var children = this._children,child;
1696         context.save();
1697         this.transform(context);
1698         var len = children.length;
1699         if (len > 0) {
1700             this.sortAllChildren();
1701             // draw children zOrder < 0
1702             for (i = 0; i < len; i++) {
1703                 child = children[i];
1704                 if (child._zOrder < 0)
1705                     child.visit(context);
1706                 else
1707                     break;
1708             }
1709             this.draw(context);
1710             for (; i < len; i++) {
1711                 children[i].visit(context);
1712             }
1713         } else
1714             this.draw(context);
1715 
1716         this._orderOfArrival = 0;
1717         context.restore();
1718     },
1719 
1720     _visitForWebGL: function(){
1721         // quick return if not visible
1722         if (!this._visible)
1723             return;
1724         var context = cc.renderContext, i, currentStack = cc.current_stack;
1725 
1726         //cc.kmGLPushMatrixWitMat4(this._stackMatrix);
1727         //optimize performance for javascript
1728         currentStack.stack.push(currentStack.top);
1729         cc.kmMat4Assign(this._stackMatrix, currentStack.top);
1730         currentStack.top = this._stackMatrix;
1731 
1732         var locGrid = this._grid;
1733         if (locGrid && locGrid._active)
1734             locGrid.beforeDraw();
1735 
1736         this.transform();
1737 
1738         var locChildren = this._children;
1739         if (locChildren && locChildren.length > 0) {
1740             var childLen = locChildren.length;
1741             this.sortAllChildren();
1742             // draw children zOrder < 0
1743             for (i = 0; i < childLen; i++) {
1744                 if (locChildren[i] && locChildren[i]._zOrder < 0)
1745                     locChildren[i].visit();
1746                 else
1747                     break;
1748             }
1749             this.draw(context);
1750             // draw children zOrder >= 0
1751             for (; i < childLen; i++) {
1752                 if (locChildren[i]) {
1753                     locChildren[i].visit();
1754                 }
1755             }
1756         } else
1757             this.draw(context);
1758 
1759         this._orderOfArrival = 0;
1760         if (locGrid && locGrid._active)
1761             locGrid.afterDraw(this);
1762 
1763         //cc.kmGLPopMatrix();
1764         //optimize performance for javascript
1765         currentStack.top = currentStack.stack.pop();
1766     },
1767 
1768     /**
1769      * Performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes.
1770      */
1771     transform:null,
1772 
1773     _transformForCanvas: function (ctx) {
1774         // transform for canvas
1775         var context = ctx || cc.renderContext;
1776         var t = this.nodeToParentTransform();
1777         context.transform(t.a, t.c, t.b, t.d, t.tx, -t.ty);
1778     },
1779 
1780     _transformForWebGL: function () {
1781         //optimize performance for javascript
1782         var t4x4 = this._transform4x4,  topMat4 = cc.current_stack.top;
1783 
1784         // Convert 3x3 into 4x4 matrix
1785         //cc.CGAffineToGL(this.nodeToParentTransform(), this._transform4x4.mat);
1786         var trans = this.nodeToParentTransform();
1787         var t4x4Mat = t4x4.mat;
1788         t4x4Mat[0] = trans.a;
1789         t4x4Mat[4] = trans.c;
1790         t4x4Mat[12] = trans.tx;
1791         t4x4Mat[1] = trans.b;
1792         t4x4Mat[5] = trans.d;
1793         t4x4Mat[13] = trans.ty;
1794 
1795         // Update Z vertex manually
1796         //this._transform4x4.mat[14] = this._vertexZ;
1797         t4x4Mat[14] = this._vertexZ;
1798 
1799         //optimize performance for Javascript
1800         cc.kmMat4Multiply(topMat4, topMat4, t4x4); // = cc.kmGLMultMatrix(this._transform4x4);
1801 
1802         // XXX: Expensive calls. Camera should be integrated into the cached affine matrix
1803         if (this._camera != null && !(this._grid != null && this._grid.isActive())) {
1804             var apx = this._anchorPointInPoints.x, apy = this._anchorPointInPoints.y;
1805             var translate = (apx !== 0.0 || apy !== 0.0);
1806             if (translate){
1807                 cc.kmGLTranslatef(cc.RENDER_IN_SUBPIXEL(apx), cc.RENDER_IN_SUBPIXEL(apy), 0);
1808                 this._camera.locate();
1809                 cc.kmGLTranslatef(cc.RENDER_IN_SUBPIXEL(-apx), cc.RENDER_IN_SUBPIXEL(-apy), 0);
1810             } else {
1811                 this._camera.locate();
1812             }
1813         }
1814     },
1815 
1816     /** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/>
1817      * The matrix is in Pixels.
1818      * @return {cc.AffineTransform}
1819      */
1820     nodeToParentTransform: null,
1821 
1822     _nodeToParentTransformForCanvas:function () {
1823         if (!this._transform)
1824             this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0};
1825         if (this._transformDirty) {
1826             var t = this._transform;// quick reference
1827             // base position
1828             t.tx = this._position.x;
1829             t.ty = this._position.y;
1830 
1831             // rotation Cos and Sin
1832             var Cos = 1, Sin = 0;
1833             if (this._rotationX) {
1834                 Cos = Math.cos(this._rotationRadiansX);
1835                 Sin = Math.sin(this._rotationRadiansX);
1836             }
1837 
1838             // base abcd
1839             t.a = t.d = Cos;
1840             t.b = -Sin;
1841             t.c = Sin;
1842 
1843             var lScaleX = this._scaleX, lScaleY = this._scaleY;
1844             var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y;
1845 
1846             // Firefox on Vista and XP crashes
1847             // GPU thread in case of scale(0.0, 0.0)
1848             var sx = (lScaleX < 0.000001 && lScaleX > -0.000001)?  0.000001 : lScaleX,
1849                 sy = (lScaleY < 0.000001 && lScaleY > -0.000001)? 0.000001 : lScaleY;
1850 
1851             // skew
1852             if (this._skewX || this._skewY) {
1853                 // offset the anchorpoint
1854                 var skx = Math.tan(-this._skewX * Math.PI / 180);
1855                 var sky = Math.tan(-this._skewY * Math.PI / 180);
1856                 var xx = appY * skx * sx;
1857                 var yy = appX * sky * sy;
1858                 t.a = Cos + -Sin * sky;
1859                 t.b = Cos * skx + -Sin;
1860                 t.c = Sin + Cos * sky;
1861                 t.d = Sin * skx + Cos;
1862                 t.tx += Cos * xx + -Sin * yy;
1863                 t.ty += Sin * xx + Cos * yy;
1864             }
1865 
1866             // scale
1867             if (lScaleX !== 1 || lScaleY !== 1) {
1868                 t.a *= sx;
1869                 t.c *= sx;
1870                 t.b *= sy;
1871                 t.d *= sy;
1872             }
1873 
1874             // adjust anchorPoint
1875             t.tx += Cos * -appX * sx + -Sin * appY * sy;
1876             t.ty -= Sin * -appX * sx + Cos * appY * sy;
1877 
1878             // if ignore anchorPoint
1879             if (this._ignoreAnchorPointForPosition) {
1880                 t.tx += appX;
1881                 t.ty += appY;
1882             }
1883 
1884             if (this._additionalTransformDirty) {
1885                 this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform);
1886                 this._additionalTransformDirty = false;
1887             }
1888 
1889             this._transformDirty = false;
1890         }
1891         return this._transform;
1892     },
1893 
1894     _nodeToParentTransformForWebGL:function () {
1895         if (this._transformDirty) {
1896             // Translate values
1897             var x = this._position.x;
1898             var y = this._position.y;
1899             var apx = this._anchorPointInPoints.x, napx = -apx;
1900             var apy = this._anchorPointInPoints.y, napy = -apy;
1901             var scx = this._scaleX, scy = this._scaleY;
1902 
1903             if (this._ignoreAnchorPointForPosition) {
1904                 x += apx;
1905                 y += apy;
1906             }
1907 
1908             // Rotation values
1909             // Change rotation code to handle X and Y
1910             // If we skew with the exact same value for both x and y then we're simply just rotating
1911             var cx = 1, sx = 0, cy = 1, sy = 0;
1912             if (this._rotationX !== 0 || this._rotationY !== 0) {
1913                 cx = Math.cos(-this._rotationRadiansX);
1914                 sx = Math.sin(-this._rotationRadiansX);
1915                 cy = Math.cos(-this._rotationRadiansY);
1916                 sy = Math.sin(-this._rotationRadiansY);
1917             }
1918             var needsSkewMatrix = ( this._skewX || this._skewY );
1919 
1920             // optimization:
1921             // inline anchor point calculation if skew is not needed
1922             // Adjusted transform calculation for rotational skew
1923             if (!needsSkewMatrix && (apx !== 0 || apy !== 0)) {
1924                 x += cy * napx * scx + -sx * napy * scy;
1925                 y += sy * napx * scx + cx * napy * scy;
1926             }
1927 
1928             // Build Transform Matrix
1929             // Adjusted transform calculation for rotational skew
1930             var t = {a: cy * scx, b: sy * scx, c: -sx * scy, d: cx * scy, tx: x, ty: y};
1931 
1932             // XXX: Try to inline skew
1933             // If skew is needed, apply skew and then anchor point
1934             if (needsSkewMatrix) {
1935                 t = cc.AffineTransformConcat({a: 1.0, b: Math.tan(cc.DEGREES_TO_RADIANS(this._skewY)),
1936                     c: Math.tan(cc.DEGREES_TO_RADIANS(this._skewX)), d: 1.0, tx: 0.0, ty: 0.0}, t);
1937 
1938                 // adjust anchor point
1939                 if (apx !== 0 || apy !== 0)
1940                     t = cc.AffineTransformTranslate(t, napx, napy);
1941             }
1942 
1943             if (this._additionalTransformDirty) {
1944                 t = cc.AffineTransformConcat(t, this._additionalTransform);
1945                 this._additionalTransformDirty = false;
1946             }
1947             this._transform = t;
1948             this._transformDirty = false;
1949         }
1950         return this._transform;
1951     },
1952 
1953     _setNodeDirtyForCache:function () {
1954         this._cacheDirty = true;
1955         if (this._parent) {
1956             this._parent._setNodeDirtyForCache();
1957         }
1958     },
1959 
1960     /**
1961      * Returns a camera object that lets you move the node using a gluLookAt
1962      * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt
1963      * @example
1964      * var camera = node.getCamera();
1965      * camera.setEye(0, 0, 415/2);
1966      * camera.setCenter(0, 0, 0);
1967      */
1968     getCamera:function () {
1969         if (!this._camera) {
1970             this._camera = new cc.Camera();
1971         }
1972         return this._camera;
1973     },
1974 
1975     /**
1976      * Returns a grid object that is used when applying effects
1977      * @return {cc.GridBase} A CCGrid object that is used when applying effects
1978      */
1979     getGrid:function () {
1980         return this._grid;
1981     },
1982 
1983     /**
1984      * Changes a grid object that is used when applying effects
1985      * @param {cc.GridBase} grid A CCGrid object that is used when applying effects
1986      */
1987     setGrid:function (grid) {
1988         this._grid = grid;
1989     },
1990 
1991     /**
1992      * Return the shader program currently used for this node
1993      * @return {cc.GLProgram} The shader program currelty used for this node
1994      */
1995     getShaderProgram:function () {
1996         return this._shaderProgram;
1997     },
1998 
1999     /**
2000      * <p>
2001      *     Sets the shader program for this node
2002      *
2003      *     Since v2.0, each rendering node must set its shader program.
2004      *     It should be set in initialize phase.
2005      * </p>
2006      * @param {cc.GLProgram} newShaderProgram The shader program which fetchs from CCShaderCache.
2007      * @example
2008      *  node.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
2009      */
2010     setShaderProgram:function (newShaderProgram) {
2011         this._shaderProgram = newShaderProgram;
2012     },
2013 
2014     /**
2015      * Returns the state of OpenGL server side.
2016      * @return {Number} The state of OpenGL server side.
2017      */
2018     getGLServerState:function () {
2019         return this._glServerState;
2020     },
2021 
2022     /**
2023      * Sets the state of OpenGL server side.
2024      * @param {Number} state The state of OpenGL server side.
2025      */
2026     setGLServerState:function (state) {
2027         this._glServerState = state;
2028     },
2029 
2030     /** returns a "world" axis aligned bounding box of the node. <br/>
2031      * @return {cc.Rect}
2032      */
2033     getBoundingBoxToWorld:function () {
2034         var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
2035         rect = cc.RectApplyAffineTransform(rect, this.nodeToWorldTransform());
2036         rect = cc.rect(0 | rect.x - 4, 0 | rect.y - 4, 0 | rect.width + 8, 0 | rect.height + 8);
2037         //query child's BoundingBox
2038         if (!this._children)
2039             return rect;
2040 
2041         var locChildren = this._children;
2042         for (var i = 0; i < locChildren.length; i++) {
2043             var child = locChildren[i];
2044             if (child && child._visible) {
2045                 var childRect = child.getBoundingBoxToWorld();
2046                 if (childRect)
2047                     rect = cc.rectUnion(rect, childRect);
2048             }
2049         }
2050         return rect;
2051     }
2052 });
2053 
2054 if(cc.Browser.supportWebGL){
2055     //WebGL
2056     cc.Node.prototype.ctor = cc.Node.prototype._ctorForWebGL;
2057     cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForWebGL;
2058     cc.Node.prototype.visit = cc.Node.prototype._visitForWebGL;
2059     cc.Node.prototype.transform = cc.Node.prototype._transformForWebGL;
2060     cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForWebGL;
2061 }else{
2062     //Canvas
2063     cc.Node.prototype.ctor = cc.Node.prototype._ctorForCanvas;
2064     cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForCanvas;
2065     cc.Node.prototype.visit = cc.Node.prototype._visitForCanvas;
2066     cc.Node.prototype.transform = cc.Node.prototype._transformForCanvas;
2067     cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForCanvas;
2068 }
2069 
2070 /**
2071  * allocates and initializes a node.
2072  * @constructs
2073  * @return {cc.Node}
2074  * @example
2075  * // example
2076  * var node = cc.Node.create();
2077  */
2078 cc.Node.create = function () {
2079     return new cc.Node();
2080 };
2081 
2082 /**
2083  * cc.Node's state callback type
2084  * @constant
2085  * @type Number
2086  */
2087 cc.Node.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7};
2088 
2089 /**
2090  * <p>
2091  *     cc.NodeRGBA is a subclass of cc.Node that implements the CCRGBAProtocol protocol.                       <br/>
2092  *     <br/>
2093  *     All features from CCNode are valid, plus the following new features:                                     <br/>
2094  *      - opacity                                                                                               <br/>
2095  *      - RGB colors                                                                                            <br/>
2096  *     <br/>
2097  *     Opacity/Color propagates into children that conform to the CCRGBAProtocol if cascadeOpacity/cascadeColor is enabled.   <br/>
2098  * </p>
2099  *
2100  * @class
2101  * @extends cc.Node
2102  */
2103 cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{
2104     RGBAProtocol:true,
2105     _displayedOpacity:255,
2106     _realOpacity:255,
2107     _displayedColor:null,
2108     _realColor:null,
2109     _cascadeColorEnabled:false,
2110     _cascadeOpacityEnabled:false,
2111 
2112     ctor:function(){
2113         cc.Node.prototype.ctor.call(this);
2114         this._displayedOpacity = 255;
2115         this._realOpacity = 255;
2116         this._displayedColor = cc.WHITE;
2117         this._realColor = cc.WHITE;
2118         this._cascadeColorEnabled = false;
2119         this._cascadeOpacityEnabled = false;
2120     },
2121 
2122     getOpacity:function(){
2123         return this._realOpacity;
2124     },
2125 
2126     getDisplayedOpacity:function(){
2127         return this._displayedOpacity;
2128     },
2129 
2130     setOpacity:function(opacity){
2131         this._displayedOpacity = this._realOpacity = opacity;
2132 
2133         if (this._cascadeOpacityEnabled) {
2134             var parentOpacity = 255, locParent = this._parent;
2135             if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
2136                 parentOpacity = locParent.getDisplayedOpacity();
2137             this.updateDisplayedOpacity(parentOpacity);
2138         }
2139     },
2140 
2141     updateDisplayedOpacity:function(parentOpacity){
2142         this._displayedOpacity = this._realOpacity * parentOpacity/255.0;
2143         if (this._cascadeOpacityEnabled) {
2144             var selChildren = this._children;
2145             for(var i = 0; i< selChildren.length;i++){
2146                 var item = selChildren[i];
2147                 if(item && item.RGBAProtocol)
2148                     item.updateDisplayedOpacity(this._displayedOpacity);
2149             }
2150         }
2151     },
2152 
2153     isCascadeOpacityEnabled:function(){
2154         return this._cascadeOpacityEnabled;
2155     },
2156 
2157     setCascadeOpacityEnabled:function(cascadeOpacityEnabled){
2158         this._cascadeOpacityEnabled = cascadeOpacityEnabled;
2159     },
2160 
2161     getColor:function(){
2162         var locRealColor = this._realColor;
2163         return new cc.Color3B(locRealColor.r, locRealColor.g, locRealColor.b);
2164     },
2165 
2166     getDisplayedColor:function(){
2167         return this._displayedColor;
2168     },
2169 
2170     setColor:function(color){
2171         var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
2172         locDisplayedColor.r = color.r;
2173         locDisplayedColor.g = color.g;
2174         locDisplayedColor.b = color.b;
2175         locRealColor.r = color.r;
2176         locRealColor.g = color.g;
2177         locRealColor.b = color.b;
2178 
2179         if (this._cascadeColorEnabled) {
2180             var parentColor = cc.white();
2181             var locParent =  this._parent;
2182             if (locParent && locParent.RGBAProtocol &&  locParent.isCascadeColorEnabled())
2183                 parentColor = locParent.getDisplayedColor();
2184             this.updateDisplayedColor(parentColor);
2185         }
2186     },
2187 
2188     updateDisplayedColor:function(parentColor){
2189         var locDispColor = this._displayedColor, locRealColor = this._realColor;
2190         locDispColor.r = locRealColor.r * parentColor.r/255.0;
2191         locDispColor.g = locRealColor.g * parentColor.g/255.0;
2192         locDispColor.b = locRealColor.b * parentColor.b/255.0;
2193 
2194         if (this._cascadeColorEnabled){
2195             var selChildren = this._children;
2196             for(var i = 0; i< selChildren.length;i++){
2197                 var item = selChildren[i];
2198                 if(item && item.RGBAProtocol)
2199                     item.updateDisplayedColor(locDispColor);
2200             }
2201         }
2202     },
2203 
2204     isCascadeColorEnabled:function(){
2205         return this._cascadeColorEnabled;
2206     },
2207 
2208     setCascadeColorEnabled:function(cascadeColorEnabled){
2209         this._cascadeColorEnabled = cascadeColorEnabled;
2210     },
2211 
2212     setOpacityModifyRGB:function(opacityValue){},
2213 
2214     isOpacityModifyRGB:function(){
2215         return false;
2216     }
2217 });
2218