1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * Default Node tag
 29  * @constant
 30  * @type Number
 31  */
 32 cc.NODE_TAG_INVALID = -1;
 33 /**
 34  * Node on enter
 35  * @constant
 36  */
 37 cc.NODE_ON_ENTER = null;
 38 /**
 39  * Node on exit
 40  * @constant
 41  */
 42 cc.NODE_ON_EXIT = null;
 43 
 44 /**
 45  * save the context
 46  * @function
 47  */
 48 cc.saveContext = function () {
 49     if (cc.renderContextType == cc.CANVAS) {
 50         cc.renderContext.save();
 51     } else {
 52         //glPushMatrix();
 53     }
 54 };
 55 
 56 /**
 57  * restore the context
 58  * @function
 59  */
 60 cc.restoreContext = function () {
 61     if (cc.renderContextType == cc.CANVAS) {
 62         cc.renderContext.restore();
 63     } else {
 64         //glPopMatrix();
 65     }
 66 };
 67 
 68 /**
 69  *  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.
 70  * @type Number
 71  */
 72 cc.s_globalOrderOfArrival = 1;
 73 
 74 
 75 /** <p>cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.<br/>
 76  The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.<br/></p>
 77 
 78  <p>The main features of a cc.Node are: <br/>
 79  - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc) <br/>
 80  - They can schedule periodic callback (schedule, unschedule, etc) <br/>
 81  - They can execute actions (runAction, stopAction, etc) <br/></p>
 82 
 83  <p>Some cc.Node nodes provide extra functionality for them or their children.</p>
 84 
 85  <p>Subclassing a cc.Node usually means (one/all) of: <br/>
 86  - overriding init to initialize resources and schedule callbacks  <br/>
 87  - create callbacks to handle the advancement of time <br/>
 88  - overriding draw to render the node   <br/></p>
 89 
 90  <p>Features of cc.Node: <br/>
 91  - position  <br/>
 92  - scale (x, y) <br/>
 93  - rotation (in degrees, clockwise) <br/>
 94  - cc.Camera (an interface to gluLookAt ) <br/>
 95  - cc.GridBase (to do mesh transformations)  <br/>
 96  - anchor point<br/>
 97  - size <br/>
 98  - visible<br/>
 99  - z-order <br/>
100  - openGL z position <br/></P>
101 
102  <p> Default values: <br/>
103  - rotation: 0 <br/>
104  - position: (x=0,y=0) <br/>
105  - scale: (x=1,y=1) <br/>
106  - contentSize: (x=0,y=0)<br/>
107  - anchorPoint: (x=0,y=0)<br/></p>
108 
109  <p> Limitations:<br/>
110  - A cc.Node is a "void" object. It doesn't have a texture <br/></P>
111 
112  <p>Order in transformations with grid disabled <br/>
113  -# The node will be translated (position)  <br/>
114  -# The node will be rotated (rotation)<br/>
115  -# The node will be scaled (scale)  <br/>
116  -# The node will be moved according to the camera values (camera) <br/></p>
117 
118  <p>Order in transformations with grid enabled<br/>
119  -# The node will be translated (position)<br/>
120  -# The node will be rotated (rotation) <br/>
121  -# The node will be scaled (scale) <br/>
122  -# The grid will capture the screen <br/>
123  -# The node will be moved according to the camera values (camera) <br/>
124  -# The grid will render the captured screen <br/></P>
125 
126  <p>Camera:  <br/>
127  - Each node has a camera. By default it points to the center of the cc.Node.</P>
128  * @class
129  * @extends cc.Class
130  * @example
131  * // example
132  * cc.Sprite = cc.Node.extend({});
133  * cc.Sprite.initWithImage = function(){
134  * };
135  */
136 cc.Node = cc.Class.extend(/** @lends cc.Node# */{
137     _zOrder:0,
138     _vertexZ:0.0,
139     _rotation:0.0,
140     _scaleX:1.0,
141     _scaleY:1.0,
142     _position:cc.p(0, 0),
143     _skewX:0.0,
144     _skewY:0.0,
145     // children (lazy allocs),
146     _children:null,
147     // lazy alloc,
148     _camera:null,
149     _grid:null,
150     _visible:true,
151     _anchorPoint:cc.p(0, 0),
152     _anchorPointInPoints:cc.p(0, 0),
153     _contentSize:cc.SizeZero(),
154     _running:false,
155     _parent:null,
156     // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true
157     _ignoreAnchorPointForPosition:false,
158     _tag:cc.NODE_TAG_INVALID,
159     // userData is always inited as nil
160     _userData:null,
161     _userObject:null,
162     _transformDirty:true,
163     _inverseDirty:true,
164     _cacheDirty:true,
165     _transformGLDirty:null,
166     _transform:null,
167     _inverse:null,
168     //since 2.0 api
169     _reorderChildDirty:false,
170     _shaderProgram:null,
171     _orderOfArrival:0,
172     _glServerState:null,
173     _actionManager:null,
174     _scheduler:null,
175 
176     _initializedNode:false,
177 
178     /**
179      * Constructor
180      */
181     ctor:function () {
182         this._initNode();
183     },
184 
185     _initNode:function () {
186         if (cc.NODE_TRANSFORM_USING_AFFINE_MATRIX) {
187             this._transformGLDirty = true;
188         }
189         this._anchorPoint = cc.p(0, 0);
190         this._anchorPointInPoints = cc.p(0, 0);
191         this._contentSize = cc.size(0, 0);
192         this._position = cc.p(0, 0);
193 
194         var director = cc.Director.getInstance();
195         this._actionManager = director.getActionManager();
196         this.getActionManager = function () {
197             return this._actionManager;
198         };
199         this._scheduler = director.getScheduler();
200         this.getScheduler = function () {
201             return this._scheduler;
202         };
203         this._initializedNode = true;
204     },
205 
206     init:function () {
207         if (this._initializedNode === false)
208             this._initNode();
209         return true;
210     },
211 
212     /**
213      * @param {Array} array
214      * @param {cc.Node.StateCallbackType} function Type
215      * @private
216      */
217     _arrayMakeObjectsPerformSelector:function (array, callbackType) {
218         if (!array || array.length == 0)
219             return;
220 
221         var i;
222         switch (callbackType) {
223             case cc.Node.StateCallbackType.onEnter:
224                 for (i = 0; i < array.length; i++) {
225                     if (array[i])
226                         array[i].onEnter();
227                 }
228                 break;
229             case cc.Node.StateCallbackType.onExit:
230                 for (i = 0; i < array.length; i++) {
231                     if (array[i])
232                         array[i].onExit();
233                 }
234                 break;
235             case cc.Node.StateCallbackType.onEnterTransitionDidFinish:
236                 for (i = 0; i < array.length; i++) {
237                     if (array[i])
238                         array[i].onEnterTransitionDidFinish();
239                 }
240                 break;
241             case cc.Node.StateCallbackType.cleanup:
242                 for (i = 0; i < array.length; i++) {
243                     if (array[i])
244                         array[i].cleanup();
245                 }
246                 break;
247             case cc.Node.StateCallbackType.updateTransform:
248                 for (i = 0; i < array.length; i++) {
249                     if (array[i])
250                         array[i].updateTransform();
251                 }
252                 break;
253             case cc.Node.StateCallbackType.onExitTransitionDidStart:
254                 for (i = 0; i < array.length; i++) {
255                     if (array[i])
256                         array[i].onExitTransitionDidStart();
257                 }
258                 break;
259             case cc.Node.StateCallbackType.sortAllChildren:
260                 for (i = 0; i < array.length; i++) {
261                     if (array[i])
262                         array[i].sortAllChildren();
263                 }
264                 break;
265             default :
266                 throw "Unknown callback function";
267                 break;
268         }
269     },
270 
271     /**
272      * @param {cc.Rect} rect
273      * @private
274      */
275     _addDirtyRegionToDirector:function (rect) {
276         //if (!cc.firstRun) {
277         //cc.Director.getInstance().addRegionToDirtyRegion(rect);
278         //}
279     },
280 
281     _isInDirtyRegion:function () {
282         //if (!cc.firstRun) {
283         //    return cc.Director.getInstance().rectIsInDirtyRegion(this.getBoundingBoxToWorld());
284         //}
285     },
286 
287     /**
288      * set the dirty node
289      */
290     setNodeDirty:function () {
291         this._setNodeDirtyForCache();
292         this._transformDirty = this._inverseDirty = true;
293         if (cc.NODE_TRANSFORM_USING_AFFINE_MATRIX) {
294             this._transformGLDirty = true;
295         }
296     },
297 
298     _setNodeDirtyForCache:function () {
299         this._cacheDirty = true;
300         if (this._parent) {
301             this._parent._setNodeDirtyForCache();
302         }
303     },
304 
305     /**
306      *  get the skew degrees in X
307      * @return {Number}
308      */
309     getSkewX:function () {
310         return this._skewX;
311     },
312 
313     /**
314      * set the skew degrees in X
315      * @param {Number} newSkewX
316      */
317     setSkewX:function (newSkewX) {
318         //save dirty region when before change
319         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
320 
321         this._skewX = newSkewX;
322 
323         //save dirty region when after changed
324         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
325         this.setNodeDirty();
326     },
327 
328     /** get the skew degrees in Y
329      * @return {Number}
330      */
331     getSkewY:function () {
332         return this._skewY;
333     },
334 
335     /**
336      * set the skew degrees in Y
337      * @param {Number} newSkewY
338      */
339     setSkewY:function (newSkewY) {
340         //save dirty region when before change
341         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
342 
343         this._skewY = newSkewY;
344         //save dirty region when after changed
345         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
346         this.setNodeDirty();
347     },
348 
349     /**
350      * zOrder getter
351      * @return {Number}
352      */
353     getZOrder:function () {
354         return this._zOrder;
355     },
356 
357     /** zOrder setter : private method
358      * used internally to alter the zOrder variable. DON'T call this method manually
359      * @param {Number} z
360      * @private
361      */
362     _setZOrder:function (z) {
363         this._zOrder = z;
364     },
365 
366     setZOrder:function (z) {
367         this._setZOrder(z);
368         if (this._parent) {
369             this._parent.reorderChild(this, z);
370         }
371     },
372 
373     /**
374      * ertexZ getter
375      * @return {Number}
376      */
377     getVertexZ:function () {
378         return this._vertexZ;
379     },
380 
381     /**
382      * vertexZ setter
383      * @param {Number} Var
384      */
385     setVertexZ:function (Var) {
386         this._vertexZ = Var;
387     },
388 
389     /**
390      * rotation getter
391      * @return {Number}
392      */
393     getRotation:function () {
394         return this._rotation;
395     },
396 
397     _rotationRadians:0,
398     /**
399      * rotation setter
400      * @param {Number} newRotation
401      */
402     setRotation:function (newRotation) {
403         if (this._rotation == newRotation)
404             return;
405         this._rotation = newRotation;
406         this._rotationRadians = this._rotation * (Math.PI / 180);
407 
408         this.setNodeDirty();
409     },
410 
411     /** Get the scale factor of the node.
412      * @warning: Assert when _scaleX != _scaleY.
413      * @return {Number}
414      */
415     getScale:function () {
416         cc.Assert(this._scaleX == this._scaleY, "cc.Node#scale. ScaleX != ScaleY. Don't know which one to return");
417         return this._scaleX;
418     },
419 
420     /**
421      * The scale factor of the node. 1.0 is the default scale factor.
422      * @param {Number} scale or scaleX value
423      * @param {Number} scaleY
424      */
425     setScale:function (scale, scaleY) {
426         //save dirty region when before change
427         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
428 
429         this._scaleX = scale;
430         this._scaleY = scaleY || scale;
431 
432         //save dirty region when after changed
433         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
434         this.setNodeDirty();
435     },
436 
437     /**
438      * scaleX getter
439      * @return {Number}
440      */
441     getScaleX:function () {
442         return this._scaleX;
443     },
444 
445     /**
446      * scaleX setter
447      * @param {Number} newScaleX
448      */
449     setScaleX:function (newScaleX) {
450         //save dirty region when before change
451         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
452 
453         this._scaleX = newScaleX;
454 
455         //save dirty region when after changed
456         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
457         this.setNodeDirty();
458     },
459 
460     /**
461      * scaleY getter
462      * @return {Number}
463      */
464     getScaleY:function () {
465         return this._scaleY;
466     },
467 
468     /**
469      * scaleY setter
470      * @param {Number} newScaleY
471      */
472     setScaleY:function (newScaleY) {
473         //save dirty region when before change
474         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
475 
476         this._scaleY = newScaleY;
477 
478         //save dirty region when after changed
479         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
480         this.setNodeDirty();
481     },
482 
483     /**
484      * position setter
485      * @param {cc.Point|Number} newPosOrxValue
486      * @param {Number}  yValue
487      */
488     setPosition:function (newPosOrxValue, yValue) {
489         //save dirty region when before change
490         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
491         if (arguments.length == 2) {
492             this._position = new cc.Point(newPosOrxValue, yValue);
493             //this.setPosition = this._setPositionByValue;
494         } else if (arguments.length == 1) {
495             this._position = new cc.Point(newPosOrxValue.x, newPosOrxValue.y);
496             //this.setPosition = this._setPositionByValue;
497         }
498         //save dirty region when after changed
499         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
500         this.setNodeDirty();
501     },
502 
503     _setPositionByValue:function (newPosOrxValue, yValue) {
504         if (arguments.length == 2) {
505             this._position.x = newPosOrxValue;
506             this._position.y = yValue;
507             //this._position = cc.p(newPosOrxValue,yValue);
508         } else if (arguments.length == 1) {
509             this._position.x = newPosOrxValue.x;
510             this._position.y = newPosOrxValue.y;
511         }
512         this.setNodeDirty();
513     },
514 
515     /** <p>get/set Position for Lua (pass number faster than cc.Point object)</p>
516 
517      <p>lua code:<br/>
518      local x, y = node:getPosition()    -- return x, y values from C++ <br/>
519      local x    = node:getPositionX()<br/>
520      local y    = node:getPositionY()<br/>
521      node:setPosition(x, y)             -- pass x, y values to C++ <br/>
522      node:setPositionX(x) <br/>
523      node:setPositionY(y)<br/>
524      node:setPositionInPixels(x, y)     -- pass x, y values to C++ <br/></P>
525      * @return {cc.Point}
526      */
527     getPosition:function () {
528         return cc.p(this._position.x, this._position.y);
529     },
530 
531     /**
532      * @return {Number}
533      */
534     getPositionX:function () {
535         return this._position.x;
536     },
537 
538     /**
539      * @param {Number} x
540      */
541     setPositionX:function (x) {
542         this._position.x = x;
543         //this._position = cc.p(x,this._position.y);
544         this.setNodeDirty();
545     },
546 
547     /**
548      * @return {Number}
549      */
550     getPositionY:function () {
551         return  this._position.y;
552     },
553 
554     /**
555      * @param {Number} y
556      */
557     setPositionY:function (y) {
558         this._position.y = y;
559         //this._position = cc.p(this._position.x, y);
560         this.setNodeDirty();
561     },
562 
563     /**
564      * Get children count
565      * @return {Number}
566      */
567 
568     getChildrenCount:function () {
569         return this._children ? this._children.length : 0;
570     },
571 
572     /**
573      * children getter
574      * @return {object}
575      */
576     getChildren:function () {
577         if (!this._children)
578             this._children = [];
579         return this._children;
580     },
581 
582     /**
583      * camera getter: lazy alloc
584      * @return {cc.Camera}
585      */
586     getCamera:function () {
587         if (!this._camera) {
588             this._camera = new cc.Camera();
589         }
590         return this._camera;
591     },
592 
593     /**
594      * grid getter
595      * @return {cc.GridBase}
596      */
597     getGrid:function () {
598         return this._grid;
599     },
600 
601     /**
602      * grid setter
603      * @param {cc.GridBase} grid
604      */
605     setGrid:function (grid) {
606         this._grid = grid;
607     },
608 
609     /**
610      * isVisible getter
611      * @return {Boolean}
612      */
613     isVisible:function () {
614         return this._visible;
615     },
616 
617     /**
618      * isVisible setter
619      * @param {Boolean} Var
620      */
621     setVisible:function (Var) {
622         this._visible = Var;
623         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
624         this.setNodeDirty();
625     },
626 
627     /** <p>anchorPoint is the point around which all transformations and positioning manipulations take place.<br/>
628      It's like a pin in the node where it is "attached" to its parent. <br/>
629      The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/>
630      But you can use values higher than (1,1) and lower than (0,0) too.  <br/>
631      The default anchorPoint is (0.5,0.5), so it starts in the center of the node. <br/></p>
632      */
633     getAnchorPoint:function () {
634         return cc.p(this._anchorPoint.x, this._anchorPoint.y);
635     },
636 
637     /**
638      * @param {cc.Point} point
639      */
640     setAnchorPoint:function (point) {
641         if (!cc.Point.CCPointEqualToPoint(point, this._anchorPoint)) {
642             //save dirty region when before change
643             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
644 
645             this._anchorPoint = new cc.Point(point.x, point.y);
646             this._anchorPointInPoints = new cc.Point(this._contentSize.width * this._anchorPoint.x, this._contentSize.height * this._anchorPoint.y);
647 
648             //this.setAnchorPoint = this._setAnchorPointByValue;
649 
650             //save dirty region when after changed
651             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
652             this.setNodeDirty();
653         }
654     },
655 
656     _setAnchorPointByValue:function (point) {
657         if (!cc.Point.CCPointEqualToPoint(point, this._anchorPoint)) {
658             this._anchorPoint.x = point.x;
659             this._anchorPoint.y = point.y;
660             this._anchorPointInPoints.x = this._contentSize.width * this._anchorPoint.x;
661             this._anchorPointInPoints.y = this._contentSize.height * this._anchorPoint.y;
662             this.setNodeDirty();
663         }
664     },
665 
666     /** AnchorPointInPoints getter
667      * @return {cc.Point}
668      */
669     getAnchorPointInPoints:function () {
670         return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y);
671     },
672 
673     /** <p>The untransformed size of the node. <br/>
674      The contentSize remains the same no matter the node is scaled or rotated.<br/>
675      All nodes has a size. Layer and Scene has the same size of the screen. <br/></p>
676      * @return {cc.Size}
677      */
678     getContentSize:function () {
679         return cc.size(this._contentSize.width, this._contentSize.height);
680     },
681 
682     /**
683      * @param {cc.Size} size
684      */
685     setContentSize:function (size) {
686         if (!cc.Size.CCSizeEqualToSize(size, this._contentSize)) {
687             //save dirty region when before change
688             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
689             this._contentSize = new cc.Size(size.width, size.height);
690             this._anchorPointInPoints = new cc.Point(this._contentSize.width * this._anchorPoint.x, this._contentSize.height * this._anchorPoint.y);
691             //save dirty region when before change
692             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
693             //this.setContentSize = this._setContentSizeByValue;
694             this.setNodeDirty();
695         }
696     },
697 
698     _setContentSizeByValue:function (size) {
699         if (!cc.Size.CCSizeEqualToSize(size, this._contentSize)) {
700             this._contentSize.width = size.width;
701             this._contentSize.height = size.height;
702             this._anchorPointInPoints.x = this._contentSize.width * this._anchorPoint.x;
703             this._anchorPointInPoints.y = this._contentSize.height * this._anchorPoint.y;
704             this.setNodeDirty();
705         }
706     },
707 
708     /**
709      * isRunning getter
710      * @return {Boolean}
711      */
712     isRunning:function () {
713         return this._running;
714     },
715 
716     /** parent getter
717      * @return {cc.Node}
718      */
719     getParent:function () {
720         return this._parent;
721     },
722 
723     /** parent setter
724      * @param {cc.Node} Var
725      */
726     setParent:function (Var) {
727         this._parent = Var;
728     },
729 
730     /** ignoreAnchorPointForPosition getter
731      * @return {Boolean}
732      */
733     isIgnoreAnchorPointForPosition:function () {
734         return this._ignoreAnchorPointForPosition;
735     },
736 
737     /** ignoreAnchorPointForPosition setter
738      * @param {Boolean} newValue
739      */
740     ignoreAnchorPointForPosition:function (newValue) {
741         if (newValue != this._ignoreAnchorPointForPosition) {
742             //save dirty region when before change
743             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
744 
745             this._ignoreAnchorPointForPosition = newValue;
746 
747             //save dirty region when before change
748             //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
749             this.setNodeDirty();
750         }
751     },
752 
753     /**
754      * tag getter
755      * @return {Number}
756      */
757     getTag:function () {
758         return this._tag;
759     },
760 
761     /** tag setter
762      * @param {Number} Var
763      */
764     setTag:function (Var) {
765         this._tag = Var;
766     },
767 
768     /**
769      * @return {object}
770      */
771     getUserData:function () {
772         return this._userData;
773     },
774 
775     /**
776      * @param {object} Var
777      */
778     setUserData:function (Var) {
779         this._userData = Var;
780     },
781 
782     /**
783      * Similar to userData, but instead of holding a void* it holds an id
784      * @return {object}
785      */
786     getUserObject:function () {
787         return this._userObject;
788     },
789 
790     /**
791      * Similar to userData, but instead of holding a void* it holds an id
792      * @param {object} newValue
793      */
794     setUserObject:function (newValue) {
795         if (this._userObject != newValue) {
796             this._userObject = newValue;
797         }
798     },
799 
800     /**
801      * Shader Program getter
802      * @return {object}
803      */
804     getShaderProgram:function () {
805         return this._shaderProgram;
806     },
807 
808     /**
809      * Shader Program setter
810      * @param {object} newValue
811      */
812     setShaderProgram:function (newValue) {
813         if (this._shaderProgram != newValue) {
814             this._shaderProgram = newValue;
815         }
816     },
817 
818     /**
819      * used internally for zOrder sorting, don't change this manually
820      * @return {Number}
821      */
822     getOrderOfArrival:function () {
823         return this._orderOfArrival;
824     },
825 
826     /**
827      * used internally for zOrder sorting, don't change this manually
828      * @param {Number} Var
829      */
830     setOrderOfArrival:function (Var) {
831         this._orderOfArrival = Var;
832     },
833 
834     /**
835      * GL server side state getter
836      * @return {Number}
837      */
838     getGLServerState:function () {
839         return this._glServerState;
840     },
841 
842     /**
843      * GL server side state setter
844      * @param {Number} Var
845      */
846     setGLServerState:function (Var) {
847         this._glServerState = Var;
848     },
849 
850     /**
851      * <p>cc.ActionManager used by all the actions. <br/>
852      * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)</p>
853      * @return {cc.ActionManager}
854      */
855     getActionManager:function () {
856         if (!this._actionManager) {
857             this._actionManager = cc.Director.getInstance().getActionManager();
858             this.getActionManager = function () {
859                 return this._actionManager;
860             };
861         }
862 
863         return this._actionManager;
864     },
865 
866     /**
867      * <p>cc.ActionManager used by all the actions. <br/>
868      * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)</p>
869      * @param {cc.ActionManager} actionManager
870      */
871     setActionManager:function (actionManager) {
872         if (this._actionManager != actionManager) {
873             this.stopAllActions();
874             this._shaderProgram = actionManager;
875         }
876     },
877 
878     /**
879      * <p>
880      *   cc.Scheduler used to schedule all "updates" and timers.<br/>
881      *   IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed.
882      * </p>
883      * @return {cc.Scheduler}
884      */
885     getScheduler:function () {
886         if (!this._scheduler) {
887             this._scheduler = cc.Director.getInstance().getScheduler();
888             this.getScheduler = function () {
889                 return this._scheduler;
890             };
891         }
892         return this._scheduler;
893     },
894 
895     /**
896      * <p>
897      *   cc.Scheduler used to schedule all "updates" and timers.<br/>
898      *   IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed.
899      * </p>
900      */
901     setScheduler:function (scheduler) {
902         if (this._scheduler != scheduler) {
903             this.unscheduleAllCallbacks();
904             this._scheduler = scheduler;
905         }
906     },
907 
908     /** returns a "local" axis aligned bounding box of the node. <br/>
909      * The returned box is relative only to its parent.
910      * @return {cc.Rect}
911      */
912     getBoundingBox:function () {
913         var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
914         return cc.RectApplyAffineTransform(rect, this.nodeToParentTransform());
915     },
916 
917     /** returns a "world" axis aligned bounding box of the node. <br/>
918      * @return {cc.Rect}
919      */
920     getBoundingBoxToWorld:function () {
921         var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
922         rect = cc.RectApplyAffineTransform(rect, this.nodeToWorldTransform());
923         rect = cc.rect(0 | rect.origin.x - 4, 0 | rect.origin.y - 4, 0 | rect.size.width + 8, 0 | rect.size.height + 8);
924         //query child's BoundingBox
925         if (!this._children)
926             return rect;
927 
928         for (var i = 0; i < this._children.length; i++) {
929             var child = this._children[i];
930             if (child && child._visible) {
931                 var childRect = child.getBoundingBoxToWorld();
932                 if (childRect) {
933                     rect = cc.Rect.CCRectUnion(rect, childRect);
934                 }
935             }
936         }
937         return rect;
938     },
939     /**
940      * Stops all running actions and schedulers
941      */
942     cleanup:function () {
943         // actions
944         this.stopAllActions();
945         this.unscheduleAllCallbacks();
946 
947         // timers
948         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup);
949     },
950 
951     /** Node description
952      * @return {String}
953      */
954     description:function () {
955         return "<cc.Node | Tag =" + this._tag + ">";
956     },
957 
958     _childrenAlloc:function () {
959         this._children = [];
960     },
961 
962     // composition: GET
963     /**
964      * Gets a child from the container given its tag
965      * @param {Number} aTag
966      * @return {cc.Node}
967      */
968     getChildByTag:function (aTag) {
969         cc.Assert(aTag != cc.NODE_TAG_INVALID, "Invalid tag");
970         if (this._children != null) {
971             for (var i = 0; i < this._children.length; i++) {
972                 var node = this._children[i];
973                 if (node && node._tag == aTag) {
974                     return node;
975                 }
976             }
977         }
978         //throw "not found";
979         return null;
980     },
981     // composition: ADD
982 
983     /** <p>"add" logic MUST only be on this method <br/> </p>
984      *
985      * <p>If a class want's to extend the 'addChild' behaviour it only needs  <br/>
986      * to override this method </p>
987      *
988      * @param {cc.Node} child
989      * @param {Number} zOrder
990      * @param {Number} tag
991      */
992     addChild:function (child, zOrder, tag) {
993         if (child === this) {
994             console.warn('cc.Node.addChild: An Node can\'t be added as a child of itself.');
995             return;
996         }
997 
998         cc.Assert(child != null, "Argument must be non-nil");
999         cc.Assert(child._parent == null, "child already added. It can't be added again");
1000         var tempzOrder = (zOrder != null) ? zOrder : child.getZOrder();
1001         var tmptag = (tag != null) ? tag : child.getTag();
1002         child.setTag(tmptag);
1003 
1004         if (!this._children) {
1005             this._childrenAlloc();
1006         }
1007 
1008         this._insertChild(child, tempzOrder);
1009 
1010         child.setParent(this);
1011         if (this._running) {
1012             child.onEnter();
1013             child.onEnterTransitionDidFinish();
1014         }
1015 
1016     },
1017 
1018     // composition: REMOVE
1019     /** Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks. <br/>
1020      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1021      * If the node orphan, then nothing happens.
1022      * @param {Boolean} cleanup
1023      */
1024     removeFromParent:function (cleanup) {
1025         if (this._parent) {
1026             cleanup = cleanup || true;
1027             this._parent.removeChild(this, cleanup);
1028         }
1029     },
1030     /** XXX deprecated */
1031     removeFromParentAndCleanup:function (cleanup) {
1032         cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead");
1033         this.removeFromParent(cleanup);
1034     },
1035 
1036     /** <p>Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. </p>
1037      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1038      *<p> "remove" logic MUST only be on this method  <br/>
1039      * If a class wants to extend the 'removeChild' behavior it only needs <br/>
1040      * to override this method </p>
1041      *
1042      * @param {cc.Node} child
1043      * @param {Boolean} cleanup
1044      */
1045     removeChild:function (child, cleanup) {
1046         // explicit nil handling
1047         if (this._children == null) {
1048             return;
1049         }
1050 
1051         cleanup = cleanup || true;
1052         if (this._children.indexOf(child) > -1) {
1053             this._detachChild(child, cleanup);
1054         }
1055 
1056         this.setNodeDirty();
1057     },
1058 
1059     /**
1060      * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter.
1061      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1062      * @param {Number} tag
1063      * @param {Boolean} cleanup
1064      */
1065     removeChildByTag:function (tag, cleanup) {
1066         cc.Assert(tag != cc.NODE_TAG_INVALID, "Invalid tag");
1067 
1068         var child = this.getChildByTag(tag);
1069         if (child == null) {
1070             cc.log("cocos2d: removeChildByTag: child not found!");
1071         } else {
1072             this.removeChild(child, cleanup);
1073         }
1074     },
1075 
1076     /* XXX deprecated */
1077     removeAllChildrenWithCleanup:function (cleanup) {
1078         cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead");
1079         this.removeAllChildren(cleanup);
1080     },
1081 
1082     /**
1083      * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
1084      * If the cleanup parameter is not passed, it will force a cleanup. <br/>
1085      * @param {Boolean} cleanup
1086      */
1087     removeAllChildren:function (cleanup) {
1088         // not using detachChild improves speed here
1089         if (this._children != null) {
1090             cleanup = cleanup || true;
1091             for (var i = 0; i < this._children.length; i++) {
1092                 var node = this._children[i];
1093                 if (node) {
1094                     // IMPORTANT:
1095                     //  -1st do onExit
1096                     //  -2nd cleanup
1097                     if (this._running) {
1098                         node.onExitTransitionDidStart();
1099                         node.onExit();
1100                     }
1101                     if (cleanup)
1102                         node.cleanup();
1103                     // set parent nil at the end
1104                     node.setParent(null);
1105                 }
1106             }
1107             this._children.length = 0;
1108         }
1109     },
1110 
1111     /**
1112      * @param {cc.Node} child
1113      * @param {Boolean} doCleanup
1114      * @private
1115      */
1116     _detachChild:function (child, doCleanup) {
1117         // IMPORTANT:
1118         //  -1st do onExit
1119         //  -2nd cleanup
1120         if (this._running) {
1121             child.onExitTransitionDidStart();
1122             child.onExit();
1123         }
1124 
1125         // If you don't do cleanup, the child's actions will not get removed and the
1126         // its scheduledSelectors_ dict will not get released!
1127         if (doCleanup) {
1128             child.cleanup();
1129         }
1130 
1131         // set parent nil at the end
1132         child.setParent(null);
1133 
1134         cc.ArrayRemoveObject(this._children, child);
1135     },
1136 
1137     /** helper used by reorderChild & add
1138      * @param {cc.Node} child
1139      * @param {Number} z
1140      * @private
1141      */
1142     _insertChild:function (child, z) {
1143         this._reorderChildDirty = true;
1144         var a = this._children[this._children.length - 1];
1145         if (!a || a.getZOrder() <= z) {
1146             this._children.push(child);
1147         } else {
1148             for (var i = 0; i < this._children.length; i++) {
1149                 var node = this._children[i];
1150                 if (node && (node.getZOrder() > z )) {
1151                     this._children = cc.ArrayAppendObjectToIndex(this._children, child, i);
1152                     break;
1153                 }
1154             }
1155         }
1156         child._setZOrder(z);
1157     },
1158 
1159     /** Reorders a child according to a new z value. <br/>
1160      * The child MUST be already added.
1161      * @param {cc.Node} child
1162      * @param {Number} zOrder
1163      */
1164     reorderChild:function (child, zOrder) {
1165         cc.Assert(child != null, "Child must be non-nil");
1166         this._reorderChildDirty = true;
1167 
1168         //save dirty region when before change
1169         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
1170 
1171         child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
1172         child._setZOrder(zOrder);
1173 
1174         //save dirty region when after changed
1175         //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
1176         this.setNodeDirty();
1177     },
1178 
1179     /**
1180      * <p>performance improvement, Sort the children array once before drawing, instead of every time when a child is added or reordered <br/>
1181      * don't call this manually unless a child added needs to be removed in the same frame </p>
1182      */
1183     sortAllChildren:function () {
1184         if (this._reorderChildDirty) {
1185             var i, j, length = this._children.length;
1186 
1187             // insertion sort
1188             for (i = 0; i < length; i++) {
1189                 var tempItem = this._children[i];
1190                 j = i - 1;
1191 
1192                 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
1193                 while (j >= 0 && ( tempItem._zOrder < this._children[j]._zOrder ||
1194                     ( tempItem._zOrder == this._children[j]._zOrder && tempItem._orderOfArrival < this._children[j]._orderOfArrival ))) {
1195                     this._children[j + 1] = this._children[j];
1196                     j = j - 1;
1197                 }
1198                 this._children[j + 1] = tempItem;
1199             }
1200 
1201             //don't need to check children recursively, that's done in visit of each child
1202             this._reorderChildDirty = false;
1203         }
1204     },
1205 
1206     // draw
1207     /** <p>Override this method to draw your own node. <br/>
1208      * The following GL states will be enabled by default: <br/>
1209      - glEnableClientState(GL_VERTEX_ARRAY);  <br/>
1210      - glEnableClientState(GL_COLOR_ARRAY); <br/>
1211      - glEnableClientState(GL_TEXTURE_COORD_ARRAY); <br/>
1212      - glEnable(GL_TEXTURE_2D); </p>
1213 
1214      <p>AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE</p>
1215 
1216      <p>But if you enable any other GL state, you should disable it after drawing your node. </p>
1217      * @param {CanvasContext} ctx
1218      */
1219     draw:function (ctx) {
1220         //cc.Assert(0);
1221         // override me
1222         // Only use- this function to draw your staff.
1223         // DON'T draw your stuff outside this method
1224     },
1225 
1226     /**
1227      * recursive method that visit its children and draw them
1228      * @param {CanvasContext} ctx
1229      */
1230     visit:function (ctx) {
1231         //visit for canvas
1232 
1233         // quick return if not visible
1234         if (!this._visible)
1235             return;
1236 
1237         var context = ctx || cc.renderContext, i;
1238         context.save();
1239         this.transform(context);
1240         if (this._children && this._children.length > 0) {
1241             this.sortAllChildren();
1242             // draw children zOrder < 0
1243             for (i = 0; i < this._children.length; i++) {
1244                 if (this._children[i] && this._children[i]._zOrder < 0)
1245                     this._children[i].visit(context);
1246                 else
1247                     break;
1248             }
1249             this.draw(context);
1250             if (this._children) {
1251                 for (; i < this._children.length; i++) {
1252                     if (this._children[i] && this._children[i]._zOrder >= 0)
1253                         this._children[i].visit(context);
1254                 }
1255             }
1256         } else
1257             this.draw(context);
1258 
1259         this._orderOfArrival = 0;
1260         context.restore();
1261     },
1262 
1263     _visitForWebGL:function (ctx) {
1264         if (!this._visible)
1265             return;
1266 
1267         var context = ctx, i;
1268 
1269         context.save();
1270 
1271         if (this._grid && this._grid.isActive()) {
1272             this._grid.beforeDraw();
1273         }
1274 
1275         this.transform(context);
1276         if (this._children && this._children.length > 0) {
1277             this.sortAllChildren();
1278             // draw children zOrder < 0
1279             for (i = 0; i < this._children.length; i++) {
1280                 if (this._children[i] && this._children[i]._zOrder < 0) {
1281                     this._children[i].visit(context);
1282                 } else {
1283                     break;
1284                 }
1285             }
1286 
1287             //if (this._isInDirtyRegion()) {
1288             // self draw
1289             this.draw(context);
1290             //}
1291 
1292             // draw children zOrder >= 0
1293             if (this._children) {
1294                 for (; i < this._children.length; i++) {
1295                     if (this._children[i] && this._children[i]._zOrder >= 0) {
1296                         this._children[i].visit(context);
1297                     }
1298                 }
1299             }
1300         } else {
1301             //if (this._isInDirtyRegion()) {
1302             // self draw
1303             this.draw(context);
1304             //}
1305         }
1306 
1307         this._orderOfArrival = 0;
1308         if (this._grid && this._grid.isActive()) {
1309             this._grid.afterDraw(this);
1310         }
1311         context.restore();
1312     },
1313 
1314     /** performs OpenGL view-matrix transformation of it's ancestors.<br/>
1315      * Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) <br/>
1316      * it's necessary to transform the ancestors again.
1317      */
1318     transformAncestors:function () {
1319         if (this._parent != null) {
1320             this._parent.transformAncestors();
1321             this._parent.transform();
1322         }
1323     },
1324 
1325     /** transformations <br/>
1326      * performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes.
1327      * @param {CanvasContext} ctx
1328      */
1329     transform:function (ctx) {
1330         // transform for canvas
1331         var context = ctx || cc.renderContext;
1332 
1333         // transformations
1334         if (!this._ignoreAnchorPointForPosition) {
1335             if (this._parent)
1336                 context.translate(0 | (this._position.x - this._parent._anchorPointInPoints.x), -(0 | (this._position.y - this._parent._anchorPointInPoints.y)));
1337             else
1338                 context.translate(0 | this._position.x, -(0 | this._position.y));
1339         } else {
1340             if (this._parent) {
1341                 context.translate(0 | ( this._position.x - this._parent._anchorPointInPoints.x + this._anchorPointInPoints.x),
1342                     -(0 | (this._position.y - this._parent._anchorPointInPoints.y + this._anchorPointInPoints.y)));
1343             } else {
1344                 context.translate(0 | ( this._position.x + this._anchorPointInPoints.x), -(0 | (this._position.y + this._anchorPointInPoints.y)));
1345             }
1346         }
1347 
1348         if (this._rotation != 0)
1349             context.rotate(this._rotationRadians);
1350 
1351         if ((this._scaleX != 1) || (this._scaleY != 1))
1352             context.scale(this._scaleX, this._scaleY);
1353 
1354         if ((this._skewX != 0) || (this._skewY != 0)) {
1355             context.transform(1,
1356                 -Math.tan(cc.DEGREES_TO_RADIANS(this._skewY)),
1357                 -Math.tan(cc.DEGREES_TO_RADIANS(this._skewX)),
1358                 1, 0, 0);
1359         }
1360     },
1361 
1362     _transformForWebGL:function (ctx) {
1363         var context = ctx;
1364 
1365         //Todo WebGL implement need fixed
1366         var transfrom4x4;
1367 
1368         // Convert 3x3 into 4x4 matrix
1369         var tmpAffine = this.nodeToParentTransform();
1370         //CGAffineToGL(&tmpAffine, transfrom4x4.mat);
1371 
1372         // Update Z vertex manually
1373         //transfrom4x4.mat[14] = m_fVertexZ;
1374 
1375         //kmGLMultMatrix( &transfrom4x4 );
1376 
1377 
1378         // XXX: Expensive calls. Camera should be integrated into the cached affine matrix
1379         /*if ( m_pCamera != NULL && !(m_pGrid != NULL && m_pGrid->isActive()) ) {
1380          bool translate = (m_tAnchorPointInPoints.x != 0.0f || m_tAnchorPointInPoints.y != 0.0f);
1381 
1382          if( translate )
1383          kmGLTranslatef(RENDER_IN_SUBPIXEL(m_tAnchorPointInPoints.x), RENDER_IN_SUBPIXEL(m_tAnchorPointInPoints.y), 0 );
1384 
1385          m_pCamera->locate();
1386 
1387          if( translate )
1388          kmGLTranslatef(RENDER_IN_SUBPIXEL(-m_tAnchorPointInPoints.x), RENDER_IN_SUBPIXEL(-m_tAnchorPointInPoints.y), 0 );
1389          }*/
1390     },
1391 
1392     //scene managment
1393     /**
1394      * callback that is called every time the cc.Node enters the 'stage'.<br/>
1395      * If the cc.Node enters the 'stage' with a transition, this callback is called when the transition starts.
1396      * During onEnter you can't a "sister/brother" node.
1397      */
1398     onEnter:function () {
1399         this._running = true;//should be running before resumeSchedule
1400         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnter);
1401         this.resumeSchedulerAndActions();
1402     },
1403 
1404     /**
1405      * <p>callback that is called when the cc.Node enters in the 'stage'.  <br/>
1406      * If the cc.Node enters the 'stage' with a transition, this callback is called when the transition finishes.</p>
1407      */
1408     onEnterTransitionDidFinish:function () {
1409         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnterTransitionDidFinish);
1410     },
1411 
1412     /**
1413      * <p>callback that is called every time the cc.Node leaves the 'stage'.  <br/>
1414      * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. </p>
1415      */
1416     onExitTransitionDidStart:function () {
1417         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExitTransitionDidStart);
1418     },
1419 
1420     /**
1421      * callback that is called every time the cc.Node leaves the 'stage'.<br/>
1422      * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/>
1423      * During onExit you can't access a sibling node.
1424      */
1425     onExit:function () {
1426         this._running = false;
1427         this.pauseSchedulerAndActions();
1428         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExit);
1429     },
1430 
1431     // actions
1432     /**
1433      * Executes an action, and returns the action that is executed.<br/>
1434      * The node becomes the action's target.
1435      * @warning Starting from v0.8 actions don't retain their target anymore.
1436      * @param {cc.Action} action
1437      * @return {cc.Action}
1438      */
1439     runAction:function (action) {
1440         cc.Assert(action != null, "Argument must be non-nil");
1441         this.getActionManager().addAction(action, this, !this._running);
1442         return action;
1443     },
1444 
1445     /**
1446      * Removes all actions from the running action list
1447      */
1448     stopAllActions:function () {
1449         this.getActionManager().removeAllActionsFromTarget(this);
1450     },
1451 
1452     /**
1453      * Removes an action from the running action list
1454      * @param {cc.Action} action
1455      */
1456     stopAction:function (action) {
1457         this.getActionManager().removeAction(action);
1458     },
1459 
1460     /**
1461      * Removes an action from the running action list given its tag
1462      * @param {Number} tag
1463      */
1464     stopActionByTag:function (tag) {
1465         cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag");
1466         this.getActionManager().removeActionByTag(tag, this);
1467     },
1468 
1469     /**
1470      * Gets an action from the running action list given its tag
1471      * @param {Number} tag
1472      * @return {cc.Action}
1473      */
1474     getActionByTag:function (tag) {
1475         cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag");
1476         return this.getActionManager().getActionByTag(tag, this);
1477     },
1478 
1479     /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).<br/>
1480      *    Composable actions are counted as 1 action. Example:<br/>
1481      *    If you are running 1 Sequence of 7 actions, it will return 1. <br/>
1482      *    If you are running 7 Sequences of 2 actions, it will return 7.
1483      * @return {Number}
1484      */
1485     numberOfRunningActions:function () {
1486         return this.getActionManager().numberOfRunningActionsInTarget(this);
1487     },
1488 
1489     // cc.Node - Callbacks
1490     // timers
1491     /**
1492      * schedules the "update" method. It will use the order number 0. This method will be called every frame.<br/>
1493      * Scheduled methods with a lower order value will be called before the ones that have a higher order value.<br/>
1494      * Only one "update" method could be scheduled per node.
1495      */
1496     scheduleUpdate:function () {
1497         this.scheduleUpdateWithPriority(0);
1498     },
1499 
1500     /**
1501      * schedules the "update" callback function with a custom priority. This callback function will be called every frame.<br/>
1502      * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.<br/>
1503      * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).<br/>
1504      * @param {Number} priority
1505      */
1506     scheduleUpdateWithPriority:function (priority) {
1507         this.getScheduler().scheduleUpdateForTarget(this, priority, !this._running);
1508     },
1509 
1510     /**
1511      * unschedules the "update" method.
1512      */
1513     unscheduleUpdate:function () {
1514         this.getScheduler().unscheduleUpdateForTarget(this);
1515     },
1516 
1517     /**
1518      * schedules a callback function with interval, repeat and delay.
1519      * @param {function} callback_fn
1520      * @param {Number} interval
1521      */
1522     schedule:function (callback_fn, interval, repeat, delay) {
1523         interval = interval || 0;
1524 
1525         cc.Assert(callback_fn, "Argument must be non-nil");
1526         cc.Assert(interval >= 0, "Argument must be positive");
1527 
1528         repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
1529         delay = delay || 0;
1530 
1531         this.getScheduler().scheduleCallbackForTarget(this, callback_fn, interval, repeat, delay, !this._running);
1532     },
1533 
1534     /**
1535      * Schedules a callback function that runs only once, with a delay of 0 or larger
1536      * @param {cc.Class} callback_fn
1537      * @param {Number} delay
1538      */
1539     scheduleOnce:function (callback_fn, delay) {
1540         this.schedule(callback_fn, 0.0, 0, delay);
1541     },
1542 
1543     /**
1544      * unschedules a custom callback function.
1545      * @param {function} callback_fn
1546      */
1547     unschedule:function (callback_fn) {
1548         // explicit nil handling
1549         if (!callback_fn)
1550             return;
1551 
1552         this.getScheduler().unscheduleCallbackForTarget(this, callback_fn);
1553     },
1554 
1555     /**
1556      * unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.<br/>
1557      * Actions are not affected by this method.
1558      */
1559     unscheduleAllCallbacks:function () {
1560         this.getScheduler().unscheduleAllCallbacksForTarget(this);
1561     },
1562 
1563     /**
1564      * resumes all scheduled callback functions and actions.<br/>
1565      * Called internally by onEnter
1566      */
1567     resumeSchedulerAndActions:function () {
1568         this.getScheduler().resumeTarget(this);
1569         this.getActionManager().resumeTarget(this);
1570     },
1571 
1572     /**
1573      * pauses all scheduled selectors and actions.<br/>
1574      * Called internally by onExit
1575      */
1576     pauseSchedulerAndActions:function () {
1577         this.getScheduler().pauseTarget(this);
1578         this.getActionManager().pauseTarget(this);
1579     },
1580 
1581     /** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/>
1582      * The matrix is in Pixels.
1583      * @return {cc.AffineTransform}
1584      */
1585     nodeToParentTransform:function () {
1586         if (this._transformDirty) {
1587             // Translate values
1588             var x = this._position.x;
1589             var y = this._position.y;
1590 
1591             if (this._ignoreAnchorPointForPosition) {
1592                 x += this._anchorPointInPoints.x;
1593                 y += this._anchorPointInPoints.y;
1594             }
1595 
1596             // Rotation values
1597             var c = 1, s = 0;
1598             if (this._rotation) {
1599                 //var radians = -cc.DEGREES_TO_RADIANS(this._rotation);
1600                 c = Math.cos(-this._rotationRadians);
1601                 s = Math.sin(-this._rotationRadians);
1602             }
1603 
1604             var needsSkewMatrix = ( this._skewX || this._skewY );
1605 
1606             // optimization:
1607             // inline anchor point calculation if skew is not needed
1608             if (!needsSkewMatrix && !cc.Point.CCPointEqualToPoint(this._anchorPointInPoints, cc.p(0, 0))) {
1609                 x += c * -this._anchorPointInPoints.x * this._scaleX + -s * -this._anchorPointInPoints.y * this._scaleY;
1610                 y += s * -this._anchorPointInPoints.x * this._scaleX + c * -this._anchorPointInPoints.y * this._scaleY;
1611             }
1612 
1613             // Build Transform Matrix
1614             this._transform = cc.AffineTransformMake(c * this._scaleX, s * this._scaleX,
1615                 -s * this._scaleY, c * this._scaleY, x, y);
1616 
1617             // XXX: Try to inline skew
1618             // If skew is needed, apply skew and then anchor point
1619             if (needsSkewMatrix) {
1620                 var skewMatrix = cc.AffineTransformMake(1.0, Math.tan(cc.DEGREES_TO_RADIANS(this._skewY)),
1621                     Math.tan(cc.DEGREES_TO_RADIANS(this._skewX)), 1.0, 0.0, 0.0);
1622                 this._transform = cc.AffineTransformConcat(skewMatrix, this._transform);
1623 
1624                 // adjust anchor point
1625                 if (!cc.Point.CCPointEqualToPoint(this._anchorPointInPoints, cc.p(0, 0))) {
1626                     this._transform = cc.AffineTransformTranslate(this._transform, -this._anchorPointInPoints.x, -this._anchorPointInPoints.y);
1627                 }
1628             }
1629 
1630             this._transformDirty = false;
1631         }
1632 
1633         return this._transform;
1634     },
1635 
1636     /**
1637      * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.<br/>
1638      * The matrix is in Pixels.
1639      * @return {Number}
1640      */
1641     parentToNodeTransform:function () {
1642         if (this._inverseDirty) {
1643             this._inverse = cc.AffineTransformInvert(this.nodeToParentTransform());
1644             this._inverseDirty = false;
1645         }
1646 
1647         return this._inverse;
1648     },
1649 
1650     /**
1651      *  Retrusn the world affine transform matrix. The matrix is in Pixels.
1652      * @return {cc.AffineTransform}
1653      */
1654     nodeToWorldTransform:function () {
1655         var t = this.nodeToParentTransform();
1656         for (var p = this._parent; p != null; p = p.getParent()) {
1657             t = cc.AffineTransformConcat(t, p.nodeToParentTransform());
1658         }
1659         return t;
1660     },
1661 
1662     /**
1663      * Returns the inverse world affine transform matrix. The matrix is in Pixels.
1664      * @return {cc.AffineTransform}
1665      */
1666     worldToNodeTransform:function () {
1667         return cc.AffineTransformInvert(this.nodeToWorldTransform());
1668     },
1669 
1670     /**
1671      * Converts a Point to node (local) space coordinates. The result is in Points.
1672      * @param {cc.Point} worldPoint
1673      * @return {cc.Point}
1674      */
1675     convertToNodeSpace:function (worldPoint) {
1676         return cc.PointApplyAffineTransform(worldPoint, this.worldToNodeTransform());
1677     },
1678 
1679     /**
1680      * Converts a Point to world space coordinates. The result is in Points.
1681      * @param {cc.Point} nodePoint
1682      * @return {cc.Point}
1683      */
1684     convertToWorldSpace:function (nodePoint) {
1685         return cc.PointApplyAffineTransform(nodePoint, this.nodeToWorldTransform());
1686     },
1687 
1688     /**
1689      * Converts a Point to node (local) space coordinates. The result is in Points.<br/>
1690      * treating the returned/received node point as anchor relative.
1691      * @param {cc.Point} worldPoint
1692      * @return {cc.Point}
1693      */
1694     convertToNodeSpaceAR:function (worldPoint) {
1695         return cc.pSub(this.convertToNodeSpace(worldPoint), this._anchorPointInPoints);
1696     },
1697 
1698     /**
1699      * Converts a local Point to world space coordinates.The result is in Points.<br/>
1700      * treating the returned/received node point as anchor relative.
1701      * @param {cc.Point} nodePoint
1702      * @return {cc.Point}
1703      */
1704     convertToWorldSpaceAR:function (nodePoint) {
1705         var pt = cc.pAdd(nodePoint, this._anchorPointInPoints);
1706         return this.convertToWorldSpace(pt);
1707     },
1708 
1709     _convertToWindowSpace:function (nodePoint) {
1710         var worldPoint = this.convertToWorldSpace(nodePoint);
1711         return cc.Director.getInstance().convertToUI(worldPoint);
1712     },
1713 
1714     /** convenience methods which take a cc.Touch instead of cc.Point
1715      * @param {cc.Touch} touch
1716      * @return {cc.Point}
1717      */
1718     convertTouchToNodeSpace:function (touch) {
1719         var point = touch.getLocation();
1720         //TODO in canvas point don't convert to GL
1721         //point = cc.Director.getInstance().convertToGL(point);
1722         return this.convertToNodeSpace(point);
1723     },
1724 
1725     /**
1726      * converts a cc.Touch (world coordinates) into a local coordiante. This method is AR (Anchor Relative).
1727      * @param {cc.Touch}touch
1728      * @return {cc.Point}
1729      */
1730     convertTouchToNodeSpaceAR:function (touch) {
1731         var point = touch.getLocation();
1732         point = cc.Director.getInstance().convertToGL(point);
1733         return this.convertToNodeSpaceAR(point);
1734     },
1735 
1736     /** implement cc.Object's method (override me)
1737      * @param {Number} dt
1738      */
1739     update:function (dt) {
1740     },
1741 
1742     updateTransform:function(){
1743         // Recursively iterate over children
1744         this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
1745     },
1746 
1747     /**
1748      * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
1749      * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
1750      * This is a hack, and should be removed once JSB fixes the retain/release bug
1751      */
1752     retain:function () {
1753     },
1754     release:function () {
1755     }
1756 });
1757 
1758 /**
1759  * cc.Node's state callback type
1760  * @constant
1761  * @type Number
1762  */
1763 cc.Node.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7};
1764 
1765 
1766 /**
1767  * allocates and initializes a node.
1768  * @constructs
1769  * @return {cc.Node}
1770  * @example
1771  * // example
1772  * var node = cc.Node.create();
1773  */
1774 cc.Node.create = function () {
1775     return new cc.Node();
1776 };
1777 
1778