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 if(cc.isUndefined(tag)){ 1260 tag = undefined; 1261 name = child._name; 1262 } else if(cc.isString(tag)){ 1263 name = tag; 1264 tag = undefined; 1265 } else if(cc.isNumber(tag)){ 1266 setTag = true; 1267 name = ""; 1268 } 1269 1270 cc.assert(child, cc._LogInfos.Node_addChild_3); 1271 cc.assert(child._parent === null, "child already added. It can't be added again"); 1272 1273 this._addChildHelper(child, localZOrder, tag, name, setTag); 1274 }, 1275 1276 _addChildHelper: function(child, localZOrder, tag, name, setTag){ 1277 if(!this._children) 1278 this._children = []; 1279 1280 this._insertChild(child, localZOrder); 1281 if(setTag) 1282 child.setTag(tag); 1283 else 1284 child.setName(name); 1285 1286 child.setParent(this); 1287 child.setOrderOfArrival(cc.s_globalOrderOfArrival++); 1288 1289 if( this._running ){ 1290 child.onEnter(); 1291 // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter 1292 if (this._isTransitionFinished) 1293 child.onEnterTransitionDidFinish(); 1294 } 1295 1296 if (this._cascadeColorEnabled) 1297 this._enableCascadeColor(); 1298 if (this._cascadeOpacityEnabled) 1299 this._enableCascadeOpacity(); 1300 }, 1301 1302 // composition: REMOVE 1303 /** 1304 * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks. <br/> 1305 * If the cleanup parameter is not passed, it will force a cleanup. <br/> 1306 * If the node orphan, then nothing happens. 1307 * @function 1308 * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. 1309 * @see cc.Node#removeFromParentAndCleanup 1310 */ 1311 removeFromParent: function (cleanup) { 1312 if (this._parent) { 1313 if (cleanup == null) 1314 cleanup = true; 1315 this._parent.removeChild(this, cleanup); 1316 } 1317 }, 1318 1319 /** 1320 * Removes this node itself from its parent node. <br/> 1321 * If the node orphan, then nothing happens. 1322 * @deprecated since v3.0, please use removeFromParent() instead 1323 * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. 1324 */ 1325 removeFromParentAndCleanup: function (cleanup) { 1326 cc.log(cc._LogInfos.Node_removeFromParentAndCleanup); 1327 this.removeFromParent(cleanup); 1328 }, 1329 1330 /** <p>Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. </p> 1331 * If the cleanup parameter is not passed, it will force a cleanup. <br/> 1332 * <p> "remove" logic MUST only be on this method <br/> 1333 * If a class wants to extend the 'removeChild' behavior it only needs <br/> 1334 * to override this method </p> 1335 * @function 1336 * @param {cc.Node} child The child node which will be removed. 1337 * @param {Boolean|null} [cleanup=null] true if all running actions and callbacks on the child node will be cleanup, false otherwise. 1338 */ 1339 removeChild: function (child, cleanup) { 1340 // explicit nil handling 1341 if (this._children.length === 0) 1342 return; 1343 1344 if (cleanup == null) 1345 cleanup = true; 1346 if (this._children.indexOf(child) > -1) 1347 this._detachChild(child, cleanup); 1348 1349 this.setNodeDirty(); 1350 }, 1351 1352 /** 1353 * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter. 1354 * If the cleanup parameter is not passed, it will force a cleanup. <br/> 1355 * @function 1356 * @param {Number} tag An integer number that identifies a child node 1357 * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. 1358 * @see cc.Node#removeChildByTag 1359 */ 1360 removeChildByTag: function (tag, cleanup) { 1361 if (tag === cc.NODE_TAG_INVALID) 1362 cc.log(cc._LogInfos.Node_removeChildByTag); 1363 1364 var child = this.getChildByTag(tag); 1365 if (child == null) 1366 cc.log(cc._LogInfos.Node_removeChildByTag_2, tag); 1367 else 1368 this.removeChild(child, cleanup); 1369 }, 1370 1371 /** 1372 * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. 1373 * @param {Boolean | null } cleanup 1374 */ 1375 removeAllChildrenWithCleanup: function (cleanup) { 1376 //cc.log(cc._LogInfos.Node_removeAllChildrenWithCleanup); //TODO It should be discuss in v3.0 1377 this.removeAllChildren(cleanup); 1378 }, 1379 1380 /** 1381 * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. <br/> 1382 * If the cleanup parameter is not passed, it will force a cleanup. <br/> 1383 * @function 1384 * @param {Boolean | null } cleanup true if all running actions on all children nodes should be cleanup, false otherwise. 1385 */ 1386 removeAllChildren: function (cleanup) { 1387 // not using detachChild improves speed here 1388 var __children = this._children; 1389 if (__children != null) { 1390 if (cleanup == null) 1391 cleanup = true; 1392 for (var i = 0; i < __children.length; i++) { 1393 var node = __children[i]; 1394 if (node) { 1395 // IMPORTANT: 1396 // -1st do onExit 1397 // -2nd cleanup 1398 if (this._running) { 1399 node.onExitTransitionDidStart(); 1400 node.onExit(); 1401 } 1402 if (cleanup) 1403 node.cleanup(); 1404 // set parent nil at the end 1405 node.parent = null; 1406 } 1407 } 1408 this._children.length = 0; 1409 } 1410 }, 1411 1412 _detachChild: function (child, doCleanup) { 1413 // IMPORTANT: 1414 // -1st do onExit 1415 // -2nd cleanup 1416 if (this._running) { 1417 child.onExitTransitionDidStart(); 1418 child.onExit(); 1419 } 1420 1421 // If you don't do cleanup, the child's actions will not get removed and the 1422 // its scheduledSelectors_ dict will not get released! 1423 if (doCleanup) 1424 child.cleanup(); 1425 1426 // set parent nil at the end 1427 child.parent = null; 1428 1429 cc.arrayRemoveObject(this._children, child); 1430 }, 1431 1432 _insertChild: function (child, z) { 1433 this._reorderChildDirty = true; 1434 this._children.push(child); 1435 child._setLocalZOrder(z); 1436 }, 1437 1438 /** Reorders a child according to a new z value. <br/> 1439 * The child MUST be already added. 1440 * @function 1441 * @param {cc.Node} child An already added child node. It MUST be already added. 1442 * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) 1443 */ 1444 reorderChild: function (child, zOrder) { 1445 cc.assert(child, cc._LogInfos.Node_reorderChild) 1446 this._reorderChildDirty = true; 1447 child.arrivalOrder = cc.s_globalOrderOfArrival; 1448 cc.s_globalOrderOfArrival++; 1449 child._setLocalZOrder(zOrder); 1450 this.setNodeDirty(); 1451 }, 1452 1453 /** 1454 * <p> 1455 * Sorts the children array once before drawing, instead of every time when a child is added or reordered. <br/> 1456 * This approach can improves the performance massively. 1457 * </p> 1458 * @function 1459 * @note Don't call this manually unless a child added needs to be removed in the same frame 1460 */ 1461 sortAllChildren: function () { 1462 if (this._reorderChildDirty) { 1463 var _children = this._children; 1464 1465 // insertion sort 1466 var len = _children.length, i, j, tmp; 1467 for(i=1; i<len; i++){ 1468 tmp = _children[i]; 1469 j = i - 1; 1470 1471 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 1472 while(j >= 0){ 1473 if(tmp._localZOrder < _children[j]._localZOrder){ 1474 _children[j+1] = _children[j]; 1475 }else if(tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder){ 1476 _children[j+1] = _children[j]; 1477 }else{ 1478 break; 1479 } 1480 j--; 1481 } 1482 _children[j+1] = tmp; 1483 } 1484 1485 //don't need to check children recursively, that's done in visit of each child 1486 this._reorderChildDirty = false; 1487 } 1488 }, 1489 1490 /** 1491 * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function 1492 * @function 1493 * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context 1494 */ 1495 draw: function (ctx) { 1496 // override me 1497 // Only use- this function to draw your staff. 1498 // DON'T draw your stuff outside this method 1499 }, 1500 1501 // Internal use only, do not call it by yourself, 1502 transformAncestors: function () { 1503 if (this._parent != null) { 1504 this._parent.transformAncestors(); 1505 this._parent.transform(); 1506 } 1507 }, 1508 1509 //scene managment 1510 /** 1511 * <p> 1512 * Event callback that is invoked every time when CCNode enters the 'stage'. <br/> 1513 * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts. <br/> 1514 * During onEnter you can't access a "sister/brother" node. <br/> 1515 * If you override onEnter, you must call its parent's onEnter function with this._super(). 1516 * </p> 1517 * @function 1518 */ 1519 onEnter: function () { 1520 this._isTransitionFinished = false; 1521 this._running = true;//should be running before resumeSchedule 1522 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._StateCallbackType.onEnter); 1523 this.resume(); 1524 }, 1525 1526 /** 1527 * <p> 1528 * Event callback that is invoked when the CCNode enters in the 'stage'. <br/> 1529 * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes. <br/> 1530 * If you override onEnterTransitionDidFinish, you shall call its parent's onEnterTransitionDidFinish with this._super() 1531 * </p> 1532 * @function 1533 */ 1534 onEnterTransitionDidFinish: function () { 1535 this._isTransitionFinished = true; 1536 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._StateCallbackType.onEnterTransitionDidFinish); 1537 }, 1538 1539 /** 1540 * <p>callback that is called every time the cc.Node leaves the 'stage'. <br/> 1541 * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. <br/> 1542 * If you override onExitTransitionDidStart, you shall call its parent's onExitTransitionDidStart with this._super()</p> 1543 * @function 1544 */ 1545 onExitTransitionDidStart: function () { 1546 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._StateCallbackType.onExitTransitionDidStart); 1547 }, 1548 1549 /** 1550 * <p> 1551 * callback that is called every time the cc.Node leaves the 'stage'. <br/> 1552 * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/> 1553 * During onExit you can't access a sibling node. <br/> 1554 * If you override onExit, you shall call its parent's onExit with this._super(). 1555 * </p> 1556 * @function 1557 */ 1558 onExit: function () { 1559 this._running = false; 1560 this.pause(); 1561 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._StateCallbackType.onExit); 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 1575 cc.assert(action, cc._LogInfos.Node_runAction); 1576 1577 this.actionManager.addAction(action, this, !this._running); 1578 return action; 1579 }, 1580 1581 /** 1582 * Stops and removes all actions from the running action list . 1583 * @function 1584 */ 1585 stopAllActions: function () { 1586 this.actionManager && this.actionManager.removeAllActionsFromTarget(this); 1587 }, 1588 1589 /** 1590 * Stops and removes an action from the running action list. 1591 * @function 1592 * @param {cc.Action} action An action object to be removed. 1593 */ 1594 stopAction: function (action) { 1595 this.actionManager.removeAction(action); 1596 }, 1597 1598 /** 1599 * Removes an action from the running action list by its tag. 1600 * @function 1601 * @param {Number} tag A tag that indicates the action to be removed. 1602 */ 1603 stopActionByTag: function (tag) { 1604 if (tag === cc.ACTION_TAG_INVALID) { 1605 cc.log(cc._LogInfos.Node_stopActionByTag); 1606 return; 1607 } 1608 this.actionManager.removeActionByTag(tag, this); 1609 }, 1610 1611 /** 1612 * Returns an action from the running action list by its tag. 1613 * @function 1614 * @see cc.Node#getTag and cc.Node#setTag 1615 * @param {Number} tag 1616 * @return {cc.Action} The action object with the given tag. 1617 */ 1618 getActionByTag: function (tag) { 1619 if (tag === cc.ACTION_TAG_INVALID) { 1620 cc.log(cc._LogInfos.Node_getActionByTag); 1621 return null; 1622 } 1623 return this.actionManager.getActionByTag(tag, this); 1624 }, 1625 1626 /** <p>Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).<br/> 1627 * Composable actions are counted as 1 action. Example:<br/> 1628 * If you are running 1 Sequence of 7 actions, it will return 1. <br/> 1629 * If you are running 7 Sequences of 2 actions, it will return 7.</p> 1630 * @function 1631 * @return {Number} The number of actions that are running plus the ones that are schedule to run 1632 */ 1633 getNumberOfRunningActions: function () { 1634 return this.actionManager.numberOfRunningActionsInTarget(this); 1635 }, 1636 1637 // cc.Node - Callbacks 1638 // timers 1639 /** 1640 * <p>schedules the "update" method. <br/> 1641 * It will use the order number 0. This method will be called every frame. <br/> 1642 * Scheduled methods with a lower order value will be called before the ones that have a higher order value.<br/> 1643 * Only one "update" method could be scheduled per node.</p> 1644 * @function 1645 */ 1646 scheduleUpdate: function () { 1647 this.scheduleUpdateWithPriority(0); 1648 }, 1649 1650 /** 1651 * <p> 1652 * schedules the "update" callback function with a custom priority. 1653 * This callback function will be called every frame.<br/> 1654 * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.<br/> 1655 * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).<br/> 1656 * </p> 1657 * @function 1658 * @param {Number} priority 1659 */ 1660 scheduleUpdateWithPriority: function (priority) { 1661 this.scheduler.scheduleUpdateForTarget(this, priority, !this._running); 1662 }, 1663 1664 /** 1665 * Unschedules the "update" method. 1666 * @function 1667 * @see cc.Node#scheduleUpdate 1668 */ 1669 unscheduleUpdate: function () { 1670 this.scheduler.unscheduleUpdateForTarget(this); 1671 }, 1672 1673 /** 1674 * <p>Schedules a custom selector. <br/> 1675 * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.</p> 1676 * @function 1677 * @param {function} callback_fn A function wrapped as a selector 1678 * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead. 1679 * @param {Number} repeat The selector will be executed (repeat + 1) times, you can use kCCRepeatForever for tick infinitely. 1680 * @param {Number} delay The amount of time that the first tick will wait before execution. 1681 */ 1682 schedule: function (callback_fn, interval, repeat, delay) { 1683 interval = interval || 0; 1684 1685 cc.assert(callback_fn, cc._LogInfos.Node_schedule); 1686 1687 cc.assert(interval >= 0, cc._LogInfos.Node_schedule_2); 1688 1689 repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat; 1690 delay = delay || 0; 1691 1692 this.scheduler.scheduleCallbackForTarget(this, callback_fn, interval, repeat, delay, !this._running); 1693 }, 1694 1695 /** 1696 * Schedules a callback function that runs only once, with a delay of 0 or larger 1697 * @function 1698 * @see cc.Node#schedule 1699 * @param {function} callback_fn A function wrapped as a selector 1700 * @param {Number} delay The amount of time that the first tick will wait before execution. 1701 */ 1702 scheduleOnce: function (callback_fn, delay) { 1703 this.schedule(callback_fn, 0.0, 0, delay); 1704 }, 1705 1706 /** 1707 * unschedules a custom callback function. 1708 * @function 1709 * @see cc.Node#schedule 1710 * @param {function} callback_fn A function wrapped as a selector 1711 */ 1712 unschedule: function (callback_fn) { 1713 // explicit nil handling 1714 if (!callback_fn) 1715 return; 1716 1717 this.scheduler.unscheduleCallbackForTarget(this, callback_fn); 1718 }, 1719 1720 /** 1721 * <p>unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.<br/> 1722 * Actions are not affected by this method.</p> 1723 * @function 1724 */ 1725 unscheduleAllCallbacks: function () { 1726 this.scheduler.unscheduleAllCallbacksForTarget(this); 1727 }, 1728 1729 /** 1730 * Resumes all scheduled selectors and actions.<br/> 1731 * This method is called internally by onEnter 1732 * @function 1733 * @deprecated since v3.0, please use resume() instead 1734 */ 1735 resumeSchedulerAndActions: function () { 1736 cc.log(cc._LogInfos.Node_resumeSchedulerAndActions); 1737 this.resume(); 1738 }, 1739 1740 /** 1741 * <p>Resumes all scheduled selectors and actions.<br/> 1742 * This method is called internally by onEnter</p> 1743 */ 1744 resume: function () { 1745 this.scheduler.resumeTarget(this); 1746 this.actionManager && this.actionManager.resumeTarget(this); 1747 cc.eventManager.resumeTarget(this); 1748 }, 1749 1750 /** 1751 * <p>Pauses all scheduled selectors and actions.<br/> 1752 * This method is called internally by onExit</p> 1753 * @deprecated since v3.0, please use pause instead 1754 * @function 1755 */ 1756 pauseSchedulerAndActions: function () { 1757 cc.log(cc._LogInfos.Node_pauseSchedulerAndActions); 1758 this.pause(); 1759 }, 1760 1761 /** 1762 * <p>Pauses all scheduled selectors and actions.<br/> 1763 * This method is called internally by onExit</p> 1764 * @function 1765 */ 1766 pause: function () { 1767 this.scheduler.pauseTarget(this); 1768 this.actionManager && this.actionManager.pauseTarget(this); 1769 cc.eventManager.pauseTarget(this); 1770 }, 1771 1772 /** 1773 *<p>Sets the additional transform.<br/> 1774 * The additional transform will be concatenated at the end of getNodeToParentTransform.<br/> 1775 * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).<br/> 1776 * </p> 1777 * @function 1778 * @param {cc.AffineTransform} additionalTransform The additional transform 1779 * @example 1780 * // create a batchNode 1781 * var batch= cc.SpriteBatchNode.create("Icon-114.png"); 1782 * this.addChild(batch); 1783 * 1784 * // create two sprites, spriteA will be added to batchNode, they are using different textures. 1785 * var spriteA = cc.Sprite.create(batch->getTexture()); 1786 * var spriteB = cc.Sprite.create("Icon-72.png"); 1787 * 1788 * batch.addChild(spriteA); 1789 * 1790 * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer. 1791 * // But we want to simulate `parent-child` relationship for these two node. 1792 * this.addChild(spriteB); 1793 * 1794 * //position 1795 * spriteA.setPosition(ccp(200, 200)); 1796 * 1797 * // Gets the spriteA's transform. 1798 * var t = spriteA.getNodeToParentTransform(); 1799 * 1800 * // Sets the additional transform to spriteB, spriteB's position will based on its pseudo parent i.e. spriteA. 1801 * spriteB.setAdditionalTransform(t); 1802 * 1803 * //scale 1804 * spriteA.setScale(2); 1805 * 1806 * // Gets the spriteA's transform. 1807 * t = spriteA.getNodeToParentTransform(); 1808 * 1809 * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA. 1810 * spriteB.setAdditionalTransform(t); 1811 * 1812 * //rotation 1813 * spriteA.setRotation(20); 1814 * 1815 * // Gets the spriteA's transform. 1816 * t = spriteA.getNodeToParentTransform(); 1817 * 1818 * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA. 1819 * spriteB.setAdditionalTransform(t); 1820 */ 1821 setAdditionalTransform: function (additionalTransform) { 1822 this._additionalTransform = additionalTransform; 1823 this._transformDirty = true; 1824 this._additionalTransformDirty = true; 1825 }, 1826 1827 /** 1828 * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.<br/> 1829 * The matrix is in Pixels. 1830 * @function 1831 * @return {cc.AffineTransform} 1832 */ 1833 getParentToNodeTransform: function () { 1834 if (this._inverseDirty) { 1835 this._inverse = cc.affineTransformInvert(this.getNodeToParentTransform()); 1836 this._inverseDirty = false; 1837 } 1838 return this._inverse; 1839 }, 1840 1841 /** 1842 * @function 1843 * @deprecated since v3.0, please use getParentToNodeTransform instead 1844 */ 1845 parentToNodeTransform: function () { 1846 return this.getParentToNodeTransform(); 1847 }, 1848 1849 /** 1850 * Returns the world affine transform matrix. The matrix is in Pixels. 1851 * @function 1852 * @return {cc.AffineTransform} 1853 */ 1854 getNodeToWorldTransform: function () { 1855 var t = this.getNodeToParentTransform(); 1856 for (var p = this._parent; p != null; p = p.parent) 1857 t = cc.affineTransformConcat(t, p.getNodeToParentTransform()); 1858 return t; 1859 }, 1860 1861 /** 1862 * @function 1863 * @deprecated since v3.0, please use getNodeToWorldTransform instead 1864 */ 1865 nodeToWorldTransform: function(){ 1866 return this.getNodeToWorldTransform(); 1867 }, 1868 1869 /** 1870 * Returns the inverse world affine transform matrix. The matrix is in Pixels. 1871 * @function 1872 * @return {cc.AffineTransform} 1873 */ 1874 getWorldToNodeTransform: function () { 1875 return cc.affineTransformInvert(this.getNodeToWorldTransform()); 1876 }, 1877 1878 /** 1879 * @function 1880 * @deprecated since v3.0, please use getWorldToNodeTransform instead 1881 */ 1882 worldToNodeTransform: function () { 1883 return this.getWorldToNodeTransform(); 1884 }, 1885 1886 /** 1887 * Converts a Point to node (local) space coordinates. The result is in Points. 1888 * @function 1889 * @param {cc.Point} worldPoint 1890 * @return {cc.Point} 1891 */ 1892 convertToNodeSpace: function (worldPoint) { 1893 return cc.pointApplyAffineTransform(worldPoint, this.getWorldToNodeTransform()); 1894 }, 1895 1896 /** 1897 * Converts a Point to world space coordinates. The result is in Points. 1898 * @function 1899 * @param {cc.Point} nodePoint 1900 * @return {cc.Point} 1901 */ 1902 convertToWorldSpace: function (nodePoint) { 1903 nodePoint = nodePoint || cc.p(0,0); 1904 return cc.pointApplyAffineTransform(nodePoint, this.getNodeToWorldTransform()); 1905 }, 1906 1907 /** 1908 * Converts a Point to node (local) space coordinates. The result is in Points.<br/> 1909 * treating the returned/received node point as anchor relative. 1910 * @function 1911 * @param {cc.Point} worldPoint 1912 * @return {cc.Point} 1913 */ 1914 convertToNodeSpaceAR: function (worldPoint) { 1915 return cc.pSub(this.convertToNodeSpace(worldPoint), this._anchorPointInPoints); 1916 }, 1917 1918 /** 1919 * Converts a local Point to world space coordinates.The result is in Points.<br/> 1920 * treating the returned/received node point as anchor relative. 1921 * @function 1922 * @param {cc.Point} nodePoint 1923 * @return {cc.Point} 1924 */ 1925 convertToWorldSpaceAR: function (nodePoint) { 1926 nodePoint = nodePoint || cc.p(0,0); 1927 var pt = cc.pAdd(nodePoint, this._anchorPointInPoints); 1928 return this.convertToWorldSpace(pt); 1929 }, 1930 1931 _convertToWindowSpace: function (nodePoint) { 1932 var worldPoint = this.convertToWorldSpace(nodePoint); 1933 return cc.director.convertToUI(worldPoint); 1934 }, 1935 1936 /** convenience methods which take a cc.Touch instead of cc.Point 1937 * @function 1938 * @param {cc.Touch} touch The touch object 1939 * @return {cc.Point} 1940 */ 1941 convertTouchToNodeSpace: function (touch) { 1942 var point = touch.getLocation(); 1943 //TODO This point needn't convert to GL in HTML5 1944 //point = cc.director.convertToGL(point); 1945 return this.convertToNodeSpace(point); 1946 }, 1947 1948 /** 1949 * converts a cc.Touch (world coordinates) into a local coordiante. This method is AR (Anchor Relative). 1950 * @function 1951 * @param {cc.Touch} touch The touch object 1952 * @return {cc.Point} 1953 */ 1954 convertTouchToNodeSpaceAR: function (touch) { 1955 var point = touch.getLocation(); 1956 point = cc.director.convertToGL(point); 1957 return this.convertToNodeSpaceAR(point); 1958 }, 1959 1960 /** 1961 * Update will be called automatically every frame if "scheduleUpdate" is called when the node is "live".<br/> 1962 * The default behavior is to invoke the visit function of node's componentContainer.<br/> 1963 * Override me to implement your own update logic. 1964 * @function 1965 * @param {Number} dt Delta time since last update 1966 */ 1967 update: function (dt) { 1968 if (this._componentContainer && !this._componentContainer.isEmpty()) 1969 this._componentContainer.visit(dt); 1970 }, 1971 1972 /** 1973 * <p> 1974 * Calls children's updateTransform() method recursively. <br/> 1975 * <br/> 1976 * This method is moved from CCSprite, so it's no longer specific to CCSprite. <br/> 1977 * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode. <br/> 1978 * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before. 1979 * </p> 1980 * @function 1981 */ 1982 updateTransform: function () { 1983 // Recursively iterate over children 1984 this._arrayMakeObjectsPerformSelector(this._children, cc.Node._StateCallbackType.updateTransform); 1985 }, 1986 1987 /** 1988 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 1989 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 1990 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 1991 * 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/> 1992 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 1993 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 1994 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 1995 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 1996 * retain and release function call should be paired in developer's game code.</p> 1997 * @function 1998 * @see cc.Node#release 1999 */ 2000 retain: function () { 2001 }, 2002 /** 2003 * <p>Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 2004 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 2005 * This is a hack, and should be removed once JSB fixes the retain/release bug<br/> 2006 * 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/> 2007 * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,<br/> 2008 * when you want to use it later, a "Invalid Native Object" error will be raised.<br/> 2009 * The retain function can increase a reference count for the native object to avoid it being released,<br/> 2010 * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.<br/> 2011 * retain and release function call should be paired in developer's game code.</p> 2012 * @function 2013 * @see cc.Node#retain 2014 */ 2015 release: function () { 2016 }, 2017 2018 /** 2019 * Returns a component identified by the name given. 2020 * @function 2021 * @param {String} name The name to search for 2022 * @return {cc.Component} The component found 2023 */ 2024 getComponent: function (name) { 2025 return this._componentContainer.getComponent(name); 2026 }, 2027 2028 /** 2029 * Adds a component to the node's component container. 2030 * @function 2031 * @param {cc.Component} component 2032 */ 2033 addComponent: function (component) { 2034 this._componentContainer.add(component); 2035 }, 2036 2037 /** 2038 * Removes a component identified by the given name or removes the component object given 2039 * @function 2040 * @param {String|cc.Component} component 2041 */ 2042 removeComponent: function (component) { 2043 return this._componentContainer.remove(component); 2044 }, 2045 2046 /** 2047 * Removes all components 2048 * @function 2049 */ 2050 removeAllComponents: function () { 2051 this._componentContainer.removeAll(); 2052 }, 2053 2054 grid: null, 2055 2056 /** 2057 * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function. 2058 * @function 2059 */ 2060 ctor: null, 2061 2062 /** 2063 * Recursive method that visit its children and draw them 2064 * @function 2065 * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx 2066 */ 2067 visit: null, 2068 2069 /** 2070 * Performs view-matrix transformation based on position, scale, rotation and other attributes. 2071 * @function 2072 * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx Render context 2073 */ 2074 transform: null, 2075 2076 /** 2077 * <p>Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/> 2078 * The matrix is in Pixels.</p> 2079 * @function 2080 * @return {cc.AffineTransform} 2081 * @deprecated since v3.0, please use getNodeToParentTransform instead 2082 */ 2083 nodeToParentTransform: function(){ 2084 return this.getNodeToParentTransform(); 2085 }, 2086 2087 /** 2088 * Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/> 2089 * The matrix is in Pixels. 2090 * @function 2091 * @return {cc.AffineTransform} The affine transform object 2092 */ 2093 getNodeToParentTransform: null, 2094 2095 _setNodeDirtyForCache: function () { 2096 if (this._cacheDirty === false) { 2097 this._cacheDirty = true; 2098 2099 var cachedP = this._cachedParent; 2100 //var cachedP = this._parent; 2101 cachedP && cachedP != this && cachedP._setNodeDirtyForCache(); 2102 } 2103 }, 2104 2105 _setCachedParent: function(cachedParent){ 2106 if(this._cachedParent == cachedParent) 2107 return; 2108 2109 this._cachedParent = cachedParent; 2110 var children = this._children; 2111 for(var i = 0, len = children.length; i < len; i++) 2112 children[i]._setCachedParent(cachedParent); 2113 }, 2114 2115 /** 2116 * Returns a camera object that lets you move the node using a gluLookAt 2117 * @function 2118 * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt 2119 * @deprecated since v3.0, no alternative function 2120 * @example 2121 * var camera = node.getCamera(); 2122 * camera.setEye(0, 0, 415/2); 2123 * camera.setCenter(0, 0, 0); 2124 */ 2125 getCamera: function () { 2126 if (!this._camera) { 2127 this._camera = new cc.Camera(); 2128 } 2129 return this._camera; 2130 }, 2131 2132 /** 2133 * <p>Returns a grid object that is used when applying effects.<br/> 2134 * This function have been deprecated, please use cc.NodeGrid to run grid actions</p> 2135 * @function 2136 * @return {cc.GridBase} A CCGrid object that is used when applying effects 2137 * @deprecated since v3.0, no alternative function 2138 */ 2139 getGrid: function () { 2140 return this.grid; 2141 }, 2142 2143 /** 2144 * <p>Changes a grid object that is used when applying effects<br/> 2145 * This function have been deprecated, please use cc.NodeGrid to run grid actions</p> 2146 * @function 2147 * @param {cc.GridBase} grid A CCGrid object that is used when applying effects 2148 * @deprecated since v3.0, no alternative function 2149 */ 2150 setGrid: function (grid) { 2151 this.grid = grid; 2152 }, 2153 2154 /** 2155 * Return the shader program currently used for this node 2156 * @function 2157 * @return {cc.GLProgram} The shader program currently used for this node 2158 */ 2159 getShaderProgram: function () { 2160 return this._shaderProgram; 2161 }, 2162 2163 /** 2164 * <p> 2165 * Sets the shader program for this node 2166 * 2167 * Since v2.0, each rendering node must set its shader program. 2168 * It should be set in initialize phase. 2169 * </p> 2170 * @function 2171 * @param {cc.GLProgram} newShaderProgram The shader program which fetchs from CCShaderCache. 2172 * @example 2173 * node.setGLProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); 2174 */ 2175 setShaderProgram: function (newShaderProgram) { 2176 this._shaderProgram = newShaderProgram; 2177 }, 2178 2179 /** 2180 * Returns the state of OpenGL server side. 2181 * @function 2182 * @return {Number} The state of OpenGL server side. 2183 * @deprecated since v3.0, no need anymore 2184 */ 2185 getGLServerState: function () { 2186 return this._glServerState; 2187 }, 2188 2189 /** 2190 * Sets the state of OpenGL server side. 2191 * @function 2192 * @param {Number} state The state of OpenGL server side. 2193 * @deprecated since v3.0, no need anymore 2194 */ 2195 setGLServerState: function (state) { 2196 this._glServerState = state; 2197 }, 2198 2199 /** 2200 * Returns a "world" axis aligned bounding box of the node. 2201 * @function 2202 * @return {cc.Rect} 2203 */ 2204 getBoundingBoxToWorld: function () { 2205 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 2206 var trans = this.getNodeToWorldTransform(); 2207 rect = cc.rectApplyAffineTransform(rect, this.getNodeToWorldTransform()); 2208 2209 //query child's BoundingBox 2210 if (!this._children) 2211 return rect; 2212 2213 var locChildren = this._children; 2214 for (var i = 0; i < locChildren.length; i++) { 2215 var child = locChildren[i]; 2216 if (child && child._visible) { 2217 var childRect = child._getBoundingBoxToCurrentNode(trans); 2218 if (childRect) 2219 rect = cc.rectUnion(rect, childRect); 2220 } 2221 } 2222 return rect; 2223 }, 2224 2225 _getBoundingBoxToCurrentNode: function (parentTransform) { 2226 var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); 2227 var trans = (parentTransform == null) ? this.getNodeToParentTransform() : cc.affineTransformConcat(this.getNodeToParentTransform(), parentTransform); 2228 rect = cc.rectApplyAffineTransform(rect, trans); 2229 2230 //query child's BoundingBox 2231 if (!this._children) 2232 return rect; 2233 2234 var locChildren = this._children; 2235 for (var i = 0; i < locChildren.length; i++) { 2236 var child = locChildren[i]; 2237 if (child && child._visible) { 2238 var childRect = child._getBoundingBoxToCurrentNode(trans); 2239 if (childRect) 2240 rect = cc.rectUnion(rect, childRect); 2241 } 2242 } 2243 return rect; 2244 }, 2245 2246 _getNodeToParentTransformForWebGL: function () { 2247 var _t = this; 2248 if (_t._transformDirty) { 2249 // Translate values 2250 var x = _t._position.x; 2251 var y = _t._position.y; 2252 var apx = _t._anchorPointInPoints.x, napx = -apx; 2253 var apy = _t._anchorPointInPoints.y, napy = -apy; 2254 var scx = _t._scaleX, scy = _t._scaleY; 2255 2256 if (_t._ignoreAnchorPointForPosition) { 2257 x += apx; 2258 y += apy; 2259 } 2260 2261 // Rotation values 2262 // Change rotation code to handle X and Y 2263 // If we skew with the exact same value for both x and y then we're simply just rotating 2264 var cx = 1, sx = 0, cy = 1, sy = 0; 2265 if (_t._rotationX !== 0 || _t._rotationY !== 0) { 2266 cx = Math.cos(-_t._rotationRadiansX); 2267 sx = Math.sin(-_t._rotationRadiansX); 2268 cy = Math.cos(-_t._rotationRadiansY); 2269 sy = Math.sin(-_t._rotationRadiansY); 2270 } 2271 var needsSkewMatrix = ( _t._skewX || _t._skewY ); 2272 2273 // optimization: 2274 // inline anchor point calculation if skew is not needed 2275 // Adjusted transform calculation for rotational skew 2276 if (!needsSkewMatrix && (apx !== 0 || apy !== 0)) { 2277 x += cy * napx * scx + -sx * napy * scy; 2278 y += sy * napx * scx + cx * napy * scy; 2279 } 2280 2281 // Build Transform Matrix 2282 // Adjusted transform calculation for rotational skew 2283 var t = _t._transform; 2284 t.a = cy * scx; 2285 t.b = sy * scx; 2286 t.c = -sx * scy; 2287 t.d = cx * scy; 2288 t.tx = x; 2289 t.ty = y; 2290 2291 // XXX: Try to inline skew 2292 // If skew is needed, apply skew and then anchor point 2293 if (needsSkewMatrix) { 2294 t = cc.affineTransformConcat({a: 1.0, b: Math.tan(cc.degreesToRadians(_t._skewY)), 2295 c: Math.tan(cc.degreesToRadians(_t._skewX)), d: 1.0, tx: 0.0, ty: 0.0}, t); 2296 2297 // adjust anchor point 2298 if (apx !== 0 || apy !== 0) 2299 t = cc.affineTransformTranslate(t, napx, napy); 2300 } 2301 2302 if (_t._additionalTransformDirty) { 2303 t = cc.affineTransformConcat(t, _t._additionalTransform); 2304 _t._additionalTransformDirty = false; 2305 } 2306 _t._transform = t; 2307 _t._transformDirty = false; 2308 } 2309 return _t._transform; 2310 }, 2311 2312 _updateColor: function(){ 2313 //TODO 2314 }, 2315 2316 /** 2317 * Returns the opacity of Node 2318 * @function 2319 * @returns {number} opacity 2320 */ 2321 getOpacity: function () { 2322 return this._realOpacity; 2323 }, 2324 2325 /** 2326 * Returns the displayed opacity of Node, 2327 * 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. 2328 * @function 2329 * @returns {number} displayed opacity 2330 */ 2331 getDisplayedOpacity: function () { 2332 return this._displayedOpacity; 2333 }, 2334 2335 /** 2336 * Sets the opacity of Node 2337 * @function 2338 * @param {Number} opacity 2339 */ 2340 setOpacity: function (opacity) { 2341 this._displayedOpacity = this._realOpacity = opacity; 2342 2343 var parentOpacity = 255, locParent = this._parent; 2344 if (locParent && locParent.cascadeOpacity) 2345 parentOpacity = locParent.getDisplayedOpacity(); 2346 this.updateDisplayedOpacity(parentOpacity); 2347 2348 this._displayedColor.a = this._realColor.a = opacity; 2349 }, 2350 2351 /** 2352 * Update displayed opacity 2353 * @function 2354 * @param {Number} parentOpacity 2355 */ 2356 updateDisplayedOpacity: function (parentOpacity) { 2357 this._displayedOpacity = this._realOpacity * parentOpacity / 255.0; 2358 if (this._cascadeOpacityEnabled) { 2359 var selChildren = this._children; 2360 for (var i = 0; i < selChildren.length; i++) { 2361 var item = selChildren[i]; 2362 if (item) 2363 item.updateDisplayedOpacity(this._displayedOpacity); 2364 } 2365 } 2366 }, 2367 2368 /** 2369 * Returns whether node's opacity value affect its child nodes. 2370 * @function 2371 * @returns {boolean} 2372 */ 2373 isCascadeOpacityEnabled: function () { 2374 return this._cascadeOpacityEnabled; 2375 }, 2376 2377 /** 2378 * Enable or disable cascade opacity, if cascade enabled, child nodes' opacity will be the multiplication of parent opacity and its own opacity. 2379 * @function 2380 * @param {boolean} cascadeOpacityEnabled 2381 */ 2382 setCascadeOpacityEnabled: function (cascadeOpacityEnabled) { 2383 if (this._cascadeOpacityEnabled === cascadeOpacityEnabled) 2384 return; 2385 2386 this._cascadeOpacityEnabled = cascadeOpacityEnabled; 2387 if (cascadeOpacityEnabled) 2388 this._enableCascadeOpacity(); 2389 else 2390 this._disableCascadeOpacity(); 2391 }, 2392 2393 _enableCascadeOpacity: function () { 2394 var parentOpacity = 255, locParent = this._parent; 2395 if (locParent && locParent.cascadeOpacity) 2396 parentOpacity = locParent.getDisplayedOpacity(); 2397 this.updateDisplayedOpacity(parentOpacity); 2398 }, 2399 2400 _disableCascadeOpacity: function () { 2401 this._displayedOpacity = this._realOpacity; 2402 2403 var selChildren = this._children; 2404 for (var i = 0; i < selChildren.length; i++) { 2405 var item = selChildren[i]; 2406 if (item) 2407 item.updateDisplayedOpacity(255); 2408 } 2409 }, 2410 2411 /** 2412 * Returns the color of Node 2413 * @function 2414 * @returns {cc.Color} 2415 */ 2416 getColor: function () { 2417 var locRealColor = this._realColor; 2418 return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a); 2419 }, 2420 2421 /** 2422 * Returns the displayed color of Node, 2423 * 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. 2424 * @function 2425 * @returns {cc.Color} 2426 */ 2427 getDisplayedColor: function () { 2428 var tmpColor = this._displayedColor; 2429 return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a); 2430 }, 2431 2432 /** 2433 * <p>Sets the color of Node.<br/> 2434 * When color doesn't include opacity value like cc.color(128,128,128), this function only change the color. <br/> 2435 * When color include opacity like cc.color(128,128,128,100), then this function will change the color and the opacity.</p> 2436 * @function 2437 * @param {cc.Color} color The new color given 2438 */ 2439 setColor: function (color) { 2440 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 2441 locDisplayedColor.r = locRealColor.r = color.r; 2442 locDisplayedColor.g = locRealColor.g = color.g; 2443 locDisplayedColor.b = locRealColor.b = color.b; 2444 2445 var parentColor, locParent = this._parent; 2446 if (locParent && locParent.cascadeColor) 2447 parentColor = locParent.getDisplayedColor(); 2448 else 2449 parentColor = cc.color.WHITE; 2450 this.updateDisplayedColor(parentColor); 2451 2452 /*if (color.a !== undefined && !color.a_undefined) { //setColor doesn't support changing opacity, please use setOpacity 2453 this.setOpacity(color.a); 2454 }*/ 2455 }, 2456 2457 /** 2458 * Update the displayed color of Node 2459 * @function 2460 * @param {cc.Color} parentColor 2461 */ 2462 updateDisplayedColor: function (parentColor) { 2463 var locDispColor = this._displayedColor, locRealColor = this._realColor; 2464 locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0); 2465 locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0); 2466 locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0); 2467 2468 if (this._cascadeColorEnabled) { 2469 var selChildren = this._children; 2470 for (var i = 0; i < selChildren.length; i++) { 2471 var item = selChildren[i]; 2472 if (item) 2473 item.updateDisplayedColor(locDispColor); 2474 } 2475 } 2476 }, 2477 2478 /** 2479 * Returns whether node's color value affect its child nodes. 2480 * @function 2481 * @returns {boolean} 2482 */ 2483 isCascadeColorEnabled: function () { 2484 return this._cascadeColorEnabled; 2485 }, 2486 2487 /** 2488 * Enable or disable cascade color, if cascade enabled, child nodes' opacity will be the cascade value of parent color and its own color. 2489 * @param {boolean} cascadeColorEnabled 2490 */ 2491 setCascadeColorEnabled: function (cascadeColorEnabled) { 2492 if (this._cascadeColorEnabled === cascadeColorEnabled) 2493 return; 2494 this._cascadeColorEnabled = cascadeColorEnabled; 2495 if (this._cascadeColorEnabled) 2496 this._enableCascadeColor(); 2497 else 2498 this._disableCascadeColor(); 2499 }, 2500 2501 _enableCascadeColor: function () { 2502 var parentColor , locParent = this._parent; 2503 if (locParent && locParent.cascadeColor) 2504 parentColor = locParent.getDisplayedColor(); 2505 else 2506 parentColor = cc.color.WHITE; 2507 this.updateDisplayedColor(parentColor); 2508 }, 2509 2510 _disableCascadeColor: function () { 2511 var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; 2512 locDisplayedColor.r = locRealColor.r; 2513 locDisplayedColor.g = locRealColor.g; 2514 locDisplayedColor.b = locRealColor.b; 2515 2516 var selChildren = this._children, whiteColor = cc.color.WHITE; 2517 for (var i = 0; i < selChildren.length; i++) { 2518 var item = selChildren[i]; 2519 if (item) 2520 item.updateDisplayedColor(whiteColor); 2521 } 2522 }, 2523 2524 /** 2525 * Set whether color should be changed with the opacity value, 2526 * useless in cc.Node, but this function is overrided in some class to have such behavior. 2527 * @function 2528 * @param {Boolean} value 2529 */ 2530 setOpacityModifyRGB: function (opacityValue) { 2531 }, 2532 2533 /** 2534 * Get whether color should be changed with the opacity value 2535 * @function 2536 * @return {Boolean} 2537 */ 2538 isOpacityModifyRGB: function () { 2539 return false; 2540 } 2541 }); 2542 2543 /** 2544 * Allocates and initializes a node. 2545 * @deprecated since v3.0, please use new construction instead. 2546 * @see cc.Node 2547 * @return {cc.Node} 2548 */ 2549 cc.Node.create = function () { 2550 return new cc.Node(); 2551 }; 2552 2553 cc.Node._StateCallbackType = {onEnter: 1, onExit: 2, cleanup: 3, onEnterTransitionDidFinish: 4, updateTransform: 5, onExitTransitionDidStart: 6, sortAllChildren: 7}; 2554 2555 if (cc._renderType === cc._RENDER_TYPE_CANVAS) { 2556 2557 //redefine cc.Node 2558 var _p = cc.Node.prototype; 2559 _p.ctor = function () { 2560 this._initNode(); 2561 }; 2562 2563 _p.setNodeDirty = function () { 2564 var _t = this; 2565 _t._setNodeDirtyForCache(); 2566 _t._transformDirty === false && (_t._transformDirty = _t._inverseDirty = true); 2567 }; 2568 2569 _p.visit = function (ctx) { 2570 var _t = this; 2571 // quick return if not visible 2572 if (!_t._visible) 2573 return; 2574 2575 //visit for canvas 2576 var context = ctx || cc._renderContext, i; 2577 var children = _t._children, child; 2578 context.save(); 2579 _t.transform(context); 2580 var len = children.length; 2581 if (len > 0) { 2582 _t.sortAllChildren(); 2583 // draw children zOrder < 0 2584 for (i = 0; i < len; i++) { 2585 child = children[i]; 2586 if (child._localZOrder < 0) 2587 child.visit(context); 2588 else 2589 break; 2590 } 2591 _t.draw(context); 2592 for (; i < len; i++) { 2593 children[i].visit(context); 2594 } 2595 } else 2596 _t.draw(context); 2597 2598 this._cacheDirty = false; 2599 _t.arrivalOrder = 0; 2600 context.restore(); 2601 }; 2602 2603 _p.transform = function (ctx) { 2604 // transform for canvas 2605 var context = ctx || cc._renderContext, eglViewer = cc.view; 2606 2607 var t = this.getNodeToParentTransform(); 2608 context.transform(t.a, t.c, t.b, t.d, t.tx * eglViewer.getScaleX(), -t.ty * eglViewer.getScaleY()); 2609 }; 2610 2611 _p.getNodeToParentTransform = function () { 2612 var _t = this; 2613 if (_t._transformDirty) { 2614 var t = _t._transform;// quick reference 2615 2616 // base position 2617 t.tx = _t._position.x; 2618 t.ty = _t._position.y; 2619 2620 // rotation Cos and Sin 2621 var Cos = 1, Sin = 0; 2622 if (_t._rotationX) { 2623 Cos = Math.cos(_t._rotationRadiansX); 2624 Sin = Math.sin(_t._rotationRadiansX); 2625 } 2626 2627 // base abcd 2628 t.a = t.d = Cos; 2629 t.b = -Sin; 2630 t.c = Sin; 2631 2632 var lScaleX = _t._scaleX, lScaleY = _t._scaleY; 2633 var appX = _t._anchorPointInPoints.x, appY = _t._anchorPointInPoints.y; 2634 2635 // Firefox on Vista and XP crashes 2636 // GPU thread in case of scale(0.0, 0.0) 2637 var sx = (lScaleX < 0.000001 && lScaleX > -0.000001) ? 0.000001 : lScaleX, 2638 sy = (lScaleY < 0.000001 && lScaleY > -0.000001) ? 0.000001 : lScaleY; 2639 2640 // skew 2641 if (_t._skewX || _t._skewY) { 2642 // offset the anchorpoint 2643 var skx = Math.tan(-_t._skewX * Math.PI / 180); 2644 var sky = Math.tan(-_t._skewY * Math.PI / 180); 2645 if(skx === Infinity){ 2646 skx = 99999999; 2647 } 2648 if(sky === Infinity){ 2649 sky = 99999999; 2650 } 2651 var xx = appY * skx * sx; 2652 var yy = appX * sky * sy; 2653 t.a = Cos + -Sin * sky; 2654 t.b = Cos * skx + -Sin; 2655 t.c = Sin + Cos * sky; 2656 t.d = Sin * skx + Cos; 2657 t.tx += Cos * xx + -Sin * yy; 2658 t.ty += Sin * xx + Cos * yy; 2659 } 2660 2661 // scale 2662 if (lScaleX !== 1 || lScaleY !== 1) { 2663 t.a *= sx; 2664 t.c *= sx; 2665 t.b *= sy; 2666 t.d *= sy; 2667 } 2668 2669 // adjust anchorPoint 2670 t.tx += Cos * -appX * sx + -Sin * appY * sy; 2671 t.ty -= Sin * -appX * sx + Cos * appY * sy; 2672 2673 // if ignore anchorPoint 2674 if (_t._ignoreAnchorPointForPosition) { 2675 t.tx += appX; 2676 t.ty += appY; 2677 } 2678 2679 if (_t._additionalTransformDirty) { 2680 _t._transform = cc.affineTransformConcat(t, _t._additionalTransform); 2681 _t._additionalTransformDirty = false; 2682 } 2683 2684 _t._transformDirty = false; 2685 } 2686 return _t._transform; 2687 }; 2688 2689 _p = null; 2690 2691 } else { 2692 cc.assert(cc.isFunction(cc._tmp.WebGLCCNode), cc._LogInfos.MissingFile, "BaseNodesWebGL.js"); 2693 cc._tmp.WebGLCCNode(); 2694 delete cc._tmp.WebGLCCNode; 2695 } 2696 cc.assert(cc.isFunction(cc._tmp.PrototypeCCNode), cc._LogInfos.MissingFile, "BaseNodesPropertyDefine.js"); 2697 cc._tmp.PrototypeCCNode(); 2698 delete cc._tmp.PrototypeCCNode;