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