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