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