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 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.orderDirty); 1450 }, 1451 1452 /** 1453 * <p> 1454 * Sorts the children array once before drawing, instead of every time when a child is added or reordered. <br/> 1455 * This approach can improves the performance massively. 1456 * </p> 1457 * @function 1458 * @note Don't call this manually unless a child added needs to be removed in the same frame 1459 */ 1460 sortAllChildren: function () { 1461 if (this._reorderChildDirty) { 1462 var _children = this._children; 1463 1464 // insertion sort 1465 var len = _children.length, i, j, tmp; 1466 for(i=1; i<len; i++){ 1467 tmp = _children[i]; 1468 j = i - 1; 1469 1470 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 1471 while(j >= 0){ 1472 if(tmp._localZOrder < _children[j]._localZOrder){ 1473 _children[j+1] = _children[j]; 1474 }else if(tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder){ 1475 _children[j+1] = _children[j]; 1476 }else{ 1477 break; 1478 } 1479 j--; 1480 } 1481 _children[j+1] = tmp; 1482 } 1483 1484 //don't need to check children recursively, that's done in visit of each child 1485 this._reorderChildDirty = false; 1486 } 1487 }, 1488 1489 /** 1490 * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function 1491 * @function 1492 * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context 1493 */ 1494 draw: function (ctx) { 1495 // override me 1496 // Only use- this function to draw your staff. 1497 // DON'T draw your stuff outside this method 1498 }, 1499 1500 // Internal use only, do not call it by yourself, 1501 transformAncestors: function () { 1502 if (this._parent !== null) { 1503 this._parent.transformAncestors(); 1504 this._parent.transform(); 1505 } 1506 }, 1507 1508 //scene managment 1509 /** 1510 * <p> 1511 * Event callback that is invoked every time when CCNode enters the 'stage'. <br/> 1512 * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts. <br/> 1513 * During onEnter you can't access a "sister/brother" node. <br/> 1514 * If you override onEnter, you must call its parent's onEnter function with this._super(). 1515 * </p> 1516 * @function 1517 */ 1518 onEnter: function () { 1519 this._isTransitionFinished = false; 1520 this._running = true;//should be running before resumeSchedule 1521 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onEnter); 1522 this.resume(); 1523 }, 1524 1525 /** 1526 * <p> 1527 * Event callback that is invoked when the CCNode enters in the 'stage'. <br/> 1528 * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes. <br/> 1529 * If you override onEnterTransitionDidFinish, you shall call its parent's onEnterTransitionDidFinish with this._super() 1530 * </p> 1531 * @function 1532 */ 1533 onEnterTransitionDidFinish: function () { 1534 this._isTransitionFinished = true; 1535 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onEnterTransitionDidFinish); 1536 }, 1537 1538 /** 1539 * <p>callback that is called every time the cc.Node leaves the 'stage'. <br/> 1540 * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. <br/> 1541 * If you override onExitTransitionDidStart, you shall call its parent's onExitTransitionDidStart with this._super()</p> 1542 * @function 1543 */ 1544 onExitTransitionDidStart: function () { 1545 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onExitTransitionDidStart); 1546 }, 1547 1548 /** 1549 * <p> 1550 * callback that is called every time the cc.Node leaves the 'stage'. <br/> 1551 * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/> 1552 * During onExit you can't access a sibling node. <br/> 1553 * If you override onExit, you shall call its parent's onExit with this._super(). 1554 * </p> 1555 * @function 1556 */ 1557 onExit: function () { 1558 this._running = false; 1559 this.pause(); 1560 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onExit); 1561 this.removeAllComponents(); 1562 }, 1563 1564 // actions 1565 /** 1566 * Executes an action, and returns the action that is executed.<br/> 1567 * The node becomes the action's target. Refer to cc.Action's getTarget() 1568 * @function 1569 * @warning Starting from v0.8 actions don't retain their target anymore. 1570 * @param {cc.Action} action 1571 * @return {cc.Action} An Action pointer 1572 */ 1573 runAction: function (action) { 1574 cc.assert(action, cc._LogInfos.Node_runAction); 1575 1576 this.actionManager.addAction(action, this, !this._running); 1577 return action; 1578 }, 1579 1580 /** 1581 * Stops and removes all actions from the running action list . 1582 * @function 1583 */ 1584 stopAllActions: function () { 1585 this.actionManager && this.actionManager.removeAllActionsFromTarget(this); 1586 }, 1587 1588 /** 1589 * Stops and removes an action from the running action list. 1590 * @function 1591 * @param {cc.Action} action An action object to be removed. 1592 */ 1593 stopAction: function (action) { 1594 this.actionManager.removeAction(action); 1595 }, 1596 1597 /** 1598 * Removes an action from the running action list by its tag. 1599 * @function 1600 * @param {Number} tag A tag that indicates the action to be removed. 1601 */ 1602 stopActionByTag: function (tag) { 1603 if (tag === cc.ACTION_TAG_INVALID) { 1604 cc.log(cc._LogInfos.Node_stopActionByTag); 1605 return; 1606 } 1607 this.actionManager.removeActionByTag(tag, this); 1608 }, 1609 1610 /** 1611 * Returns an action from the running action list by its tag. 1612 * @function 1613 * @see cc.Node#getTag and cc.Node#setTag 1614 * @param {Number} tag 1615 * @return {cc.Action} The action object with the given tag. 1616 */ 1617 getActionByTag: function (tag) { 1618 if (tag === cc.ACTION_TAG_INVALID) { 1619 cc.log(cc._LogInfos.Node_getActionByTag); 1620 return null; 1621 } 1622 return this.actionManager.getActionByTag(tag, this); 1623 }, 1624 1625 /** <p>Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).<br/> 1626 * Composable actions are counted as 1 action. Example:<br/> 1627 * If you are running 1 Sequence of 7 actions, it will return 1. <br/> 1628 * If you are running 7 Sequences of 2 actions, it will return 7.</p> 1629 * @function 1630 * @return {Number} The number of actions that are running plus the ones that are schedule to run 1631 */ 1632 getNumberOfRunningActions: function () { 1633 return this.actionManager.numberOfRunningActionsInTarget(this); 1634 }, 1635 1636 // cc.Node - Callbacks 1637 // timers 1638 /** 1639 * <p>schedules the "update" method. <br/> 1640 * It will use the order number 0. This method will be called every frame. <br/> 1641 * Scheduled methods with a lower order value will be called before the ones that have a higher order value.<br/> 1642 * Only one "update" method could be scheduled per node.</p> 1643 * @function 1644 */ 1645 scheduleUpdate: function () { 1646 this.scheduleUpdateWithPriority(0); 1647 }, 1648 1649 /** 1650 * <p> 1651 * schedules the "update" callback function with a custom priority. 1652 * This callback function will be called every frame.<br/> 1653 * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.<br/> 1654 * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).<br/> 1655 * </p> 1656 * @function 1657 * @param {Number} priority 1658 */ 1659 scheduleUpdateWithPriority: function (priority) { 1660 this.scheduler.scheduleUpdate(this, priority, !this._running); 1661 }, 1662 1663 /** 1664 * Unschedules the "update" method. 1665 * @function 1666 * @see cc.Node#scheduleUpdate 1667 */ 1668 unscheduleUpdate: function () { 1669 this.scheduler.unscheduleUpdate(this); 1670 }, 1671 1672 /** 1673 * <p>Schedules a custom selector. <br/> 1674 * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.</p> 1675 * @function 1676 * @param {function} callback A function wrapped as a selector 1677 * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead. 1678 * @param {Number} repeat The selector will be executed (repeat + 1) times, you can use kCCRepeatForever for tick infinitely. 1679 * @param {Number} delay The amount of time that the first tick will wait before execution. 1680 * @param {String} key The only string identifying the callback 1681 */ 1682 schedule: function (callback, interval, repeat, delay, key) { 1683 var len = arguments.length; 1684 if(typeof callback === "function"){ 1685 //callback, interval, repeat, delay, key 1686 if(len === 1){ 1687 //callback 1688 interval = 0; 1689 repeat = cc.REPEAT_FOREVER; 1690 delay = 0; 1691 key = this.__instanceId; 1692 }else if(len === 2){ 1693 if(typeof interval === "number"){ 1694 //callback, interval 1695 repeat = cc.REPEAT_FOREVER; 1696 delay = 0; 1697 key = this.__instanceId; 1698 }else{ 1699 //callback, key 1700 key = interval; 1701 interval = 0; 1702 repeat = cc.REPEAT_FOREVER; 1703 delay = 0; 1704 } 1705 }else if(len === 3){ 1706 if(typeof repeat === "string"){ 1707 //callback, interval, key 1708 key = repeat; 1709 repeat = cc.REPEAT_FOREVER; 1710 }else{ 1711 //callback, interval, repeat 1712 key = this.__instanceId; 1713 } 1714 delay = 0; 1715 }else if(len === 4){ 1716 key = this.__instanceId; 1717 } 1718 }else{ 1719 //selector 1720 //selector, interval 1721 //selector, interval, repeat, delay 1722 if(len === 1){ 1723 interval = 0; 1724 repeat = cc.REPEAT_FOREVER; 1725 delay = 0; 1726 }else if(len === 2){ 1727 repeat = cc.REPEAT_FOREVER; 1728 delay = 0; 1729 } 1730 } 1731 1732 cc.assert(callback, cc._LogInfos.Node_schedule); 1733 cc.assert(interval >= 0, cc._LogInfos.Node_schedule_2); 1734 1735 interval = interval || 0; 1736 repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat; 1737 delay = delay || 0; 1738 1739 this.scheduler.schedule(callback, this, interval, repeat, delay, !this._running, key); 1740 }, 1741 1742 /** 1743 * Schedules a callback function that runs only once, with a delay of 0 or larger 1744 * @function 1745 * @see cc.Node#schedule 1746 * @param {function} callback A function wrapped as a selector 1747 * @param {Number} delay The amount of time that the first tick will wait before execution. 1748 * @param {String} key The only string identifying the callback 1749 */ 1750 scheduleOnce: function (callback, delay, key) { 1751 //selector, delay 1752 //callback, delay, key 1753 if(key === undefined) 1754 key = this.__instanceId; 1755 this.schedule(callback, 0, 0, delay, key); 1756 }, 1757 1758 /** 1759 * unschedules a custom callback function. 1760 * @function 1761 * @see cc.Node#schedule 1762 * @param {function} callback_fn A function wrapped as a selector 1763 */ 1764 unschedule: function (callback_fn) { 1765 //key 1766 //selector 1767 if (!callback_fn) 1768 return; 1769 1770 this.scheduler.unschedule(callback_fn, this); 1771 }, 1772 1773 /** 1774 * <p>unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.<br/> 1775 * Actions are not affected by this method.</p> 1776 * @function 1777 */ 1778 unscheduleAllCallbacks: function () { 1779 this.scheduler.unscheduleAllForTarget(this); 1780 }, 1781 1782 /** 1783 * Resumes all scheduled selectors and actions.<br/> 1784 * This method is called internally by onEnter 1785 * @function 1786 * @deprecated since v3.0, please use resume() instead 1787 */ 1788 resumeSchedulerAndActions: function () { 1789 cc.log(cc._LogInfos.Node_resumeSchedulerAndActions); 1790 this.resume(); 1791 }, 1792 1793 /** 1794 * <p>Resumes all scheduled selectors and actions.<br/> 1795 * This method is called internally by onEnter</p> 1796 */ 1797 resume: function () { 1798 this.scheduler.resumeTarget(this); 1799 this.actionManager && this.actionManager.resumeTarget(this); 1800 cc.eventManager.resumeTarget(this); 1801 }, 1802 1803 /** 1804 * <p>Pauses all scheduled selectors and actions.<br/> 1805 * This method is called internally by onExit</p> 1806 * @deprecated since v3.0, please use pause instead 1807 * @function 1808 */ 1809 pauseSchedulerAndActions: function () { 1810 cc.log(cc._LogInfos.Node_pauseSchedulerAndActions); 1811 this.pause(); 1812 }, 1813 1814 /** 1815 * <p>Pauses all scheduled selectors and actions.<br/> 1816 * This method is called internally by onExit</p> 1817 * @function 1818 */ 1819 pause: function () { 1820 this.scheduler.pauseTarget(this); 1821 this.actionManager && this.actionManager.pauseTarget(this); 1822 cc.eventManager.pauseTarget(this); 1823 }, 1824 1825 /** 1826 *<p>Sets the additional transform.<br/> 1827 * The additional transform will be concatenated at the end of getNodeToParentTransform.<br/> 1828 * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).<br/> 1829 * </p> 1830 * @function 1831 * @param {cc.AffineTransform} additionalTransform The additional transform 1832 * @example 1833 * // create a batchNode 1834 * var batch = new cc.SpriteBatchNode("Icon-114.png"); 1835 * this.addChild(batch); 1836 * 1837 * // create two sprites, spriteA will be added to batchNode, they are using different textures. 1838 * var spriteA = new cc.Sprite(batch->getTexture()); 1839 * var spriteB = new cc.Sprite("Icon-72.png"); 1840 * 1841 * batch.addChild(spriteA); 1842 * 1843 * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer. 1844 * // But we want to simulate `parent-child` relationship for these two node. 1845 * this.addChild(spriteB); 1846 * 1847 * //position 1848 * spriteA.setPosition(ccp(200, 200)); 1849 * 1850 * // Gets the spriteA's transform. 1851 * var t = spriteA.getNodeToParentTransform(); 1852 * 1853 * // Sets the additional transform to spriteB, spriteB's position will based on its pseudo parent i.e. spriteA. 1854 * spriteB.setAdditionalTransform(t); 1855 * 1856 * //scale 1857 * spriteA.setScale(2); 1858 * 1859 * // Gets the spriteA's transform. 1860 * t = spriteA.getNodeToParentTransform(); 1861 * 1862 * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA. 1863 * spriteB.setAdditionalTransform(t); 1864 * 1865 * //rotation 1866 * spriteA.setRotation(20); 1867 * 1868 * // Gets the spriteA's transform. 1869 * t = spriteA.getNodeToParentTransform(); 1870 * 1871 * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA. 1872 * spriteB.setAdditionalTransform(t); 1873 */ 1874 setAdditionalTransform: function (additionalTransform) { 1875 if(additionalTransform === undefined) 1876 return this._additionalTransformDirty = false; 1877 this._additionalTransform = additionalTransform; 1878 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 1879 this._additionalTransformDirty = true; 1880 }, 1881 1882 /** 1883 * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.<br/> 1884 * The matrix is in Pixels. 1885 * @function 1886 * @return {cc.AffineTransform} 1887 */ 1888 getParentToNodeTransform: function () { 1889 this._renderCmd.getParentToNodeTransform(); 1890 }, 1891 1892 /** 1893 * @function 1894 * @deprecated since v3.0, please use getParentToNodeTransform instead 1895 */ 1896 parentToNodeTransform: function () { 1897 return this.getParentToNodeTransform(); 1898 }, 1899 1900 /** 1901 * Returns the world affine transform matrix. The matrix is in Pixels. 1902 * @function 1903 * @return {cc.AffineTransform} 1904 */ 1905 getNodeToWorldTransform: function () { 1906 //TODO renderCmd has a WorldTransform 1907 var t = this.getNodeToParentTransform(); 1908 for (var p = this._parent; p !== null; p = p.parent) 1909 t = cc.affineTransformConcat(t, p.getNodeToParentTransform()); 1910 return t; 1911 }, 1912 1913 /** 1914 * @function 1915 * @deprecated since v3.0, please use getNodeToWorldTransform instead 1916 */ 1917 nodeToWorldTransform: function(){ 1918 return this.getNodeToWorldTransform(); 1919 }, 1920 1921 /** 1922 * Returns the inverse world affine transform matrix. The matrix is in Pixels. 1923 * @function 1924 * @return {cc.AffineTransform} 1925 */ 1926 getWorldToNodeTransform: function () { 1927 return cc.affineTransformInvert(this.getNodeToWorldTransform()); 1928 }, 1929 1930 /** 1931 * @function 1932 * @deprecated since v3.0, please use getWorldToNodeTransform instead 1933 */ 1934 worldToNodeTransform: function () { 1935 return this.getWorldToNodeTransform(); 1936 }, 1937 1938 /** 1939 * Converts a Point to node (local) space coordinates. The result is in Points. 1940 * @function 1941 * @param {cc.Point} worldPoint 1942 * @return {cc.Point} 1943 */ 1944 convertToNodeSpace: function (worldPoint) { 1945 return cc.pointApplyAffineTransform(worldPoint, this.getWorldToNodeTransform()); 1946 }, 1947 1948 /** 1949 * Converts a Point to world space coordinates. The result is in Points. 1950 * @function 1951 * @param {cc.Point} nodePoint 1952 * @return {cc.Point} 1953 */ 1954 convertToWorldSpace: function (nodePoint) { 1955 nodePoint = nodePoint || cc.p(0,0); 1956 return cc.pointApplyAffineTransform(nodePoint, this.getNodeToWorldTransform()); 1957 }, 1958 1959 /** 1960 * Converts a Point to node (local) space coordinates. The result is in Points.<br/> 1961 * treating the returned/received node point as anchor relative. 1962 * @function 1963 * @param {cc.Point} worldPoint 1964 * @return {cc.Point} 1965 */ 1966 convertToNodeSpaceAR: function (worldPoint) { 1967 return cc.pSub(this.convertToNodeSpace(worldPoint), this._renderCmd.getAnchorPointInPoints()); 1968 }, 1969 1970 /** 1971 * Converts a local Point to world space coordinates.The result is in Points.<br/> 1972 * treating the returned/received node point as anchor relative. 1973 * @function 1974 * @param {cc.Point} nodePoint 1975 * @return {cc.Point} 1976 */ 1977 convertToWorldSpaceAR: function (nodePoint) { 1978 nodePoint = nodePoint || cc.p(0,0); 1979 var pt = cc.pAdd(nodePoint, this._renderCmd.getAnchorPointInPoints()); 1980 return this.convertToWorldSpace(pt); 1981 }, 1982 1983 _convertToWindowSpace: function (nodePoint) { 1984 var worldPoint = this.convertToWorldSpace(nodePoint); 1985 return cc.director.convertToUI(worldPoint); 1986 }, 1987 1988 /** convenience methods which take a cc.Touch instead of cc.Point 1989 * @function 1990 * @param {cc.Touch} touch The touch object 1991 * @return {cc.Point} 1992 */ 1993 convertTouchToNodeSpace: function (touch) { 1994 var point = touch.getLocation(); 1995 return this.convertToNodeSpace(point); 1996 }, 1997 1998 /** 1999 * converts a cc.Touch (world coordinates) into a local coordinate. This method is AR (Anchor Relative). 2000 * @function 2001 * @param {cc.Touch} touch The touch object 2002 * @return {cc.Point} 2003 */ 2004 convertTouchToNodeSpaceAR: function (touch) { 2005 var point = cc.director.convertToGL(touch.getLocation()); 2006 return this.convertToNodeSpaceAR(point); 2007 }, 2008 2009 /** 2010 * Update will be called automatically every frame if "scheduleUpdate" is called when the node is "live".<br/> 2011 * The default behavior is to invoke the visit function of node's componentContainer.<br/> 2012 * Override me to implement your own update logic. 2013 * @function 2014 * @param {Number} dt Delta time since last update 2015 */ 2016 update: function (dt) { 2017 if (this._componentContainer && !this._componentContainer.isEmpty()) 2018 this._componentContainer.visit(dt); 2019 }, 2020 2021 /** 2022 * <p> 2023 * Calls children's updateTransform() method recursively. <br/> 2024 * <br/> 2025 * This method is moved from CCSprite, so it's no longer specific to CCSprite. <br/> 2026 * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode. <br/> 2027 * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before. 2028 * </p> 2029 * @function 2030 */ 2031 updateTransform: function () { 2032 // Recursively iterate over children 2033 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.updateTransform); 2034 }, 2035 2036 /** 2037 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 2038 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 2039 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 2040 * 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/> 2041 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 2042 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 2043 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 2044 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 2045 * retain and release function call should be paired in developer's game code.</p> 2046 * @function 2047 * @see cc.Node#release 2048 */ 2049 retain: function () { 2050 }, 2051 /** 2052 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 2053 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 2054 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 2055 * 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/> 2056 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 2057 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 2058 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 2059 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 2060 * retain and release function call should be paired in developer's game code.</p> 2061 * @function 2062 * @see cc.Node#retain 2063 */ 2064 release: function () { 2065 }, 2066 2067 /** 2068 * Returns a component identified by the name given. 2069 * @function 2070 * @param {String} name The name to search for 2071 * @return {cc.Component} The component found 2072 */ 2073 getComponent: function (name) { 2074 if(this._componentContainer) 2075 return this._componentContainer.getComponent(name); 2076 return null; 2077 }, 2078 2079 /** 2080 * Adds a component to the node's component container. 2081 * @function 2082 * @param {cc.Component} component 2083 */ 2084 addComponent: function (component) { 2085 if(this._componentContainer) 2086 this._componentContainer.add(component); 2087 }, 2088 2089 /** 2090 * Removes a component identified by the given name or removes the component object given 2091 * @function 2092 * @param {String|cc.Component} component 2093 */ 2094 removeComponent: function (component) { 2095 if(this._componentContainer) 2096 return this._componentContainer.remove(component); 2097 return false; 2098 }, 2099 2100 /** 2101 * Removes all components of cc.Node, it called when cc.Node is exiting from stage. 2102 * @function 2103 */ 2104 removeAllComponents: function () { 2105 if(this._componentContainer) 2106 this._componentContainer.removeAll(); 2107 }, 2108 2109 grid: null, 2110 2111 /** 2112 * Recursive method that visit its children and draw them 2113 * @function 2114 * @param {cc.Node.RenderCmd} parentCmd 2115 */ 2116 visit: function(parentCmd){ 2117 this._renderCmd.visit(parentCmd); 2118 }, 2119 2120 /** 2121 * Performs view-matrix transformation based on position, scale, rotation and other attributes. 2122 * @function 2123 * @param {cc.Node.RenderCmd} parentCmd parent's render command 2124 * @param {boolean} recursive whether call its children's transform 2125 */ 2126 transform: function(parentCmd, recursive){ 2127 this._renderCmd.transform(parentCmd, recursive); 2128 }, 2129 2130 /** 2131 * <p>Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/> 2132 * The matrix is in Pixels.</p> 2133 * @function 2134 * @return {cc.AffineTransform} 2135 * @deprecated since v3.0, please use getNodeToParentTransform instead 2136 */ 2137 nodeToParentTransform: function(){ 2138 return this.getNodeToParentTransform(); 2139 }, 2140 2141 /** 2142 * Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/> 2143 * The matrix is in Pixels. 2144 * @function 2145 * @return {cc.AffineTransform} The affine transform object 2146 */ 2147 getNodeToParentTransform: function(ancestor){ 2148 var t = this._renderCmd.getNodeToParentTransform(); 2149 if(ancestor){ 2150 var T = {a: t.a, b: t.b, c: t.c, d: t.d, tx: t.tx, ty: t.ty}; 2151 for(var p = this._parent; p != null && p != ancestor ; p = p.getParent()){ 2152 cc.affineTransformConcatIn(T, p.getNodeToParentTransform()); 2153 } 2154 return T; 2155 }else{ 2156 return t; 2157 } 2158 }, 2159 2160 getNodeToParentAffineTransform: function(ancestor){ 2161 return this.getNodeToParentTransform(ancestor); 2162 }, 2163 2164 /** 2165 * Returns a camera object that lets you move the node using a gluLookAt 2166 * @function 2167 * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt 2168 * @deprecated since v3.0, no alternative function 2169 * @example 2170 * var camera = node.getCamera(); 2171 * camera.setEye(0, 0, 415/2); 2172 * camera.setCenter(0, 0, 0); 2173 */ 2174 getCamera: function () { 2175 if (!this._camera) 2176 this._camera = new cc.Camera(); 2177 return this._camera; 2178 }, 2179 2180 /** 2181 * <p>Returns a grid object that is used when applying effects.<br/> 2182 * This function have been deprecated, please use cc.NodeGrid to run grid actions</p> 2183 * @function 2184 * @return {cc.GridBase} A CCGrid object that is used when applying effects 2185 * @deprecated since v3.0, no alternative function 2186 */ 2187 getGrid: function () { 2188 return this.grid; 2189 }, 2190 2191 /** 2192 * <p>Changes a grid object that is used when applying effects<br/> 2193 * This function have been deprecated, please use cc.NodeGrid to run grid actions</p> 2194 * @function 2195 * @param {cc.GridBase} grid A CCGrid object that is used when applying effects 2196 * @deprecated since v3.0, no alternative function 2197 */ 2198 setGrid: function (grid) { 2199 this.grid = grid; 2200 }, 2201 2202 /** 2203 * Return the shader program currently used for this node 2204 * @function 2205 * @return {cc.GLProgram} The shader program currently used for this node 2206 */ 2207 getShaderProgram: function () { 2208 return this._renderCmd.getShaderProgram(); 2209 }, 2210 2211 /** 2212 * <p> 2213 * Sets the shader program for this node 2214 * 2215 * Since v2.0, each rendering node must set its shader program. 2216 * It should be set in initialize phase. 2217 * </p> 2218 * @function 2219 * @param {cc.GLProgram} newShaderProgram The shader program which fetches from CCShaderCache. 2220 * @example 2221 * node.setGLProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); 2222 */ 2223 setShaderProgram: function (newShaderProgram) { 2224 this._renderCmd.setShaderProgram(newShaderProgram); 2225 }, 2226 2227 /** 2228 * Returns the state of OpenGL server side. 2229 * @function 2230 * @return {Number} The state of OpenGL server side. 2231 * @deprecated since v3.0, no need anymore 2232 */ 2233 getGLServerState: function () { 2234 return 0; 2235 }, 2236 2237 /** 2238 * Sets the state of OpenGL server side. 2239 * @function 2240 * @param {Number} state The state of OpenGL server side. 2241 * @deprecated since v3.0, no need anymore 2242 */ 2243 setGLServerState: function (state) { 2244 }, 2245 2246 /** 2247 * Returns a "world" axis aligned bounding box of the node. 2248 * @function 2249 * @return {cc.Rect} 2250 */ 2251 getBoundingBoxToWorld: function () { 2252 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 2253 var trans = this.getNodeToWorldTransform(); 2254 rect = cc.rectApplyAffineTransform(rect, trans); 2255 2256 //query child's BoundingBox 2257 if (!this._children) 2258 return rect; 2259 2260 var locChildren = this._children; 2261 for (var i = 0; i < locChildren.length; i++) { 2262 var child = locChildren[i]; 2263 if (child && child._visible) { 2264 var childRect = child._getBoundingBoxToCurrentNode(trans); 2265 if (childRect) 2266 rect = cc.rectUnion(rect, childRect); 2267 } 2268 } 2269 return rect; 2270 }, 2271 2272 _getBoundingBoxToCurrentNode: function (parentTransform) { 2273 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 2274 var trans = (parentTransform === undefined) ? this.getNodeToParentTransform() : cc.affineTransformConcat(this.getNodeToParentTransform(), parentTransform); 2275 rect = cc.rectApplyAffineTransform(rect, trans); 2276 2277 //query child's BoundingBox 2278 if (!this._children) 2279 return rect; 2280 2281 var locChildren = this._children; 2282 for (var i = 0; i < locChildren.length; i++) { 2283 var child = locChildren[i]; 2284 if (child && child._visible) { 2285 var childRect = child._getBoundingBoxToCurrentNode(trans); 2286 if (childRect) 2287 rect = cc.rectUnion(rect, childRect); 2288 } 2289 } 2290 return rect; 2291 }, 2292 2293 /** 2294 * Returns the opacity of Node 2295 * @function 2296 * @returns {number} opacity 2297 */ 2298 getOpacity: function () { 2299 return this._realOpacity; 2300 }, 2301 2302 /** 2303 * Returns the displayed opacity of Node, 2304 * 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. 2305 * @function 2306 * @returns {number} displayed opacity 2307 */ 2308 getDisplayedOpacity: function () { 2309 return this._renderCmd.getDisplayedOpacity(); 2310 }, 2311 2312 /** 2313 * Sets the opacity of Node 2314 * @function 2315 * @param {Number} opacity 2316 */ 2317 setOpacity: function (opacity) { 2318 this._realOpacity = opacity; 2319 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty); 2320 }, 2321 2322 /** 2323 * Update displayed opacity 2324 * @function 2325 * @param {Number} parentOpacity 2326 */ 2327 updateDisplayedOpacity: function (parentOpacity) { 2328 //TODO this API shouldn't be public. 2329 this._renderCmd._updateDisplayOpacity(parentOpacity); 2330 }, 2331 2332 /** 2333 * Returns whether node's opacity value affect its child nodes. 2334 * @function 2335 * @returns {boolean} 2336 */ 2337 isCascadeOpacityEnabled: function () { 2338 return this._cascadeOpacityEnabled; 2339 }, 2340 2341 /** 2342 * Enable or disable cascade opacity, if cascade enabled, child nodes' opacity will be the multiplication of parent opacity and its own opacity. 2343 * @function 2344 * @param {boolean} cascadeOpacityEnabled 2345 */ 2346 setCascadeOpacityEnabled: function (cascadeOpacityEnabled) { 2347 if (this._cascadeOpacityEnabled === cascadeOpacityEnabled) 2348 return; 2349 this._cascadeOpacityEnabled = cascadeOpacityEnabled; 2350 this._renderCmd.setCascadeOpacityEnabledDirty(); 2351 }, 2352 2353 /** 2354 * Returns the color of Node 2355 * @function 2356 * @returns {cc.Color} 2357 */ 2358 getColor: function () { 2359 var locRealColor = this._realColor; 2360 return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a); 2361 }, 2362 2363 /** 2364 * Returns the displayed color of Node, 2365 * 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. 2366 * @function 2367 * @returns {cc.Color} 2368 */ 2369 getDisplayedColor: function () { 2370 return this._renderCmd.getDisplayedColor(); 2371 }, 2372 2373 /** 2374 * <p>Sets the color of Node.<br/> 2375 * When color doesn't include opacity value like cc.color(128,128,128), this function only change the color. <br/> 2376 * When color include opacity like cc.color(128,128,128,100), then this function will change the color and the opacity.</p> 2377 * @function 2378 * @param {cc.Color} color The new color given 2379 */ 2380 setColor: function (color) { 2381 var locRealColor = this._realColor; 2382 locRealColor.r = color.r; 2383 locRealColor.g = color.g; 2384 locRealColor.b = color.b; 2385 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty); 2386 }, 2387 2388 /** 2389 * Update the displayed color of Node 2390 * @function 2391 * @param {cc.Color} parentColor 2392 */ 2393 updateDisplayedColor: function (parentColor) { 2394 //TODO this API shouldn't be public. 2395 this._renderCmd._updateDisplayColor(parentColor); 2396 }, 2397 2398 /** 2399 * Returns whether node's color value affect its child nodes. 2400 * @function 2401 * @returns {boolean} 2402 */ 2403 isCascadeColorEnabled: function () { 2404 return this._cascadeColorEnabled; 2405 }, 2406 2407 /** 2408 * Enable or disable cascade color, if cascade enabled, child nodes' opacity will be the cascade value of parent color and its own color. 2409 * @param {boolean} cascadeColorEnabled 2410 */ 2411 setCascadeColorEnabled: function (cascadeColorEnabled) { 2412 if (this._cascadeColorEnabled === cascadeColorEnabled) 2413 return; 2414 this._cascadeColorEnabled = cascadeColorEnabled; 2415 this._renderCmd.setCascadeColorEnabledDirty(); 2416 }, 2417 2418 /** 2419 * Set whether color should be changed with the opacity value, 2420 * useless in cc.Node, but this function is override in some class to have such behavior. 2421 * @function 2422 * @param {Boolean} opacityValue 2423 */ 2424 setOpacityModifyRGB: function (opacityValue) { 2425 }, 2426 2427 /** 2428 * Get whether color should be changed with the opacity value 2429 * @function 2430 * @return {Boolean} 2431 */ 2432 isOpacityModifyRGB: function () { 2433 return false; 2434 }, 2435 2436 _initRendererCmd: function(){ 2437 this._renderCmd = cc.renderer.getRenderCmd(this); 2438 }, 2439 2440 _createRenderCmd: function(){ 2441 if(cc._renderType === cc.game.RENDER_TYPE_CANVAS) 2442 return new cc.Node.CanvasRenderCmd(this); 2443 else 2444 return new cc.Node.WebGLRenderCmd(this); 2445 }, 2446 2447 /** Search the children of the receiving node to perform processing for nodes which share a name. 2448 * 2449 * @param name The name to search for, supports c++11 regular expression. 2450 * Search syntax options: 2451 * `//`: Can only be placed at the begin of the search string. This indicates that it will search recursively. 2452 * `..`: The search should move up to the node's parent. Can only be placed at the end of string. 2453 * `/` : When placed anywhere but the start of the search string, this indicates that the search should move to the node's children. 2454 * 2455 * @code 2456 * enumerateChildren("//MyName", ...): This searches the children recursively and matches any node with the name `MyName`. 2457 * enumerateChildren("[[:alnum:]]+", ...): This search string matches every node of its children. 2458 * enumerateChildren("A[[:digit:]]", ...): This searches the node's children and returns any child named `A0`, `A1`, ..., `A9`. 2459 * enumerateChildren("Abby/Normal", ...): This searches the node's grandchildren and returns any node whose name is `Normal` 2460 * and whose parent is named `Abby`. 2461 * enumerateChildren("//Abby/Normal", ...): This searches recursively and returns any node whose name is `Normal` and whose 2462 * parent is named `Abby`. 2463 * @endcode 2464 * 2465 * @warning Only support alpha or number for name, and not support unicode. 2466 * 2467 * @param callback A callback function to execute on nodes that match the `name` parameter. The function takes the following arguments: 2468 * `node` 2469 * A node that matches the name 2470 * And returns a boolean result. Your callback can return `true` to terminate the enumeration. 2471 * 2472 */ 2473 enumerateChildren: function(name, callback){ 2474 cc.assert(name && name.length != 0, "Invalid name"); 2475 cc.assert(callback != null, "Invalid callback function"); 2476 2477 var length = name.length; 2478 var subStrStartPos = 0; 2479 var subStrlength = length; 2480 2481 // Starts with '//'? 2482 var searchRecursively = false; 2483 if(length > 2 && name[0] === "/" && name[1] === "/"){ 2484 searchRecursively = true; 2485 subStrStartPos = 2; 2486 subStrlength -= 2; 2487 } 2488 2489 var searchFromParent = false; 2490 if(length > 3 && name[length-3] === "/" && name[length-2] === "." && name[length-1] === "."){ 2491 searchFromParent = true; 2492 subStrlength -= 3; 2493 } 2494 2495 var newName = name.substr(subStrStartPos, subStrlength); 2496 2497 if(searchFromParent) 2498 newName = "[[:alnum:]]+/" + newName; 2499 2500 if(searchRecursively) 2501 this.doEnumerateRecursive(this, newName, callback); 2502 else 2503 this.doEnumerate(newName, callback); 2504 }, 2505 2506 doEnumerateRecursive: function(node, name, callback){ 2507 var ret = false; 2508 if(node.doEnumerate(name,callback)){ 2509 ret = true; 2510 }else{ 2511 var child, 2512 children = node.getChildren(), 2513 length = children.length; 2514 // search its children 2515 for (var i=0; i<length; i++) { 2516 child = children[i]; 2517 if (this.doEnumerateRecursive(child, name, callback)) { 2518 ret = true; 2519 break; 2520 } 2521 } 2522 } 2523 }, 2524 2525 doEnumerate: function(name, callback){ 2526 // name may be xxx/yyy, should find its parent 2527 var pos = name.indexOf('/'); 2528 var searchName = name; 2529 var needRecursive = false; 2530 if (pos !== -1){ 2531 searchName = name.substr(0, pos); 2532 //name.erase(0, pos+1); 2533 needRecursive = true; 2534 } 2535 2536 var ret = false; 2537 var child, 2538 children = this._children, 2539 length = children.length; 2540 for (var i=0; i<length; i++){ 2541 child = children[i]; 2542 if (child._name.indexOf(searchName) !== -1){ 2543 if (!needRecursive){ 2544 // terminate enumeration if callback return true 2545 if (callback(child)){ 2546 ret = true; 2547 break; 2548 } 2549 }else{ 2550 ret = child.doEnumerate(name, callback); 2551 if (ret) 2552 break; 2553 } 2554 } 2555 } 2556 2557 return ret; 2558 } 2559 }); 2560 2561 /** 2562 * Allocates and initializes a node. 2563 * @deprecated since v3.0, please use new construction instead. 2564 * @see cc.Node 2565 * @return {cc.Node} 2566 */ 2567 cc.Node.create = function () { 2568 return new cc.Node(); 2569 }; 2570 2571 cc.Node._stateCallbackType = {onEnter: 1, onExit: 2, cleanup: 3, onEnterTransitionDidFinish: 4, updateTransform: 5, onExitTransitionDidStart: 6, sortAllChildren: 7}; 2572 2573 cc.assert(cc.isFunction(cc._tmp.PrototypeCCNode), cc._LogInfos.MissingFile, "BaseNodesPropertyDefine.js"); 2574 cc._tmp.PrototypeCCNode(); 2575 delete cc._tmp.PrototypeCCNode;