UNPKG

cocos2d-html5

Version:
1,323 lines (1,202 loc) 86 kB
/**************************************************************************** Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2008-2010 Ricardo Quesada Copyright (c) 2011 Zynga Inc. http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ /** * Default Node tag * @constant * @type Number */ cc.NODE_TAG_INVALID = -1; /** * Node on enter * @constant */ cc.NODE_ON_ENTER = null; /** * Node on exit * @constant */ cc.NODE_ON_EXIT = null; /** * 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. * @type Number */ cc.s_globalOrderOfArrival = 1; /** <p>cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.<br/> The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.<br/></p> <p>The main features of a cc.Node are: <br/> - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc) <br/> - They can schedule periodic callback (schedule, unschedule, etc) <br/> - They can execute actions (runAction, stopAction, etc) <br/></p> <p>Some cc.Node nodes provide extra functionality for them or their children.</p> <p>Subclassing a cc.Node usually means (one/all) of: <br/> - overriding init to initialize resources and schedule callbacks <br/> - create callbacks to handle the advancement of time <br/> - overriding draw to render the node <br/></p> <p>Features of cc.Node: <br/> - position <br/> - scale (x, y) <br/> - rotation (in degrees, clockwise) <br/> - anchor point<br/> - size <br/> - visible<br/> - z-order <br/> - openGL z position <br/></P> <p> Default values: <br/> - rotation: 0 <br/> - position: (x=0,y=0) <br/> - scale: (x=1,y=1) <br/> - contentSize: (x=0,y=0)<br/> - anchorPoint: (x=0,y=0)<br/></p> <p> Limitations:<br/> - A cc.Node is a "void" object. It doesn't have a texture <br/></P> <p>Order in transformations with grid disabled <br/> -# The node will be translated (position) <br/> -# The node will be rotated (rotation)<br/> -# The node will be scaled (scale) <br/> <p>Order in transformations with grid enabled<br/> -# The node will be translated (position)<br/> -# The node will be rotated (rotation) <br/> -# The node will be scaled (scale) <br/> -# The grid will capture the screen <br/> -# The node will be moved according to the camera values (camera) <br/> -# The grid will render the captured screen <br/></P> * @class * @extends cc.Class * @example * // example * cc.Sprite = cc.Node.extend({}); * cc.Sprite.initWithImage = function(){ * }; */ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ _zOrder:0, _vertexZ:0.0, _rotationX:0, _rotationY:0.0, _scaleX:1.0, _scaleY:1.0, _position:null, _skewX:0.0, _skewY:0.0, // children (lazy allocs), _children:null, // lazy alloc, _visible:true, _anchorPoint:null, _anchorPointInPoints:null, _contentSize:null, _running:false, _parent:null, // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true _ignoreAnchorPointForPosition:false, _tag:cc.NODE_TAG_INVALID, // userData is always inited as nil _userData:null, _userObject:null, _transformDirty:true, _inverseDirty:true, _cacheDirty:true, _transformGLDirty:null, _transform:null, _inverse:null, //since 2.0 api _reorderChildDirty:false, _shaderProgram:null, _orderOfArrival:0, _actionManager:null, _scheduler:null, _initializedNode:false, _additionalTransformDirty:false, _additionalTransform:null, _componentContainer:null, _isTransitionFinished:false, _rotationRadiansX:0, _rotationRadiansY:0, _initNode:function () { this._anchorPoint = cc._pConst(0, 0); this._anchorPointInPoints = cc._pConst(0, 0); this._contentSize = cc._sizeConst(0, 0); this._position = cc._pConst(0, 0); this._children = []; this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0}; var director = cc.Director.getInstance(); this._actionManager = director.getActionManager(); this._scheduler = director.getScheduler(); this._initializedNode = true; this._additionalTransform = cc.AffineTransformMakeIdentity(); if(cc.ComponentContainer){ this._componentContainer = new cc.ComponentContainer(this); } }, /** * Initializes the instance of cc.Node * @returns {boolean} Whether the initialization was successful. */ init:function () { if (this._initializedNode === false) this._initNode(); return true; }, /** * @param {Array} array * @param {cc.Node.StateCallbackType} callbackType * @private */ _arrayMakeObjectsPerformSelector:function (array, callbackType) { if (!array || array.length === 0) return; var i, len = array.length,node; var nodeCallbackType = cc.Node.StateCallbackType; switch (callbackType) { case nodeCallbackType.onEnter: for (i = 0; i < len; i++) { node = array[i]; if (node) node.onEnter(); } break; case nodeCallbackType.onExit: for (i = 0; i < len; i++) { node = array[i]; if (node) node.onExit(); } break; case nodeCallbackType.onEnterTransitionDidFinish: for (i = 0; i < len; i++) { node = array[i]; if (node) node.onEnterTransitionDidFinish(); } break; case nodeCallbackType.cleanup: for (i = 0; i < len; i++) { node = array[i]; if (node) node.cleanup(); } break; case nodeCallbackType.updateTransform: for (i = 0; i < len; i++) { node = array[i]; if (node) node.updateTransform(); } break; case nodeCallbackType.onExitTransitionDidStart: for (i = 0; i < len; i++) { node = array[i]; if (node) node.onExitTransitionDidStart(); } break; case nodeCallbackType.sortAllChildren: for (i = 0; i < len; i++) { node = array[i]; if (node) node.sortAllChildren(); } break; default : throw "Unknown callback function"; break; } }, /** * set the dirty node */ setNodeDirty:null, _setNodeDirtyForCanvas:function () { this._setNodeDirtyForCache(); if(this._transformDirty === false) this._transformDirty = this._inverseDirty = true; }, _setNodeDirtyForWebGL:function () { if(this._transformDirty === false) this._transformDirty = this._inverseDirty = true; }, /** * <p>get the skew degrees in X </br> * The X skew angle of the node in degrees. <br/> * This angle describes the shear distortion in the X direction.<br/> * Thus, it is the angle between the Y axis and the left edge of the shape </br> * The default skewX angle is 0. Positive values distort the node in a CW direction.</br> * </p> * @return {Number} The X skew angle of the node in degrees. */ getSkewX:function () { return this._skewX; }, /** * <p> * Changes the X skew angle of the node in degrees. <br/> * <br/> * This angle describes the shear distortion in the X direction. <br/> * Thus, it is the angle between the Y axis and the left edge of the shape <br/> * The default skewX angle is 0. Positive values distort the node in a CW direction. * </p> * @param {Number} newSkewX The X skew angle of the node in degrees. */ setSkewX:function (newSkewX) { this._skewX = newSkewX; this.setNodeDirty(); }, /** * <p>get the skew degrees in Y <br/> * The Y skew angle of the node in degrees. <br/> * This angle describes the shear distortion in the Y direction. <br/> * Thus, it is the angle between the X axis and the bottom edge of the shape <br/> * The default skewY angle is 0. Positive values distort the node in a CCW direction. <br/> * </p> * @return {Number} The Y skew angle of the node in degrees. */ getSkewY:function () { return this._skewY; }, /** * <p> * Changes the Y skew angle of the node in degrees. * * This angle describes the shear distortion in the Y direction. * Thus, it is the angle between the X axis and the bottom edge of the shape * The default skewY angle is 0. Positive values distort the node in a CCW direction. * </p> * @param {Number} newSkewY The Y skew angle of the node in degrees. */ setSkewY:function (newSkewY) { this._skewY = newSkewY; this.setNodeDirty(); }, /** * zOrder getter * @return {Number} */ getZOrder:function () { return this._zOrder; }, /** * <p> * Sets the z order which stands for the drawing order <br/> * <br/> * This is an internal method. Don't call it outside the framework. <br/> * The difference between setZOrder(int) and _setOrder(int) is: <br/> * - _setZOrder(int) is a pure setter for m_nZOrder member variable <br/> * - setZOrder(int) firstly changes m_nZOrder, then recorder this node in its parent's children array. * </p> * @param {Number} z * @private */ _setZOrder:function (z) { this._zOrder = z; }, /** * <p> * Sets the Z order which stands for the drawing order, and reorder this node in its parent's children array. <br/> * <br/> * The Z order of node is relative to its "brothers": children of the same parent. <br/> * It's nothing to do with OpenGL's z vertex. This one only affects the draw order of nodes in cocos2d. <br/> * The larger number it is, the later this node will be drawn in each message loop. <br/> * Please refer to setVertexZ(float) for the difference. * </p> * @param {Number} z Z order of this node. */ setZOrder:function (z) { this._setZOrder(z); if (this._parent) this._parent.reorderChild(this, z); }, /** * Gets WebGL Z vertex of this node. * @return {Number} WebGL Z vertex of this node */ getVertexZ:function () { return this._vertexZ; }, /** * <p> * Sets the real WebGL Z vertex. <br/> * <br/> * Differences between openGL Z vertex and cocos2d Z order: <br/> * - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children <br/> * - OpenGL Z might require to set 2D projection <br/> * - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0 <br/> * <br/> * @warning Use it at your own risk since it might break the cocos2d parent-children z order * </p> * @param {Number} Var */ setVertexZ:function (Var) { this._vertexZ = Var; }, /** * The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. * @return {Number} The rotation of the node in degrees. */ getRotation:function () { if(this._rotationX !== this._rotationY) cc.log("cc.Node.rotation(): RotationX != RotationY. Don't know which one to return"); return this._rotationX; }, /** * <p> * Sets the rotation (angle) of the node in degrees. <br/> * <br/> * 0 is the default rotation angle. <br/> * Positive values rotate node clockwise, and negative values for anti-clockwise. * </p> * @param {Number} newRotation The rotation of the node in degrees. */ setRotation:function (newRotation) { this._rotationX = this._rotationY = newRotation; this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, /** * The rotation (angle) of the node in degrees. 0 is the default rotation angle. <br/> * Positive values rotate node CW. It only modifies the X rotation performing a horizontal rotational skew . * (support only in WebGl rendering mode) * @return {Number} The X rotation in degrees. */ getRotationX:function () { return this._rotationX; }, /** * <p> * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew. <br/> * <br/> * 0 is the default rotation angle. <br/> * Positive values rotate node clockwise, and negative values for anti-clockwise. * </p> * @param {Number} rotationX The X rotation in degrees which performs a horizontal rotational skew. */ setRotationX:function (rotationX) { this._rotationX = rotationX; this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, /** * The rotation (angle) of the node in degrees. 0 is the default rotation angle. <br/> * Positive values rotate node CW. It only modifies the Y rotation performing a vertical rotational skew . * @return {Number} The Y rotation in degrees. */ getRotationY:function () { return this._rotationY; }, /** * <p> * Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew. <br/> * <br/> * 0 is the default rotation angle. <br/> * Positive values rotate node clockwise, and negative values for anti-clockwise. * </p> * @param rotationY The Y rotation in degrees. */ setRotationY:function (rotationY) { this._rotationY = rotationY; this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, /** Get the scale factor of the node. * @warning: Assert when _scaleX != _scaleY. * @return {Number} */ getScale:function () { if(this._scaleX !== this._scaleY) cc.log("cc.Node.getScale(): ScaleX != ScaleY. Don't know which one to return"); return this._scaleX; }, /** * The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. * @param {Number} scale or scaleX value * @param {Number} [scaleY=] */ setScale:function (scale, scaleY) { this._scaleX = scale; this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale; this.setNodeDirty(); }, /** * Returns the scale factor on X axis of this node * @return {Number} The scale factor on X axis. */ getScaleX:function () { return this._scaleX; }, /** * <p> * Changes the scale factor on X axis of this node <br/> * The deafult value is 1.0 if you haven't changed it before * </p> * @param {Number} newScaleX The scale factor on X axis. */ setScaleX:function (newScaleX) { this._scaleX = newScaleX; this.setNodeDirty(); }, /** * Returns the scale factor on Y axis of this node * @return {Number} The scale factor on Y axis. */ getScaleY:function () { return this._scaleY; }, /** * <p> * Changes the scale factor on Y axis of this node <br/> * The Default value is 1.0 if you haven't changed it before. * </p> * @param {Number} newScaleY The scale factor on Y axis. */ setScaleY:function (newScaleY) { this._scaleY = newScaleY; this.setNodeDirty(); }, /** * <p> * Changes the position (x,y) of the node in OpenGL coordinates * Usually we use ccp(x,y) to compose CCPoint object. * The original point (0,0) is at the left-bottom corner of screen. * and Passing two numbers (x,y) is much efficient than passing CCPoint object. * </p> * @param {cc.Point|Number} newPosOrxValue The position (x,y) of the node in coordinates or X coordinate for position * @param {Number} [yValue] Y coordinate for position * @example * var size = cc.Director.getInstance().getWinSize(); * node.setPosition(size.width/2, size.height/2); */ setPosition:function (newPosOrxValue, yValue) { var locPosition = this._position; if (arguments.length == 2) { locPosition._x = newPosOrxValue; locPosition._y = yValue; } else if (arguments.length == 1) { locPosition._x = newPosOrxValue.x; locPosition._y = newPosOrxValue.y; } this.setNodeDirty(); }, /** * <p>Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner. </p> * @const * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates */ getPosition:function () { return this._position; }, /** * @return {Number} */ getPositionX:function () { return this._position._x; }, /** * @param {Number} x */ setPositionX:function (x) { this._position._x = x; this.setNodeDirty(); }, /** * @return {Number} */ getPositionY:function () { return this._position._y; }, /** * @param {Number} y */ setPositionY:function (y) { this._position._y = y; this.setNodeDirty(); }, /** * Get the amount of children. * @return {Number} The amount of children. */ getChildrenCount:function () { return this._children.length; }, /** * Return an array of children <br/> * Composing a "tree" structure is a very important feature of CCNode * @return {Array} An array of children * @example * //This sample code traverses all children nodes, and set their position to (0,0) * var allChildren = parent.getChildren(); * for(var i = 0; i< allChildren.length; i++) { * allChildren[i].setPosition(0,0); * } */ getChildren:function () { return this._children; }, /** * Determines if the node is visible * @see setVisible(bool) * @return {Boolean} true if the node is visible, false if the node is hidden. */ isVisible:function () { return this._visible; }, /** * Sets whether the node is visible <br/> * The default value is true, a node is default to visible * @param {Boolean} Var true if the node is visible, false if the node is hidden. */ setVisible:function (Var) { this._visible = Var; this.setNodeDirty(); }, /** * <p>anchorPoint is the point around which all transformations and positioning manipulations take place.<br/> * It's like a pin in the node where it is "attached" to its parent. <br/> * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/> * But you can use values higher than (1,1) and lower than (0,0) too. <br/> * The default anchorPoint is (0.5,0.5), so it starts in the center of the node. <br/></p> * @const * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { return this._anchorPoint; }, /** * <p> * Sets the anchor point in percent. <br/> * <br/> * anchorPoint is the point around which all transformations and positioning manipulations take place. <br/> * It's like a pin in the node where it is "attached" to its parent. <br/> * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/> * But you can use values higher than (1,1) and lower than (0,0) too. <br/> * The default anchorPoint is (0.5,0.5), so it starts in the center of the node. * </p> * @param {cc.Point|Number} point The anchor point of node or The anchor point.x of node. * @param {Number} [y] The anchor point.y of node. */ setAnchorPoint:function (point, y) { var locAnchorPoint = this._anchorPoint; if (arguments.length === 2) { if ((point === locAnchorPoint._x) && (y === locAnchorPoint._y)) return; locAnchorPoint._x = point; locAnchorPoint._y = y; } else { if ((point.x === locAnchorPoint._x) && (point.y === locAnchorPoint._y)) return; locAnchorPoint._x = point.x; locAnchorPoint._y = point.y; } var locAPP = this._anchorPointInPoints, locSize = this._contentSize; locAPP._x = locSize._width * locAnchorPoint._x; locAPP._y = locSize._height * locAnchorPoint._y; this.setNodeDirty(); }, /** * The anchorPoint in absolute pixels. <br/> * you can only read it. If you wish to modify it, use anchorPoint instead * @see getAnchorPoint() * @const * @return {cc.Point} The anchor point in absolute pixels. */ getAnchorPointInPoints:function () { return this._anchorPointInPoints; }, /** * <p>The untransformed size of the node. <br/> * The contentSize remains the same no matter the node is scaled or rotated.<br/> * All nodes has a size. Layer and Scene has the same size of the screen. <br/></p> * @const * @return {cc.Size} The untransformed size of the node. */ getContentSize:function () { return this._contentSize; }, /** * <p> * Sets the untransformed size of the node. <br/> * <br/> * The contentSize remains the same no matter the node is scaled or rotated. <br/> * All nodes has a size. Layer and Scene has the same size of the screen. * </p> * @param {cc.Size|Number} size The untransformed size of the node or The untransformed size's width of the node. * @param {Number} [height] The untransformed size's height of the node. */ setContentSize:function (size, height) { var locContentSize = this._contentSize; if (arguments.length === 2) { if ((size === locContentSize._width) && (height === locContentSize._height)) return; locContentSize._width = size; locContentSize._height = height; } else { if ((size.width === locContentSize._width) && (size.height === locContentSize._height)) return; locContentSize._width = size.width; locContentSize._height = size.height; } var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint; locAPP._x = locContentSize._width * locAnchorPoint._x; locAPP._y = locContentSize._height * locAnchorPoint._y; this.setNodeDirty(); }, /** * <p> * Returns whether or not the node accepts event callbacks. <br/> * Running means the node accept event callbacks like onEnter(), onExit(), update() * </p> * @return {Boolean} Whether or not the node is running. */ isRunning:function () { return this._running; }, /** * Returns a pointer to the parent node * @return {cc.Node} A pointer to the parent node */ getParent:function () { return this._parent; }, /** * Sets the parent node * @param {cc.Node} Var A pointer to the parent node */ setParent:function (Var) { this._parent = Var; }, /** * Gets whether the anchor point will be (0,0) when you position this node. * @see ignoreAnchorPointForPosition(bool) * @return {Boolean} true if the anchor point will be (0,0) when you position this node. */ isIgnoreAnchorPointForPosition:function () { return this._ignoreAnchorPointForPosition; }, /** * <p> * Sets whether the anchor point will be (0,0) when you position this node. <br/> * <br/> * This is an internal method, only used by CCLayer and CCScene. Don't call it outside framework. <br/> * The default value is false, while in CCLayer and CCScene are true * </p> * @param {Boolean} newValue true if anchor point will be (0,0) when you position this node */ ignoreAnchorPointForPosition:function (newValue) { if (newValue != this._ignoreAnchorPointForPosition) { this._ignoreAnchorPointForPosition = newValue; this.setNodeDirty(); } }, /** * Returns a tag that is used to identify the node easily. * * @return {Number} An integer that identifies the node. * @example * //You can set tags to node then identify them easily. * // set tags * node1.setTag(TAG_PLAYER); * node2.setTag(TAG_MONSTER); * node3.setTag(TAG_BOSS); * parent.addChild(node1); * parent.addChild(node2); * parent.addChild(node3); * // identify by tags * var allChildren = parent.getChildren(); * for(var i = 0; i < allChildren.length; i++){ * switch(node.getTag()) { * case TAG_PLAYER: * break; * case TAG_MONSTER: * break; * case TAG_BOSS: * break; * } * } */ getTag:function () { return this._tag; }, /** * Changes the tag that is used to identify the node easily. <br/> * Please refer to getTag for the sample code. * @param {Number} Var A integer that identifies the node. */ setTag:function (Var) { this._tag = Var; }, /** * <p> * Returns a custom user data pointer <br/> * You can set everything in UserData pointer, a data block, a structure or an object. * </p> * @return {object} A custom user data pointer */ getUserData:function () { return this._userData; }, /** * <p> * Sets a custom user data pointer <br/> * You can set everything in UserData pointer, a data block, a structure or an object, etc. * </p> * @warning Don't forget to release the memory manually,especially before you change this data pointer, and before this node is autoreleased. * @param {object} Var A custom user data */ setUserData:function (Var) { this._userData = Var; }, /** * Returns a user assigned CCObject. <br/> * Similar to userData, but instead of holding a void* it holds an id * @return {object} A user assigned CCObject */ getUserObject:function () { return this._userObject; }, /** * <p> * Returns a user assigned CCObject <br/> * Similar to UserData, but instead of holding a void* it holds an object. <br/> * The UserObject will be retained once in this method, and the previous UserObject (if existed) will be release. <br/> * The UserObject will be released in CCNode's destruction. * </p> * @param {object} newValue A user assigned CCObject */ setUserObject:function (newValue) { if (this._userObject != newValue) { this._userObject = newValue; } }, /** * Returns the arrival order, indicates which children is added previously. * @return {Number} The arrival order. */ getOrderOfArrival:function () { return this._orderOfArrival; }, /** * <p> * Sets the arrival order when this node has a same ZOrder with other children. <br/> * <br/> * A node which called addChild subsequently will take a larger arrival order, <br/> * If two children have the same Z order, the child with larger arrival order will be drawn later. * </p> * @warning This method is used internally for zOrder sorting, don't change this manually * @param {Number} Var The arrival order. */ setOrderOfArrival:function (Var) { this._orderOfArrival = Var; }, /** * <p>Gets the CCActionManager object that is used by all actions.<br/> * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)</p> * @see setActionManager() * @return {cc.ActionManager} A CCActionManager object. */ getActionManager:function () { if (!this._actionManager) { this._actionManager = cc.Director.getInstance().getActionManager(); } return this._actionManager; }, /** * <p>Sets the cc.ActionManager object that is used by all actions. </p> * @warning If you set a new CCActionManager, then previously created actions will be removed. * @param {cc.ActionManager} actionManager A CCActionManager object that is used by all actions. */ setActionManager:function (actionManager) { if (this._actionManager != actionManager) { this.stopAllActions(); this._actionManager = actionManager; } }, /** * <p> * cc.Scheduler used to schedule all "updates" and timers.<br/> * IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed. * </p> * @return {cc.Scheduler} A CCScheduler object. */ getScheduler:function () { if (!this._scheduler) { this._scheduler = cc.Director.getInstance().getScheduler(); } return this._scheduler; }, /** * <p> * Sets a CCScheduler object that is used to schedule all "updates" and timers. <br/> * </p> * @warning If you set a new CCScheduler, then previously created timers/update are going to be removed. * @param scheduler A cc.Scheduler object that is used to schedule all "update" and timers. */ setScheduler:function (scheduler) { if (this._scheduler != scheduler) { this.unscheduleAllCallbacks(); this._scheduler = scheduler; } }, /** * Returns a "local" axis aligned bounding box of the node. <br/> * The returned box is relative only to its parent. * @note This method returns a temporary variable, so it can't returns const CCRect& * @const * @return {cc.Rect} */ getBoundingBox:function () { var rect = cc.rect(0, 0, this._contentSize._width, this._contentSize._height); return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform()); }, /** * Stops all running actions and schedulers */ cleanup:function () { // actions this.stopAllActions(); this.unscheduleAllCallbacks(); // timers this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup); }, /** * Gets the description string. It makes debugging easier. * @return {String} */ description:function () { return "<cc.Node | Tag =" + this._tag + ">"; }, // composition: GET /** * Gets a child from the container given its tag * @param {Number} aTag An identifier to find the child node. * @return {cc.Node} a CCNode object whose tag equals to the input parameter */ getChildByTag:function (aTag) { var __children = this._children; if (__children != null) { for (var i = 0; i < __children.length; i++) { var node = __children[i]; if (node && node._tag == aTag) return node; } } //throw "not found"; return null; }, // composition: ADD /** <p>"add" logic MUST only be on this method <br/> </p> * * <p>If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.</p> * * @param {cc.Node} child A child node * @param {Number} [zOrder=] Z order for drawing priority. Please refer to setZOrder(int) * @param {Number} [tag=] A integer to identify the node easily. Please refer to setTag(int) */ addChild:function (child, zOrder, tag) { if(!child) throw "cc.Node.addChild(): child must be non-null"; if (child === this) { cc.log('cc.Node.addChild(): An Node can\'t be added as a child of itself.'); return; } if (child._parent !== null) { cc.log("cc.Node.addChild(): child already added. It can't be added again"); return; } var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder; child._tag = (tag != null) ? tag : child._tag; this._insertChild(child, tmpzOrder); child._parent = this; if (this._running) { child.onEnter(); // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter if(this._isTransitionFinished) child.onEnterTransitionDidFinish(); } }, // composition: REMOVE /** * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks. <br/> * If the cleanup parameter is not passed, it will force a cleanup. <br/> * If the node orphan, then nothing happens. * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. * @see removeFromParentAndCleanup(bool) */ removeFromParent:function (cleanup) { if (this._parent) { if (cleanup == null) cleanup = true; this._parent.removeChild(this, cleanup); } }, /** * Removes this node itself from its parent node. <br/> * If the node orphan, then nothing happens. * @deprecated * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. */ removeFromParentAndCleanup:function (cleanup) { cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead"); this.removeFromParent(cleanup); }, /** <p>Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. </p> * If the cleanup parameter is not passed, it will force a cleanup. <br/> *<p> "remove" logic MUST only be on this method <br/> * If a class wants to extend the 'removeChild' behavior it only needs <br/> * to override this method </p> * * @param {cc.Node} child The child node which will be removed. * @param {Boolean|null} [cleanup=null] true if all running actions and callbacks on the child node will be cleanup, false otherwise. */ removeChild:function (child, cleanup) { // explicit nil handling if (this._children.length === 0) return; if (cleanup == null) cleanup = true; if (this._children.indexOf(child) > -1) this._detachChild(child, cleanup); this.setNodeDirty(); }, /** * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter. * If the cleanup parameter is not passed, it will force a cleanup. <br/> * @param {Number} tag An integer number that identifies a child node * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. * @see removeChildByTag(int, bool) */ removeChildByTag:function (tag, cleanup) { if(tag === cc.NODE_TAG_INVALID) cc.log("cc.Node.removeChildByTag(): argument tag is an invalid tag"); var child = this.getChildByTag(tag); if (child == null) cc.log("cocos2d: removeChildByTag(tag = " + tag + "): child not found!"); else this.removeChild(child, cleanup); }, /** * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. * @deprecated * @param {Boolean | null } cleanup */ removeAllChildrenWithCleanup:function (cleanup) { cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead"); this.removeAllChildren(cleanup); }, /** * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. <br/> * If the cleanup parameter is not passed, it will force a cleanup. <br/> * @param {Boolean | null } cleanup true if all running actions on all children nodes should be cleanup, false otherwise. */ removeAllChildren:function (cleanup) { // not using detachChild improves speed here var __children = this._children; if (__children != null) { if (cleanup == null) cleanup = true; for (var i = 0; i < __children.length; i++) { var node = __children[i]; if (node) { // IMPORTANT: // -1st do onExit // -2nd cleanup if (this._running) { node.onExitTransitionDidStart(); node.onExit(); } if (cleanup) node.cleanup(); // set parent nil at the end node.setParent(null); } } this._children.length = 0; } }, /** * @param {cc.Node} child * @param {Boolean} doCleanup * @private */ _detachChild:function (child, doCleanup) { // IMPORTANT: // -1st do onExit // -2nd cleanup if (this._running) { child.onExitTransitionDidStart(); child.onExit(); } // If you don't do cleanup, the child's actions will not get removed and the // its scheduledSelectors_ dict will not get released! if (doCleanup) child.cleanup(); // set parent nil at the end child.setParent(null); cc.ArrayRemoveObject(this._children, child); }, /** helper used by reorderChild & add * @param {cc.Node} child * @param {Number} z * @private */ _insertChild:function (child, z) { this._reorderChildDirty = true; this._children.push(child); child._setZOrder(z); }, /** Reorders a child according to a new z value. <br/> * The child MUST be already added. * @param {cc.Node} child An already added child node. It MUST be already added. * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) */ reorderChild:function (child, zOrder) { if(!child) throw "cc.Node.reorderChild(): child must be non-null"; this._reorderChildDirty = true; child.setOrderOfArrival(cc.s_globalOrderOfArrival++); child._setZOrder(zOrder); this.setNodeDirty(); }, /** * <p> * Sorts the children array once before drawing, instead of every time when a child is added or reordered. <br/> * This approach can improves the performance massively. * </p> * @note Don't call this manually unless a child added needs to be removed in the same frame */ sortAllChildren:function () { if (this._reorderChildDirty) { var _children = this._children; var i, j, length = _children.length,tempChild; // insertion sort for (i = 0; i < length; i++) { var tempItem = _children[i]; j = i - 1; tempChild = _children[j]; //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { _children[j + 1] = tempChild; j = j - 1; tempChild = _children[j]; } _children[j + 1] = tempItem; } //don't need to check children recursively, that's done in visit of each child this._reorderChildDirty = false; } }, // draw /** <p>Override this method to draw your own node. <br/> * The following GL states will be enabled by default: <br/> - glEnableClientState(GL_VERTEX_ARRAY); <br/> - glEnableClientState(GL_COLOR_ARRAY); <br/> - glEnableClientState(GL_TEXTURE_COORD_ARRAY); <br/> - glEnable(GL_TEXTURE_2D); </p> <p>AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE</p> <p>But if you enable any other GL state, you should disable it after drawing your node. </p> * @param {CanvasContext} ctx */ draw:function (ctx) { // override me // Only use- this function to draw your staff. // DON'T draw your stuff outside this method }, /** performs OpenGL view-matrix transformation of it's ancestors.<br/> * Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) <br/> * it's necessary to transform the ancestors again. */ transformAncestors:function () { if (this._parent != null) { this._parent.transformAncestors(); this._parent.transform(); } }, //scene managment /** * <p> * Event callback that is invoked every time when CCNode enters the 'stage'. <br/> * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts. <br/> * During onEnter you can't access a "sister/brother" node. <br/> * If you override onEnter, you shall call its parent's one, e.g., CCNode::onEnter(). * </p> */ onEnter:function () { this._isTransitionFinished = false; this._running = true;//should be running before resumeSchedule this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnter); this.resumeSchedulerAndActions(); }, /** * <p> * Event callback that is invoked when the CCNode enters in the 'stage'. <br/> * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes. <br/> * If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. CCNode::onEnterTransitionDidFinish() * </p> */ onEnterTransitionDidFinish:function () { this._isTransitionFinished = true; this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnterTransitionDidFinish); }, /** * <p>callback that is called every time the cc.Node leaves the 'stage'. <br/> * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. </p> */ onExitTransitionDidStart:function () { this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExitTransitionDidStart); }, /** * <p> * callback that is called every time the cc.Node leaves the 'stage'. <br/> * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/> * During onExit you can't access a sibling node. <br/> * If you override onExit, you shall call its parent's one, e.g., CCNode::onExit(). * </p> */ onExit:function () { this._running = false; this.pauseSchedulerAndActions(); this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExit); if(this._componentContainer){ this._componentContainer.removeAll(); } }, // actions /** * Executes an action, and returns the action that is executed.<br/> * The node becomes the action's target. Refer to CCAction::getTarget() * @warning Starting from v0.8 actions don't retain their target anymore. * @param {cc.Action} action * @return {cc.Action} An Action pointer */ runAction:function (action) { if(!action) throw "cc.Node.runAction(): action must be non-null"; this.getActionManager().addAction(action, this, !this._running); return action; }, /** * Stops and removes all actions from the running action list . */ stopAllActions:function () { this.getActionManager().removeAllActionsFromTarget(this); }, /** * Stops and removes an action from t