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