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