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