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