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