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 * cc.Sprite invalid index on the cc.SpriteBatchNode 29 * @constant 30 * @type Number 31 */ 32 cc.SPRITE_INDEX_NOT_INITIALIZED = -1; 33 34 /** 35 * generate texture's cache for texture tint 36 * @function 37 * @param {HTMLImageElement} texture 38 * @return {Array} 39 */ 40 41 cc.generateTextureCacheForColor = function (texture) { 42 if (texture.channelCache) { 43 return texture.channelCache; 44 } 45 46 var textureCache = [ 47 document.createElement("canvas"), 48 document.createElement("canvas"), 49 document.createElement("canvas"), 50 document.createElement("canvas") 51 ]; 52 53 function renderToCache() { 54 var ref = cc.generateTextureCacheForColor; 55 56 var w = texture.width; 57 var h = texture.height; 58 59 textureCache[0].width = w; 60 textureCache[0].height = h; 61 textureCache[1].width = w; 62 textureCache[1].height = h; 63 textureCache[2].width = w; 64 textureCache[2].height = h; 65 textureCache[3].width = w; 66 textureCache[3].height = h; 67 68 ref.canvas.width = w; 69 ref.canvas.height = h; 70 71 var ctx = ref.canvas.getContext("2d"); 72 ctx.drawImage(texture, 0, 0); 73 74 ref.tempCanvas.width = w; 75 ref.tempCanvas.height = h; 76 77 var pixels = ctx.getImageData(0, 0, w, h).data; 78 79 for (var rgbI = 0; rgbI < 4; rgbI++) { 80 var cacheCtx = textureCache[rgbI].getContext('2d'); 81 cacheCtx.getImageData(0, 0, w, h).data; 82 ref.tempCtx.drawImage(texture, 0, 0); 83 84 var to = ref.tempCtx.getImageData(0, 0, w, h); 85 var toData = to.data; 86 87 for (var i = 0; i < pixels.length; i += 4) { 88 toData[i ] = (rgbI === 0) ? pixels[i ] : 0; 89 toData[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0; 90 toData[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0; 91 toData[i + 3] = pixels[i + 3]; 92 } 93 cacheCtx.putImageData(to, 0, 0); 94 } 95 texture.onload = null; 96 } 97 98 try { 99 renderToCache(); 100 } catch (e) { 101 texture.onload = renderToCache; 102 } 103 104 texture.channelCache = textureCache; 105 return textureCache; 106 }; 107 108 cc.generateTextureCacheForColor.canvas = document.createElement('canvas'); 109 cc.generateTextureCacheForColor.tempCanvas = document.createElement('canvas'); 110 cc.generateTextureCacheForColor.tempCtx = cc.generateTextureCacheForColor.tempCanvas.getContext('2d'); 111 112 /** 113 * generate tinted texture 114 * source-in: Where source and destination overlaps and both are opaque, the source is displayed. 115 * Everywhere else transparency is displayed. 116 * @function 117 * @param {HTMLImageElement} texture 118 * @param {cc.Color3B|cc.Color4F} color 119 * @param {cc.Rect} rect 120 * @return {HTMLCanvasElement} 121 */ 122 cc.generateTintImage2 = function (texture, color, rect) { 123 if (!rect) { 124 rect = cc.rect(0, 0, texture.width, texture.height); 125 rect = cc.RECT_PIXELS_TO_POINTS(rect); 126 } 127 var selColor; 128 if (color instanceof cc.Color4F) { 129 selColor = cc.c4b(color.r * 255, color.g * 255, color.b * 255, color.a * 255); 130 } else { 131 selColor = cc.c4b(color.r, color.g, color.b, 50);//color; 132 } 133 134 var buff = document.createElement("canvas"); 135 var ctx = buff.getContext("2d"); 136 137 if (buff.width != rect.width) buff.width = rect.width; 138 if (buff.height != rect.height) buff.height = rect.height; 139 ctx.save(); 140 141 ctx.drawImage(texture, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height); 142 143 ctx.globalCompositeOperation = "source-in"; 144 ctx.globalAlpha = selColor.a / 255.0; 145 ctx.fillStyle = "rgb(" + selColor.r + "," + selColor.g + "," + selColor.b + ")"; 146 ctx.fillRect(0, 0, rect.width, rect.height); 147 ctx.restore(); 148 149 return buff; 150 }; 151 152 /** 153 * generate tinted texture 154 * lighter: The source and destination colors are added to each other, resulting in brighter colors, 155 * moving towards color values of 1 (maximum brightness for that color). 156 * @function 157 * @param {HTMLImageElement} texture 158 * @param {Array} tintedImgCache 159 * @param {cc.Color3B|cc.Color4F} color 160 * @param {cc.Rect} rect 161 * @param {HTMLCanvasElement} [renderCanvas] 162 * @return {HTMLCanvasElement} 163 */ 164 cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCanvas) { 165 if (!rect) 166 rect = cc.rect(0, 0, texture.width, texture.height); 167 168 var selColor; 169 if (color.a == null) { 170 // Optimization for the particle system which mainly uses c4f colors 171 selColor = cc.c4f(color.r / 255.0, color.g / 255.0, color.b / 255, 1); 172 } else { 173 selColor = color; 174 } 175 176 var w = Math.min(rect.width, tintedImgCache[0].width); 177 var h = Math.min(rect.height, tintedImgCache[0].height); 178 var buff = renderCanvas; 179 var ctx; 180 181 // Create a new buffer if required 182 if (!buff) { 183 buff = document.createElement("canvas"); 184 buff.width = w; 185 buff.height = h; 186 ctx = buff.getContext("2d"); 187 } else { 188 ctx = buff.getContext("2d"); 189 ctx.clearRect(0, 0, w, h); 190 } 191 192 ctx.save(); 193 ctx.globalCompositeOperation = 'lighter'; 194 195 // Make sure to keep the renderCanvas alpha in mind in case of overdraw 196 var a = ctx.globalAlpha; 197 if (selColor.r > 0) { 198 ctx.globalAlpha = selColor.r * a; 199 ctx.drawImage(tintedImgCache[0], rect.x, rect.y, w, h, 0, 0, w, h); 200 } 201 if (selColor.g > 0) { 202 ctx.globalAlpha = selColor.g * a; 203 ctx.drawImage(tintedImgCache[1], rect.x, rect.y, w, h, 0, 0, w, h); 204 } 205 if (selColor.b > 0) { 206 ctx.globalAlpha = selColor.b * a; 207 ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h); 208 } 209 210 if (selColor.r + selColor.g + selColor.b < 1) { 211 ctx.globalAlpha = a; 212 ctx.drawImage(tintedImgCache[3], rect.x, rect.y, w, h, 0, 0, w, h); 213 } 214 215 ctx.restore(); 216 return buff; 217 }; 218 219 cc.cutRotateImageToCanvas = function (texture, rect) { 220 if (!texture) 221 return null; 222 223 if (!rect) 224 return texture; 225 226 var nCanvas = document.createElement("canvas"); 227 nCanvas.width = rect.width; 228 nCanvas.height = rect.height; 229 230 var ctx = nCanvas.getContext("2d"); 231 ctx.translate(nCanvas.width / 2, nCanvas.height / 2); 232 ctx.rotate(-1.5707963267948966); 233 ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width); 234 return nCanvas; 235 }; 236 237 /** 238 * a Values object for transform 239 * @Class 240 * @Construct 241 * @param {cc.Point} pos position x and y 242 * @param {cc.Point} scale scale x and y 243 * @param {Number} rotation 244 * @param {cc.Point} skew skew x and y 245 * @param {cc.Point} ap anchor point in pixels 246 * @param {Boolean} visible 247 */ 248 cc.TransformValues = function (pos, scale, rotation, skew, ap, visible) { 249 this.pos = pos; // position x and y 250 this.scale = scale; // scale x and y 251 this.rotation = rotation; 252 this.skew = skew; // skew x and y 253 this.ap = ap; // anchor point in pixels 254 this.visible = visible; 255 }; 256 257 cc.RENDER_IN_SUBPIXEL = function (A) { 258 return (0 | A); 259 }; 260 if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) { 261 cc.RENDER_IN_SUBPIXEL = function (A) { 262 return A; 263 }; 264 } 265 266 /** 267 * <p>cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) <br/> 268 * 269 * cc.Sprite can be created with an image, or with a sub-rectangle of an image. <br/> 270 * 271 * If the parent or any of its ancestors is a cc.SpriteBatchNode then the following features/limitations are valid <br/> 272 * - Features when the parent is a cc.BatchNode: <br/> 273 * - MUCH faster rendering, specially if the cc.SpriteBatchNode has many children. All the children will be drawn in a single batch. <br/> 274 * 275 * - Limitations <br/> 276 * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work) <br/> 277 * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl) <br/> 278 * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property. <br/> 279 * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property. <br/> 280 * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite. <br/> 281 * 282 * If the parent is an standard cc.Node, then cc.Sprite behaves like any other cc.Node: <br/> 283 * - It supports blending functions <br/> 284 * - It supports aliasing / antialiasing <br/> 285 * - But the rendering will be slower: 1 draw per children. <br/> 286 * 287 * The default anchorPoint in cc.Sprite is (0.5, 0.5). </p> 288 * @class 289 * @extends cc.NodeRGBA 290 * 291 * @example 292 * var aSprite = new cc.Sprite(); 293 * aSprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); 294 */ 295 cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ 296 RGBAProtocol:true, 297 // 298 // Data used when the sprite is rendered using a CCSpriteSheet 299 // 300 _textureAtlas:null, //cc.SpriteBatchNode texture atlas 301 302 _atlasIndex:0, 303 _batchNode:null, 304 _dirty:false, //Whether the sprite needs to be updated 305 _recursiveDirty:null, //Whether all of the sprite's children needs to be updated 306 _hasChildren:null, //Whether the sprite contains children 307 _shouldBeHidden:false, //should not be drawn because one of the ancestors is not visible 308 _transformToBatch:null, 309 310 // 311 // Data used when the sprite is self-rendered 312 // 313 _blendFunc:null, //It's required for CCTextureProtocol inheritance 314 _texture:null, //cc.Texture2D object that is used to render the sprite 315 316 // 317 // Shared data 318 // 319 // texture 320 _rect:null, //Retangle of cc.Texture2D 321 _rectRotated:false, //Whether the texture is rotated 322 323 // Offset Position (used by Zwoptex) 324 _offsetPosition:null, // absolute 325 _unflippedOffsetPositionFromCenter:null, 326 327 _opacityModifyRGB:false, 328 329 // image is flipped 330 _flippedX:false, //Whether the sprite is flipped horizontally or not. 331 _flippedY:false, //Whether the sprite is flipped vertically or not. 332 333 _textureLoaded:false, 334 _loadedEventListeners: null, 335 _newTextureWhenChangeColor: null, //hack property for LabelBMFont 336 337 textureLoaded:function(){ 338 return this._textureLoaded; 339 }, 340 341 addLoadedEventListener:function(callback, target){ 342 if(!this._loadedEventListeners) 343 this._loadedEventListeners = []; 344 this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); 345 }, 346 347 _callLoadedEventCallbacks:function(){ 348 if(!this._loadedEventListeners) 349 return; 350 var locListeners = this._loadedEventListeners; 351 for(var i = 0, len = locListeners.length; i < len; i++){ 352 var selCallback = locListeners[i]; 353 cc.doCallback(selCallback.eventCallback, selCallback.eventTarget, this); 354 } 355 locListeners.length = 0; 356 }, 357 358 /** 359 * Whether or not the Sprite needs to be updated in the Atlas 360 * @return {Boolean} true if the sprite needs to be updated in the Atlas, false otherwise. 361 */ 362 isDirty:function () { 363 return this._dirty; 364 }, 365 366 /** 367 * Makes the Sprite to be updated in the Atlas. 368 * @param {Boolean} bDirty 369 */ 370 setDirty:function (bDirty) { 371 this._dirty = bDirty; 372 }, 373 374 /** 375 * Returns whether or not the texture rectangle is rotated. 376 * @return {Boolean} 377 */ 378 isTextureRectRotated:function () { 379 return this._rectRotated; 380 }, 381 382 /** 383 * Returns the index used on the TextureAtlas. 384 * @return {Number} 385 */ 386 getAtlasIndex:function () { 387 return this._atlasIndex; 388 }, 389 390 /** 391 * Set the index used on the TextureAtlas. 392 * @warning Don't modify this value unless you know what you are doing 393 * @param {Number} atlasIndex 394 */ 395 setAtlasIndex:function (atlasIndex) { 396 this._atlasIndex = atlasIndex; 397 }, 398 399 /** 400 * returns the rect of the cc.Sprite in points 401 * @return {cc.Rect} 402 */ 403 getTextureRect:function () { 404 return cc.rect(this._rect.x, this._rect.y, this._rect.width, this._rect.height); 405 }, 406 407 /** 408 * Gets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode 409 * @return {cc.TextureAtlas} 410 */ 411 getTextureAtlas:function () { 412 return this._textureAtlas; 413 }, 414 415 /** 416 * Sets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode 417 * @param {cc.TextureAtlas} textureAtlas 418 */ 419 setTextureAtlas:function (textureAtlas) { 420 this._textureAtlas = textureAtlas; 421 }, 422 423 /** 424 * return the SpriteBatchNode of the cc.Sprite 425 * @return {cc.SpriteBatchNode} 426 */ 427 getSpriteBatchNode:function () { 428 return this._batchNode; 429 }, 430 431 /** 432 * set the SpriteBatchNode of the cc.Sprite 433 * @param {cc.SpriteBatchNode} spriteBatchNode 434 */ 435 setSpriteBatchNode:function (spriteBatchNode) { 436 this._batchNode = spriteBatchNode; 437 }, 438 439 /** 440 * Gets the offset position of the sprite. Calculated automatically by editors like Zwoptex. 441 * @return {cc.Point} 442 */ 443 getOffsetPosition:function () { 444 return cc.p(this._offsetPosition); 445 }, 446 447 /** 448 * conforms to cc.TextureProtocol protocol 449 * @return {cc.BlendFunc} 450 */ 451 getBlendFunc:function () { 452 return this._blendFunc; 453 }, 454 455 /** 456 * Initializes a sprite with an SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite 457 * @param {cc.SpriteFrame} spriteFrame A CCSpriteFrame object. It should includes a valid texture and a rect 458 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 459 * @example 460 * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png"); 461 * var sprite = new cc.Sprite(); 462 * sprite.initWithSpriteFrame(spriteFrame); 463 */ 464 initWithSpriteFrame:function (spriteFrame) { 465 if(!spriteFrame) 466 throw "cc.Sprite.initWithSpriteFrame(): spriteFrame should be non-null"; 467 if(!spriteFrame.textureLoaded()){ 468 //add event listener 469 this._textureLoaded = false; 470 spriteFrame.addLoadedEventListener(this._spriteFrameLoadedCallback, this); 471 } 472 var ret = this.initWithTexture(spriteFrame.getTexture(), spriteFrame.getRect()); 473 this.setDisplayFrame(spriteFrame); 474 475 return ret; 476 }, 477 478 _spriteFrameLoadedCallback:null, 479 480 _spriteFrameLoadedCallbackForWebGL:function(spriteFrame){ 481 this.setNodeDirty(); 482 this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); 483 this._callLoadedEventCallbacks(); 484 }, 485 486 _spriteFrameLoadedCallbackForCanvas:function(spriteFrame){ 487 this.setNodeDirty(); 488 this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); 489 var curColor = this.getColor(); 490 if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) 491 this._changeTextureColor(); 492 493 this._callLoadedEventCallbacks(); 494 }, 495 496 /** 497 * Initializes a sprite with a sprite frame name. <br/> 498 * A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name. <br/> 499 * If the cc.SpriteFrame doesn't exist it will raise an exception. <br/> 500 * @param {String} spriteFrameName A key string that can fected a volid cc.SpriteFrame from cc.SpriteFrameCache 501 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 502 * @example 503 * var sprite = new cc.Sprite(); 504 * sprite.initWithSpriteFrameName("grossini_dance_01.png"); 505 */ 506 initWithSpriteFrameName:function (spriteFrameName) { 507 if(!spriteFrameName) 508 throw "cc.Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null"; 509 var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); 510 if(!frame) 511 throw spriteFrameName + " is null, please check."; 512 return this.initWithSpriteFrame(frame); 513 }, 514 515 /** 516 * tell the sprite to use batch node render. 517 * @param {cc.SpriteBatchNode} batchNode 518 */ 519 useBatchNode:function (batchNode) { 520 this._textureAtlas = batchNode.getTextureAtlas(); // weak ref 521 this._batchNode = batchNode; 522 }, 523 524 /** 525 * <p> 526 * set the vertex rect.<br/> 527 * It will be called internally by setTextureRect. <br/> 528 * Useful if you want to create 2x images from SD images in Retina Display. <br/> 529 * Do not call it manually. Use setTextureRect instead. <br/> 530 * (override this method to generate "double scale" sprites) 531 * </p> 532 * @param {cc.Rect} rect 533 */ 534 setVertexRect:function (rect) { 535 this._rect.x = rect.x; 536 this._rect.y = rect.y; 537 this._rect.width = rect.width; 538 this._rect.height = rect.height; 539 }, 540 541 sortAllChildren:function () { 542 if (this._reorderChildDirty) { 543 var j, tempItem, locChildren = this._children, tempChild; 544 for (var i = 1; i < locChildren.length; i++) { 545 tempItem = locChildren[i]; 546 j = i - 1; 547 tempChild = locChildren[j]; 548 549 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 550 while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || 551 ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { 552 locChildren[j + 1] = tempChild; 553 j = j - 1; 554 tempChild = locChildren[j]; 555 } 556 locChildren[j + 1] = tempItem; 557 } 558 559 if (this._batchNode) { 560 this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); 561 } 562 this._reorderChildDirty = false; 563 } 564 }, 565 566 /** 567 * Reorders a child according to a new z value. (override cc.Node ) 568 * @param {cc.Node} child 569 * @param {Number} zOrder 570 * @override 571 */ 572 reorderChild:function (child, zOrder) { 573 if(!child) 574 throw "cc.Sprite.reorderChild(): child should be non-null"; 575 if(this._children.indexOf(child) === -1){ 576 cc.log("cc.Sprite.reorderChild(): this child is not in children list"); 577 return; 578 } 579 580 if (zOrder === child.getZOrder()) 581 return; 582 583 if (this._batchNode && !this._reorderChildDirty) { 584 this._setReorderChildDirtyRecursively(); 585 this._batchNode.reorderBatch(true); 586 } 587 cc.Node.prototype.reorderChild.call(this, child, zOrder); 588 }, 589 590 /** 591 * Removes a child from the sprite. (override cc.Node ) 592 * @param child 593 * @param cleanup whether or not cleanup all running actions 594 * @override 595 */ 596 removeChild:function (child, cleanup) { 597 if (this._batchNode) 598 this._batchNode.removeSpriteFromAtlas(child); 599 cc.Node.prototype.removeChild.call(this, child, cleanup); 600 }, 601 602 /** 603 * Removes all children from the container (override cc.Node ) 604 * @param cleanup whether or not cleanup all running actions 605 * @override 606 */ 607 removeAllChildren:function (cleanup) { 608 var locChildren = this._children, locBatchNode = this._batchNode; 609 if (locBatchNode && locChildren != null) { 610 for (var i = 0, len = locChildren.length; i < len; i++) 611 locBatchNode.removeSpriteFromAtlas(locChildren[i]); 612 } 613 614 cc.Node.prototype.removeAllChildren.call(this, cleanup); 615 this._hasChildren = false; 616 }, 617 618 // 619 // cc.Node property overloads 620 // 621 622 /** 623 * set Recursively is or isn't Dirty 624 * used only when parent is cc.SpriteBatchNode 625 * @param {Boolean} value 626 */ 627 setDirtyRecursively:function (value) { 628 this._recursiveDirty = value; 629 this.setDirty(value); 630 // recursively set dirty 631 var locChildren = this._children; 632 if (locChildren != null) { 633 for (var i = 0; i < locChildren.length; i++) { 634 if (locChildren[i] instanceof cc.Sprite) 635 locChildren[i].setDirtyRecursively(true); 636 } 637 } 638 }, 639 640 /** 641 * HACK: optimization 642 */ 643 SET_DIRTY_RECURSIVELY:function () { 644 if (this._batchNode && !this._recursiveDirty) { 645 this._recursiveDirty = true; 646 this._dirty = true; 647 if (this._hasChildren) 648 this.setDirtyRecursively(true); 649 } 650 }, 651 652 /** 653 * position setter (override cc.Node ) 654 * @param {cc.Point|Number} pos position or x value of position 655 * @param {Number} [yValue] y value of position 656 * @override 657 */ 658 setPosition:function (pos, yValue) { 659 if (arguments.length >= 2) 660 cc.Node.prototype.setPosition.call(this, pos, arguments[1]); 661 else 662 cc.Node.prototype.setPosition.call(this, pos); 663 this.SET_DIRTY_RECURSIVELY(); 664 }, 665 666 /** 667 * Rotation setter (override cc.Node ) 668 * @param {Number} rotation 669 * @override 670 */ 671 setRotation:function (rotation) { 672 cc.Node.prototype.setRotation.call(this, rotation); 673 this.SET_DIRTY_RECURSIVELY(); 674 }, 675 676 setRotationX:function (rotationX) { 677 cc.Node.prototype.setRotationX.call(this, rotationX); 678 this.SET_DIRTY_RECURSIVELY(); 679 }, 680 681 setRotationY:function (rotationY) { 682 cc.Node.prototype.setRotationY.call(this, rotationY); 683 this.SET_DIRTY_RECURSIVELY(); 684 }, 685 686 /** 687 * SkewX setter (override cc.Node ) 688 * @param {Number} sx SkewX value 689 * @override 690 */ 691 setSkewX:function (sx) { 692 cc.Node.prototype.setSkewX.call(this, sx); 693 this.SET_DIRTY_RECURSIVELY(); 694 }, 695 696 /** 697 * SkewY setter (override cc.Node ) 698 * @param {Number} sy SkewY value 699 * @override 700 */ 701 setSkewY:function (sy) { 702 cc.Node.prototype.setSkewY.call(this, sy); 703 this.SET_DIRTY_RECURSIVELY(); 704 }, 705 706 /** 707 * ScaleX setter (override cc.Node ) 708 * @param {Number} scaleX 709 * @override 710 */ 711 setScaleX:function (scaleX) { 712 cc.Node.prototype.setScaleX.call(this, scaleX); 713 this.SET_DIRTY_RECURSIVELY(); 714 }, 715 716 /** 717 * ScaleY setter (override cc.Node ) 718 * @param {Number} scaleY 719 * @override 720 */ 721 setScaleY:function (scaleY) { 722 cc.Node.prototype.setScaleY.call(this, scaleY); 723 this.SET_DIRTY_RECURSIVELY(); 724 }, 725 726 /** 727 * <p>The scale factor of the node. 1.0 is the default scale factor. <br/> 728 * It modifies the X and Y scale at the same time. (override cc.Node ) <p/> 729 * @param {Number} scale 730 * @param {Number|null} [scaleY=] 731 * @override 732 */ 733 setScale:function (scale, scaleY) { 734 cc.Node.prototype.setScale.call(this, scale, scaleY); 735 this.SET_DIRTY_RECURSIVELY(); 736 }, 737 738 /** 739 * VertexZ setter (override cc.Node ) 740 * @param {Number} vertexZ 741 * @override 742 */ 743 setVertexZ:function (vertexZ) { 744 cc.Node.prototype.setVertexZ.call(this, vertexZ); 745 this.SET_DIRTY_RECURSIVELY(); 746 }, 747 748 /** 749 * Sets the anchor point in percent. (override cc.Node ) 750 * @param {cc.Point|Number} anchor The anchor Sprite of Sprite or The anchor point.x of Sprite. 751 * @param {Number} [y] The anchor point.y of Sprite. 752 * @override 753 */ 754 setAnchorPoint:function (anchor, y) { 755 cc.Node.prototype.setAnchorPoint.call(this, anchor, y); 756 this.SET_DIRTY_RECURSIVELY(); 757 }, 758 759 /** 760 * visible setter (override cc.Node ) 761 * @param {Boolean} visible 762 * @override 763 */ 764 setVisible:function (visible) { 765 cc.Node.prototype.setVisible.call(this, visible); 766 this.SET_DIRTY_RECURSIVELY(); 767 }, 768 769 /** 770 * IsRelativeAnchorPoint setter (override cc.Node ) 771 * @param {Boolean} relative 772 * @override 773 */ 774 ignoreAnchorPointForPosition:function (relative) { 775 if(this._batchNode){ 776 cc.log("cc.Sprite.ignoreAnchorPointForPosition(): it is invalid in cc.Sprite when using SpriteBatchNode"); 777 return; 778 } 779 cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); 780 }, 781 782 /** 783 * Sets whether the sprite should be flipped horizontally or not. 784 * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise. 785 */ 786 setFlippedX:function (flippedX) { 787 if (this._flippedX != flippedX) { 788 this._flippedX = flippedX; 789 this.setTextureRect(this._rect, this._rectRotated, this._contentSize); 790 this.setNodeDirty(); 791 } 792 }, 793 794 /** 795 * Sets whether the sprite should be flipped vertically or not. 796 * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise. 797 */ 798 setFlippedY:function (flippedY) { 799 if (this._flippedY != flippedY) { 800 this._flippedY = flippedY; 801 this.setTextureRect(this._rect, this._rectRotated, this._contentSize); 802 this.setNodeDirty(); 803 } 804 }, 805 806 /** 807 * <p> 808 * Returns the flag which indicates whether the sprite is flipped horizontally or not. <br/> 809 * <br/> 810 * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/> 811 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 812 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 813 * sprite->setScaleX(sprite->getScaleX() * -1); <p/> 814 * @return {Boolean} true if the sprite is flipped horizaontally, false otherwise. 815 */ 816 isFlippedX:function () { 817 return this._flippedX; 818 }, 819 820 /** 821 * <p> 822 * Return the flag which indicates whether the sprite is flipped vertically or not. <br/> 823 * <br/> 824 * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/> 825 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 826 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 827 * sprite->setScaleY(sprite->getScaleY() * -1); <p/> 828 * @return {Boolean} true if the sprite is flipped vertically, flase otherwise. 829 */ 830 isFlippedY:function () { 831 return this._flippedY; 832 }, 833 834 // 835 // RGBA protocol 836 // 837 /** 838 * opacity: conforms to CCRGBAProtocol protocol 839 * @param {Boolean} modify 840 */ 841 setOpacityModifyRGB:null, 842 843 _setOpacityModifyRGBForWebGL: function (modify) { 844 if (this._opacityModifyRGB !== modify) { 845 this._opacityModifyRGB = modify; 846 this.updateColor(); 847 } 848 }, 849 850 _setOpacityModifyRGBForCanvas: function (modify) { 851 if (this._opacityModifyRGB !== modify) { 852 this._opacityModifyRGB = modify; 853 this.setNodeDirty(); 854 } 855 }, 856 857 /** 858 * return IsOpacityModifyRGB value 859 * @return {Boolean} 860 */ 861 isOpacityModifyRGB:function () { 862 return this._opacityModifyRGB; 863 }, 864 865 updateDisplayedOpacity: null, 866 _updateDisplayedOpacityForWebGL:function (parentOpacity) { 867 cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 868 this.updateColor(); 869 }, 870 871 _updateDisplayedOpacityForCanvas:function (parentOpacity) { 872 cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 873 this._setNodeDirtyForCache(); 874 }, 875 876 // Animation 877 878 /** 879 * changes the display frame with animation name and index.<br/> 880 * The animation name will be get from the CCAnimationCache 881 * @param animationName 882 * @param frameIndex 883 */ 884 setDisplayFrameWithAnimationName:function (animationName, frameIndex) { 885 if(!animationName) 886 throw "cc.Sprite.setDisplayFrameWithAnimationName(): animationName must be non-null"; 887 var cache = cc.AnimationCache.getInstance().getAnimation(animationName); 888 if(!cache){ 889 cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Frame not found"); 890 return; 891 } 892 var animFrame = cache.getFrames()[frameIndex]; 893 if(!animFrame){ 894 cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Invalid frame index"); 895 return; 896 } 897 this.setDisplayFrame(animFrame.getSpriteFrame()); 898 }, 899 900 /** 901 * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode 902 * @returns {cc.SpriteBatchNode|null} The cc.SpriteBatchNode object if this sprite is rendered by cc.SpriteBatchNode, null if the sprite isn't used batch node. 903 */ 904 getBatchNode:function () { 905 return this._batchNode; 906 }, 907 908 _setReorderChildDirtyRecursively:function () { 909 //only set parents flag the first time 910 if (!this._reorderChildDirty) { 911 this._reorderChildDirty = true; 912 var pNode = this._parent; 913 while (pNode && pNode != this._batchNode) { 914 pNode._setReorderChildDirtyRecursively(); 915 pNode = pNode.getParent(); 916 } 917 } 918 }, 919 920 // CCTextureProtocol 921 getTexture:function () { 922 return this._texture; 923 }, 924 925 _quad:null, // vertex coords, texture coords and color info 926 _quadWebBuffer:null, 927 _quadDirty:false, 928 _colorized:false, 929 _isLighterMode:false, 930 _originalTexture:null, 931 _textureRect_Canvas:null, 932 _drawSize_Canvas:null, 933 934 /** 935 * Constructor 936 * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter 937 */ 938 ctor: null, 939 940 _ctorForWebGL: function (fileName) { 941 cc.NodeRGBA.prototype.ctor.call(this); 942 this._shouldBeHidden = false; 943 this._offsetPosition = cc.p(0, 0); 944 this._unflippedOffsetPositionFromCenter = cc.p(0, 0); 945 this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; 946 this._rect = cc.rect(0,0,0,0); 947 948 this._quad = new cc.V3F_C4B_T2F_Quad(); 949 this._quadWebBuffer = cc.renderContext.createBuffer(); 950 this._quadDirty = true; 951 952 this._textureLoaded = true; 953 954 if (fileName) { 955 if (typeof(fileName) === "string") { 956 var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); 957 this.initWithSpriteFrame(frame); 958 } else if (typeof(fileName) === "object") { 959 if (fileName instanceof cc.SpriteFrame) { 960 this.initWithSpriteFrame(fileName); 961 } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { 962 var texture2d = new cc.Texture2D(); 963 texture2d.initWithElement(fileName); 964 texture2d.handleLoadedTexture(); 965 this.initWithTexture(texture2d); 966 } else if (fileName instanceof cc.Texture2D) { 967 this.initWithTexture(fileName); 968 } 969 } 970 } 971 }, 972 973 _ctorForCanvas: function (fileName) { 974 cc.NodeRGBA.prototype.ctor.call(this); 975 this._shouldBeHidden = false; 976 this._offsetPosition = cc.p(0, 0); 977 this._unflippedOffsetPositionFromCenter = cc.p(0, 0); 978 this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; 979 this._rect = cc.rect(0, 0, 0, 0); 980 981 this._newTextureWhenChangeColor = false; 982 this._textureLoaded = true; 983 this._textureRect_Canvas = {x: 0, y: 0, width: 0, height:0, validRect: false}; 984 this._drawSize_Canvas = cc.size(0, 0); 985 986 if (fileName) { 987 if (typeof(fileName) === "string") { 988 var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); 989 this.initWithSpriteFrame(frame); 990 } else if (typeof(fileName) === "object") { 991 if (fileName instanceof cc.SpriteFrame) { 992 this.initWithSpriteFrame(fileName); 993 } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { 994 var texture2d = new cc.Texture2D(); 995 texture2d.initWithElement(fileName); 996 texture2d.handleLoadedTexture(); 997 this.initWithTexture(texture2d); 998 } else if (fileName instanceof cc.Texture2D) { 999 this.initWithTexture(fileName); 1000 } 1001 } 1002 } 1003 }, 1004 1005 /** 1006 * Returns the quad (tex coords, vertex coords and color) information. 1007 * @return {cc.V3F_C4B_T2F_Quad} 1008 */ 1009 getQuad:function () { 1010 return this._quad; 1011 }, 1012 1013 /** 1014 * conforms to cc.TextureProtocol protocol 1015 * @param {Number|cc.BlendFunc} src 1016 * @param {Number} dst 1017 */ 1018 setBlendFunc: null, 1019 1020 _setBlendFuncForWebGL: function (src, dst) { 1021 var locBlendFunc = this._blendFunc; 1022 if (dst === undefined) { 1023 locBlendFunc.src = src.src; 1024 locBlendFunc.dst = src.dst; 1025 } else { 1026 locBlendFunc.src = src; 1027 locBlendFunc.dst = dst; 1028 } 1029 }, 1030 1031 _setBlendFuncForCanvas: function (src, dst) { 1032 var locBlendFunc = this._blendFunc; 1033 if (dst === undefined) { 1034 locBlendFunc.src = src.src; 1035 locBlendFunc.dst = src.dst; 1036 } else { 1037 locBlendFunc.src = src; 1038 locBlendFunc.dst = dst; 1039 } 1040 this._isLighterMode = (locBlendFunc && 1041 (( locBlendFunc.src == gl.SRC_ALPHA && locBlendFunc.dst == gl.ONE) || (locBlendFunc.src == gl.ONE && locBlendFunc.dst == gl.ONE))); 1042 }, 1043 1044 /** 1045 * Initializes an empty sprite with nothing init. 1046 * @return {Boolean} 1047 */ 1048 init:null, 1049 1050 _initForWebGL: function () { 1051 if (arguments.length > 0) 1052 return this.initWithFile(arguments[0], arguments[1]); 1053 1054 cc.NodeRGBA.prototype.init.call(this); 1055 this._dirty = this._recursiveDirty = false; 1056 this._opacityModifyRGB = true; 1057 1058 this._blendFunc.src = cc.BLEND_SRC; 1059 this._blendFunc.dst = cc.BLEND_DST; 1060 1061 // update texture (calls _updateBlendFunc) 1062 this.setTexture(null); 1063 this._textureLoaded = true; 1064 this._flippedX = this._flippedY = false; 1065 1066 // default transform anchor: center 1067 this.setAnchorPoint(0.5, 0.5); 1068 1069 // zwoptex default values 1070 this._offsetPosition.x = 0; 1071 this._offsetPosition.y = 0; 1072 1073 this._hasChildren = false; 1074 1075 // Atlas: Color 1076 var tempColor = {r: 255, g: 255, b: 255, a: 255}; 1077 this._quad.bl.colors = tempColor; 1078 this._quad.br.colors = tempColor; 1079 this._quad.tl.colors = tempColor; 1080 this._quad.tr.colors = tempColor; 1081 this._quadDirty = true; 1082 1083 // updated in "useSelfRender" 1084 // Atlas: TexCoords 1085 this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); 1086 return true; 1087 }, 1088 1089 _initForCanvas: function () { 1090 if (arguments.length > 0) 1091 return this.initWithFile(arguments[0], arguments[1]); 1092 1093 cc.NodeRGBA.prototype.init.call(this); 1094 this._dirty = this._recursiveDirty = false; 1095 this._opacityModifyRGB = true; 1096 1097 this._blendFunc.src = cc.BLEND_SRC; 1098 this._blendFunc.dst = cc.BLEND_DST; 1099 1100 // update texture (calls _updateBlendFunc) 1101 this.setTexture(null); 1102 this._textureLoaded = true; 1103 this._flippedX = this._flippedY = false; 1104 1105 // default transform anchor: center 1106 this.setAnchorPoint(0.5, 0.5); 1107 1108 // zwoptex default values 1109 this._offsetPosition.x = 0; 1110 this._offsetPosition.y = 0; 1111 this._hasChildren = false; 1112 1113 // updated in "useSelfRender" 1114 // Atlas: TexCoords 1115 this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); 1116 return true; 1117 }, 1118 1119 /** 1120 * <p> 1121 * Initializes a sprite with an image filename. 1122 * 1123 * This method will find pszFilename from local file system, load its content to CCTexture2D, 1124 * then use CCTexture2D to create a sprite. 1125 * After initialization, the rect used will be the size of the image. The offset will be (0,0). 1126 * </p> 1127 * @param {String} filename The path to an image file in local file system 1128 * @param {cc.Rect} rect The rectangle assigned the content area from texture. 1129 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 1130 * @example 1131 * var mySprite = new cc.Sprite(); 1132 * mySprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); 1133 */ 1134 initWithFile:function (filename, rect) { 1135 if(!filename) 1136 throw "cc.Sprite.initWithFile(): filename should be non-null"; 1137 1138 var texture = cc.TextureCache.getInstance().textureForKey(filename); 1139 if (!texture) { 1140 texture = cc.TextureCache.getInstance().addImage(filename); 1141 return this.initWithTexture(texture, rect); 1142 } else { 1143 if (!rect) { 1144 var size = texture.getContentSize(); 1145 rect = cc.rect(0, 0, size.width, size.height); 1146 } 1147 return this.initWithTexture(texture, rect); 1148 } 1149 }, 1150 1151 /** 1152 * Initializes a sprite with a texture and a rect in points, optionally rotated. <br/> 1153 * After initialization, the rect used will be the size of the texture, and the offset will be (0,0). 1154 * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. 1155 * @param {cc.Rect} rect Only the contents inside rect of this texture will be applied for this sprite. 1156 * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated. 1157 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 1158 * @example 1159 * var img =cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); 1160 * var mySprite = new cc.Sprite(); 1161 * mySprite.initWithTexture(img,cc.rect(0,0,480,320)); 1162 */ 1163 initWithTexture: null, 1164 1165 _initWithTextureForWebGL: function (texture, rect, rotated) { 1166 var argnum = arguments.length; 1167 if (argnum == 0) 1168 throw "Sprite.initWithTexture(): Argument must be non-nil "; 1169 1170 rotated = rotated || false; 1171 1172 if (!cc.NodeRGBA.prototype.init.call(this)) 1173 return false; 1174 1175 this._batchNode = null; 1176 this._recursiveDirty = false; 1177 this._dirty = false; 1178 this._opacityModifyRGB = true; 1179 1180 this._blendFunc.src = cc.BLEND_SRC; 1181 this._blendFunc.dst = cc.BLEND_DST; 1182 1183 this._flippedX = this._flippedY = false; 1184 1185 // default transform anchor: center 1186 this.setAnchorPoint(0.5, 0.5); 1187 1188 // zwoptex default values 1189 this._offsetPosition.x = 0; 1190 this._offsetPosition.y = 0; 1191 this._hasChildren = false; 1192 1193 // Atlas: Color 1194 var tmpColor = new cc.Color4B(255, 255, 255, 255); 1195 var locQuad = this._quad; 1196 locQuad.bl.colors = tmpColor; 1197 locQuad.br.colors = tmpColor; 1198 locQuad.tl.colors = tmpColor; 1199 locQuad.tr.colors = tmpColor; 1200 1201 var locTextureLoaded = texture.isLoaded(); 1202 this._textureLoaded = locTextureLoaded; 1203 1204 if (!locTextureLoaded) { 1205 this._rectRotated = rotated || false; 1206 if (rect) { 1207 var locRect = this._rect; 1208 locRect.x = rect.x; 1209 locRect.y = rect.y; 1210 locRect.width = rect.width; 1211 locRect.height = rect.height; 1212 } 1213 texture.addLoadedEventListener(this._textureLoadedCallback, this); 1214 return true; 1215 } 1216 1217 if (!rect) { 1218 var locSize1 = texture.getContentSize(); 1219 rect = cc.rect(0, 0, locSize1.width, locSize1.height); 1220 } 1221 this.setTexture(texture); 1222 this.setTextureRect(rect, rotated, rect._size); 1223 1224 // by default use "Self Render". 1225 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1226 this.setBatchNode(null); 1227 this._quadDirty = true; 1228 return true; 1229 }, 1230 1231 _initWithTextureForCanvas: function (texture, rect, rotated) { 1232 var argnum = arguments.length; 1233 if (argnum == 0) 1234 throw "Sprite.initWithTexture(): Argument must be non-nil "; 1235 1236 rotated = rotated || false; 1237 1238 if (!cc.NodeRGBA.prototype.init.call(this)) 1239 return false; 1240 1241 this._batchNode = null; 1242 1243 this._recursiveDirty = false; 1244 this._dirty = false; 1245 this._opacityModifyRGB = true; 1246 1247 this._blendFunc.src = cc.BLEND_SRC; 1248 this._blendFunc.dst = cc.BLEND_DST; 1249 1250 this._flippedX = this._flippedY = false; 1251 1252 // default transform anchor: center 1253 this.setAnchorPoint(0.5, 0.5); 1254 1255 // zwoptex default values 1256 this._offsetPosition.x = 0; 1257 this._offsetPosition.y = 0; 1258 this._hasChildren = false; 1259 1260 var locTextureLoaded = texture.isLoaded(); 1261 this._textureLoaded = locTextureLoaded; 1262 1263 if (!locTextureLoaded) { 1264 this._rectRotated = rotated || false; 1265 if (rect) { 1266 this._rect.x = rect.x; 1267 this._rect.y = rect.y; 1268 this._rect.width = rect.width; 1269 this._rect.height = rect.height; 1270 } 1271 texture.addLoadedEventListener(this._textureLoadedCallback, this); 1272 return true; 1273 } 1274 1275 if (!rect) { 1276 var locSize1 = texture.getContentSize(); 1277 rect = cc.rect(0, 0, locSize1.width, locSize1.height); 1278 } 1279 this._originalTexture = texture; 1280 1281 this.setTexture(texture); 1282 this.setTextureRect(rect, rotated, rect._size); 1283 1284 // by default use "Self Render". 1285 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1286 this.setBatchNode(null); 1287 return true; 1288 }, 1289 1290 _textureLoadedCallback: null, 1291 1292 _textureLoadedCallbackForWebGL: function (sender) { 1293 if(this._textureLoaded) 1294 return; 1295 1296 this._textureLoaded = true; 1297 var locRect = this._rect; 1298 if (!locRect) { 1299 var locSize1 = sender.getContentSize(); 1300 locRect = cc.rect(0, 0, locSize1.width, locSize1.height); 1301 } else if (cc._rectEqualToZero(locRect)) { 1302 var locSize2 = sender.getContentSize(); 1303 locRect.width = locSize2.width; 1304 locRect.height = locSize2.height; 1305 } 1306 1307 this.setTexture(sender); 1308 this.setTextureRect(locRect, this._rectRotated, locRect._size); 1309 1310 // by default use "Self Render". 1311 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1312 this.setBatchNode(this._batchNode); 1313 this._quadDirty = true; 1314 this._callLoadedEventCallbacks(); 1315 }, 1316 1317 _textureLoadedCallbackForCanvas: function (sender) { 1318 if(this._textureLoaded) 1319 return; 1320 1321 this._textureLoaded = true; 1322 var locRect = this._rect; 1323 if (!locRect) { 1324 var locSize1 = sender.getContentSize(); 1325 locRect = cc.rect(0, 0, locSize1.width, locSize1.height); 1326 } else if (cc._rectEqualToZero(locRect)) { 1327 var locSize2 = sender.getContentSize(); 1328 locRect.width = locSize2.width; 1329 locRect.height = locSize2.height; 1330 } 1331 this._originalTexture = sender; 1332 1333 this.setTexture(sender); 1334 this.setTextureRect(locRect, this._rectRotated, locRect._size); 1335 1336 // by default use "Self Render". 1337 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1338 this.setBatchNode(this._batchNode); 1339 this._callLoadedEventCallbacks(); 1340 }, 1341 1342 /** 1343 * updates the texture rect of the CCSprite in points. 1344 * @param {cc.Rect} rect a rect of texture 1345 * @param {Boolean} rotated 1346 * @param {cc.Size} untrimmedSize 1347 */ 1348 setTextureRect:null, 1349 1350 _setTextureRectForWebGL:function (rect, rotated, untrimmedSize) { 1351 this._rectRotated = rotated || false; 1352 untrimmedSize = untrimmedSize || rect._size; 1353 1354 this.setContentSize(untrimmedSize); 1355 this.setVertexRect(rect); 1356 this._setTextureCoords(rect); 1357 1358 var relativeOffset = this._unflippedOffsetPositionFromCenter; 1359 if (this._flippedX) 1360 relativeOffset.x = -relativeOffset.x; 1361 if (this._flippedY) 1362 relativeOffset.y = -relativeOffset.y; 1363 1364 var locRect = this._rect; 1365 this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - locRect.width) / 2; 1366 this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - locRect.height) / 2; 1367 1368 // rendering using batch node 1369 if (this._batchNode) { 1370 // update dirty_, don't update recursiveDirty_ 1371 //this.setDirty(true); 1372 this._dirty = true; 1373 } else { 1374 // self rendering 1375 // Atlas: Vertex 1376 var x1 = 0 + this._offsetPosition.x; 1377 var y1 = 0 + this._offsetPosition.y; 1378 var x2 = x1 + locRect.width; 1379 var y2 = y1 + locRect.height; 1380 1381 // Don't update Z. 1382 var locQuad = this._quad; 1383 locQuad.bl.vertices = {x:x1, y:y1, z:0}; 1384 locQuad.br.vertices = {x:x2, y:y1, z:0}; 1385 locQuad.tl.vertices = {x:x1, y:y2, z:0}; 1386 locQuad.tr.vertices = {x:x2, y:y2, z:0}; 1387 1388 this._quadDirty = true; 1389 } 1390 }, 1391 1392 _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) { 1393 this._rectRotated = rotated || false; 1394 untrimmedSize = untrimmedSize || rect._size; 1395 1396 this.setContentSize(untrimmedSize); 1397 this.setVertexRect(rect); 1398 1399 var locTextureRect = this._textureRect_Canvas, scaleFactor = cc.CONTENT_SCALE_FACTOR(); 1400 locTextureRect.x = 0 | (rect.x * scaleFactor); 1401 locTextureRect.y = 0 | (rect.y * scaleFactor); 1402 locTextureRect.width = 0 | (rect.width * scaleFactor); 1403 locTextureRect.height = 0 | (rect.height * scaleFactor); 1404 locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0 || locTextureRect.x < 0 || locTextureRect.y < 0); 1405 1406 var relativeOffset = this._unflippedOffsetPositionFromCenter; 1407 if (this._flippedX) 1408 relativeOffset.x = -relativeOffset.x; 1409 if (this._flippedY) 1410 relativeOffset.y = -relativeOffset.y; 1411 this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2; 1412 this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2; 1413 1414 // rendering using batch node 1415 if (this._batchNode) { 1416 // update dirty_, don't update recursiveDirty_ 1417 //this.setDirty(true); 1418 this._dirty = true; 1419 } 1420 }, 1421 1422 // BatchNode methods 1423 /** 1424 * updates the quad according the the rotation, position, scale values. 1425 */ 1426 updateTransform: null, 1427 1428 _updateTransformForWebGL: function () { 1429 //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); 1430 1431 // recaculate matrix only if it is dirty 1432 if (this.isDirty()) { 1433 var locQuad = this._quad, locParent = this._parent; 1434 // If it is not visible, or one of its ancestors is not visible, then do nothing: 1435 if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { 1436 locQuad.br.vertices = {x: 0, y: 0, z: 0}; 1437 locQuad.tl.vertices = {x: 0, y: 0, z: 0}; 1438 locQuad.tr.vertices = {x: 0, y: 0, z: 0}; 1439 locQuad.bl.vertices = {x: 0, y: 0, z: 0}; 1440 this._shouldBeHidden = true; 1441 } else { 1442 this._shouldBeHidden = false; 1443 1444 if (!locParent || locParent == this._batchNode) { 1445 this._transformToBatch = this.nodeToParentTransform(); 1446 } else { 1447 //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); 1448 this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); 1449 } 1450 1451 // 1452 // calculate the Quad based on the Affine Matrix 1453 // 1454 var locTransformToBatch = this._transformToBatch; 1455 var size = this._rect._size; 1456 var x1 = this._offsetPosition.x; 1457 var y1 = this._offsetPosition.y; 1458 1459 var x2 = x1 + size.width; 1460 var y2 = y1 + size.height; 1461 var x = locTransformToBatch.tx; 1462 var y = locTransformToBatch.ty; 1463 1464 var cr = locTransformToBatch.a; 1465 var sr = locTransformToBatch.b; 1466 var cr2 = locTransformToBatch.d; 1467 var sr2 = -locTransformToBatch.c; 1468 var ax = x1 * cr - y1 * sr2 + x; 1469 var ay = x1 * sr + y1 * cr2 + y; 1470 1471 var bx = x2 * cr - y1 * sr2 + x; 1472 var by = x2 * sr + y1 * cr2 + y; 1473 1474 var cx = x2 * cr - y2 * sr2 + x; 1475 var cy = x2 * sr + y2 * cr2 + y; 1476 1477 var dx = x1 * cr - y2 * sr2 + x; 1478 var dy = x1 * sr + y2 * cr2 + y; 1479 1480 var locVertexZ = this._vertexZ; 1481 locQuad.bl.vertices = {x: cc.RENDER_IN_SUBPIXEL(ax), y: cc.RENDER_IN_SUBPIXEL(ay), z: locVertexZ}; 1482 locQuad.br.vertices = {x: cc.RENDER_IN_SUBPIXEL(bx), y: cc.RENDER_IN_SUBPIXEL(by), z: locVertexZ}; 1483 locQuad.tl.vertices = {x: cc.RENDER_IN_SUBPIXEL(dx), y: cc.RENDER_IN_SUBPIXEL(dy), z: locVertexZ}; 1484 locQuad.tr.vertices = {x: cc.RENDER_IN_SUBPIXEL(cx), y: cc.RENDER_IN_SUBPIXEL(cy), z: locVertexZ}; 1485 } 1486 this._textureAtlas.updateQuad(locQuad, this._atlasIndex); 1487 this._recursiveDirty = false; 1488 this.setDirty(false); 1489 } 1490 1491 // recursively iterate over children 1492 if (this._hasChildren) 1493 this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); 1494 1495 if (cc.SPRITE_DEBUG_DRAW) { 1496 // draw bounding box 1497 var vertices = [ 1498 cc.p(this._quad.bl.vertices.x, this._quad.bl.vertices.y), 1499 cc.p(this._quad.br.vertices.x, this._quad.br.vertices.y), 1500 cc.p(this._quad.tr.vertices.x, this._quad.tr.vertices.y), 1501 cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y) 1502 ]; 1503 cc.drawingUtil.drawPoly(vertices, 4, true); 1504 } 1505 }, 1506 1507 _updateTransformForCanvas: function () { 1508 //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); 1509 1510 // recaculate matrix only if it is dirty 1511 if (this._dirty) { 1512 // If it is not visible, or one of its ancestors is not visible, then do nothing: 1513 var locParent = this._parent; 1514 if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { 1515 this._shouldBeHidden = true; 1516 } else { 1517 this._shouldBeHidden = false; 1518 1519 if (!locParent || locParent == this._batchNode) { 1520 this._transformToBatch = this.nodeToParentTransform(); 1521 } else { 1522 //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); 1523 this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); 1524 } 1525 } 1526 this._recursiveDirty = false; 1527 this._dirty = false; 1528 } 1529 1530 // recursively iterate over children 1531 if (this._hasChildren) 1532 this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); 1533 }, 1534 1535 /** 1536 * Add child to sprite (override cc.Node ) 1537 * @param {cc.Sprite} child 1538 * @param {Number} zOrder child's zOrder 1539 * @param {String} tag child's tag 1540 * @override 1541 */ 1542 addChild: null, 1543 1544 _addChildForWebGL:function (child, zOrder, tag) { 1545 if(!child) 1546 throw "cc.Sprite.addChild(): child should be non-null"; 1547 if (zOrder == null) 1548 zOrder = child._zOrder; 1549 if (tag == null) 1550 tag = child._tag; 1551 1552 if (this._batchNode) { 1553 if(!(child instanceof cc.Sprite)){ 1554 cc.log("cc.Sprite.addChild(): cc.Sprite only supports cc.Sprites as children when using cc.SpriteBatchNode"); 1555 return; 1556 } 1557 if(child.getTexture()._webTextureObj !== this._textureAtlas.getTexture()._webTextureObj) 1558 cc.log("cc.Sprite.addChild(): cc.Sprite only supports a sprite using same texture as children when using cc.SpriteBatchNode"); 1559 1560 //put it in descendants array of batch node 1561 this._batchNode.appendChild(child); 1562 if (!this._reorderChildDirty) 1563 this._setReorderChildDirtyRecursively(); 1564 } 1565 1566 //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check 1567 cc.NodeRGBA.prototype.addChild.call(this, child, zOrder, tag); 1568 this._hasChildren = true; 1569 }, 1570 1571 _addChildForCanvas: function (child, zOrder, tag) { 1572 if(!child) 1573 throw "cc.Sprite.addChild(): child should be non-null"; 1574 if (zOrder == null) 1575 zOrder = child._zOrder; 1576 if (tag == null) 1577 tag = child._tag; 1578 1579 //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check 1580 cc.NodeRGBA.prototype.addChild.call(this, child, zOrder, tag); 1581 this._hasChildren = true; 1582 }, 1583 1584 /** 1585 * Update sprite's color 1586 */ 1587 updateColor:function () { 1588 var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity; 1589 var color4 = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: locDisplayedOpacity}; 1590 // special opacity for premultiplied textures 1591 if (this._opacityModifyRGB) { 1592 color4.r *= locDisplayedOpacity / 255.0; 1593 color4.g *= locDisplayedOpacity / 255.0; 1594 color4.b *= locDisplayedOpacity / 255.0; 1595 } 1596 var locQuad = this._quad; 1597 locQuad.bl.colors = color4; 1598 locQuad.br.colors = color4; 1599 locQuad.tl.colors = color4; 1600 locQuad.tr.colors = color4; 1601 1602 // renders using Sprite Manager 1603 if (this._batchNode) { 1604 if (this._atlasIndex != cc.SPRITE_INDEX_NOT_INITIALIZED) { 1605 this._textureAtlas.updateQuad(locQuad, this._atlasIndex) 1606 } else { 1607 // no need to set it recursively 1608 // update dirty_, don't update recursiveDirty_ 1609 //this.setDirty(true); 1610 this._dirty = true; 1611 } 1612 } 1613 // self render 1614 // do nothing 1615 this._quadDirty = true; 1616 }, 1617 1618 /** 1619 * opacity setter 1620 * @param {Number} opacity 1621 */ 1622 setOpacity:null, 1623 1624 _setOpacityForWebGL: function (opacity) { 1625 cc.NodeRGBA.prototype.setOpacity.call(this, opacity); 1626 this.updateColor(); 1627 }, 1628 1629 _setOpacityForCanvas: function (opacity) { 1630 cc.NodeRGBA.prototype.setOpacity.call(this, opacity); 1631 this._setNodeDirtyForCache(); 1632 }, 1633 1634 /** 1635 * color setter 1636 * @param {cc.Color3B} color3 1637 */ 1638 setColor: null, 1639 1640 _setColorForWebGL: function (color3) { 1641 cc.NodeRGBA.prototype.setColor.call(this, color3); 1642 this.updateColor(); 1643 }, 1644 1645 _setColorForCanvas: function (color3) { 1646 var curColor = this.getColor(); 1647 if ((curColor.r === color3.r) && (curColor.g === color3.g) && (curColor.b === color3.b)) 1648 return; 1649 1650 cc.NodeRGBA.prototype.setColor.call(this, color3); 1651 this._changeTextureColor(); 1652 this._setNodeDirtyForCache(); 1653 }, 1654 1655 updateDisplayedColor: null, 1656 1657 _updateDisplayedColorForWebGL: function (parentColor) { 1658 cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); 1659 this.updateColor(); 1660 }, 1661 1662 _updateDisplayedColorForCanvas: function (parentColor) { 1663 var oldColor = this.getColor(); 1664 cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); 1665 var newColor = this._displayedColor; 1666 if ((oldColor.r === newColor.r) && (oldColor.g === newColor.g) && (oldColor.b === newColor.b)) 1667 return; 1668 this._changeTextureColor(); 1669 this._setNodeDirtyForCache(); 1670 }, 1671 1672 // Frames 1673 /** 1674 * Sets a new display frame to the cc.Sprite. 1675 * @param {cc.SpriteFrame} newFrame 1676 */ 1677 setDisplayFrame: null, 1678 1679 _setDisplayFrameForWebGL: function (newFrame) { 1680 this.setNodeDirty(); 1681 var frameOffset = newFrame.getOffset(); 1682 this._unflippedOffsetPositionFromCenter.x = frameOffset.x; 1683 this._unflippedOffsetPositionFromCenter.y = frameOffset.y; 1684 1685 var pNewTexture = newFrame.getTexture(); 1686 var locTextureLoaded = newFrame.textureLoaded(); 1687 if (!locTextureLoaded) { 1688 this._textureLoaded = false; 1689 newFrame.addLoadedEventListener(function (sender) { 1690 this._textureLoaded = true; 1691 var locNewTexture = sender.getTexture(); 1692 if (locNewTexture != this._texture) 1693 this.setTexture(locNewTexture); 1694 this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); 1695 1696 this._callLoadedEventCallbacks(); 1697 }, this); 1698 } 1699 // update texture before updating texture rect 1700 if (pNewTexture != this._texture) 1701 this.setTexture(pNewTexture); 1702 1703 // update rect 1704 this._rectRotated = newFrame.isRotated(); 1705 this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); 1706 }, 1707 1708 _setDisplayFrameForCanvas: function (newFrame) { 1709 this.setNodeDirty(); 1710 1711 var frameOffset = newFrame.getOffset(); 1712 this._unflippedOffsetPositionFromCenter.x = frameOffset.x; 1713 this._unflippedOffsetPositionFromCenter.y = frameOffset.y; 1714 1715 // update rect 1716 this._rectRotated = newFrame.isRotated(); 1717 1718 var pNewTexture = newFrame.getTexture(); 1719 var locTextureLoaded = newFrame.textureLoaded(); 1720 if (!locTextureLoaded) { 1721 this._textureLoaded = false; 1722 newFrame.addLoadedEventListener(function (sender) { 1723 this._textureLoaded = true; 1724 var locNewTexture = sender.getTexture(); 1725 if (locNewTexture != this._texture) 1726 this.setTexture(locNewTexture); 1727 this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); 1728 this._callLoadedEventCallbacks(); 1729 }, this); 1730 } 1731 // update texture before updating texture rect 1732 if (pNewTexture != this._texture) 1733 this.setTexture(pNewTexture); 1734 1735 if (this._rectRotated) 1736 this._originalTexture = pNewTexture; 1737 1738 this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); 1739 this._colorized = false; 1740 if (locTextureLoaded) { 1741 var curColor = this.getColor(); 1742 if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) 1743 this._changeTextureColor(); 1744 } 1745 }, 1746 1747 /** 1748 * Returns whether or not a cc.SpriteFrame is being displayed 1749 * @param {cc.SpriteFrame} frame 1750 * @return {Boolean} 1751 */ 1752 isFrameDisplayed: null, 1753 1754 _isFrameDisplayedForWebGL: function (frame) { 1755 return (cc.rectEqualToRect(frame.getRect(), this._rect) && frame.getTexture().getName() == this._texture.getName() 1756 && cc.pointEqualToPoint(frame.getOffset(), this._unflippedOffsetPositionFromCenter)); 1757 }, 1758 1759 _isFrameDisplayedForCanvas: function (frame) { 1760 if (frame.getTexture() != this._texture) 1761 return false; 1762 return cc.rectEqualToRect(frame.getRect(), this._rect); 1763 }, 1764 1765 /** 1766 * Returns the current displayed frame. 1767 * @return {cc.SpriteFrame} 1768 */ 1769 displayFrame: function () { 1770 return cc.SpriteFrame.createWithTexture(this._texture, 1771 cc.RECT_POINTS_TO_PIXELS(this._rect), 1772 this._rectRotated, 1773 cc.POINT_POINTS_TO_PIXELS(this._unflippedOffsetPositionFromCenter), 1774 cc.SIZE_POINTS_TO_PIXELS(this._contentSize)); 1775 }, 1776 1777 /** 1778 * Sets the batch node to sprite 1779 * @param {cc.SpriteBatchNode|null} spriteBatchNode 1780 * @example 1781 * var batch = cc.SpriteBatchNode.create("Images/grossini_dance_atlas.png", 15); 1782 * var sprite = cc.Sprite.createWithTexture(batch.getTexture(), cc.rect(0, 0, 57, 57)); 1783 * batch.addChild(sprite); 1784 * layer.addChild(batch); 1785 */ 1786 setBatchNode:null, 1787 1788 _setBatchNodeForWebGL:function (spriteBatchNode) { 1789 this._batchNode = spriteBatchNode; // weak reference 1790 1791 // self render 1792 if (!this._batchNode) { 1793 this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; 1794 this.setTextureAtlas(null); 1795 this._recursiveDirty = false; 1796 this.setDirty(false); 1797 1798 var x1 = this._offsetPosition.x; 1799 var y1 = this._offsetPosition.y; 1800 var x2 = x1 + this._rect.width; 1801 var y2 = y1 + this._rect.height; 1802 var locQuad = this._quad; 1803 locQuad.bl.vertices = {x:x1, y:y1, z:0}; 1804 locQuad.br.vertices = {x:x2, y:y1, z:0}; 1805 locQuad.tl.vertices = {x:x1, y:y2, z:0}; 1806 locQuad.tr.vertices = {x:x2, y:y2, z:0}; 1807 1808 this._quadDirty = true; 1809 } else { 1810 // using batch 1811 this._transformToBatch = cc.AffineTransformIdentity(); 1812 this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref 1813 } 1814 }, 1815 1816 _setBatchNodeForCanvas:function (spriteBatchNode) { 1817 this._batchNode = spriteBatchNode; // weak reference 1818 1819 // self render 1820 if (!this._batchNode) { 1821 this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; 1822 this.setTextureAtlas(null); 1823 this._recursiveDirty = false; 1824 this.setDirty(false); 1825 } else { 1826 // using batch 1827 this._transformToBatch = cc.AffineTransformIdentity(); 1828 this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref 1829 } 1830 }, 1831 1832 // CCTextureProtocol 1833 /** 1834 * Texture of sprite setter 1835 * @param {cc.Texture2D} texture 1836 */ 1837 setTexture: null, 1838 1839 _setTextureForWebGL: function (texture) { 1840 // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet 1841 if(texture && !(texture instanceof cc.Texture2D)) 1842 throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; 1843 1844 // If batchnode, then texture id should be the same 1845 if(this._batchNode && this._batchNode.getTexture() != texture) { 1846 cc.log("cc.Sprite.setTexture(): Batched sprites should use the same texture as the batchnode"); 1847 return; 1848 } 1849 1850 if (texture) 1851 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); 1852 else 1853 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); 1854 1855 if (!this._batchNode && this._texture != texture) { 1856 this._texture = texture; 1857 this._updateBlendFunc(); 1858 } 1859 }, 1860 1861 _setTextureForCanvas: function (texture) { 1862 // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet 1863 if(texture && !(texture instanceof cc.Texture2D)) 1864 throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; 1865 1866 if (this._texture != texture) { 1867 if (texture && texture.getHtmlElementObj() instanceof HTMLImageElement) { 1868 this._originalTexture = texture; 1869 } 1870 this._texture = texture; 1871 } 1872 }, 1873 1874 // Texture protocol 1875 _updateBlendFunc:function () { 1876 if(this._batchNode){ 1877 cc.log("cc.Sprite._updateBlendFunc(): _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode"); 1878 return; 1879 } 1880 1881 // it's possible to have an untextured sprite 1882 if (!this._texture || !this._texture.hasPremultipliedAlpha()) { 1883 this._blendFunc.src = gl.SRC_ALPHA; 1884 this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; 1885 this.setOpacityModifyRGB(false); 1886 } else { 1887 this._blendFunc.src = cc.BLEND_SRC; 1888 this._blendFunc.dst = cc.BLEND_DST; 1889 this.setOpacityModifyRGB(true); 1890 } 1891 }, 1892 1893 _changeTextureColor: function () { 1894 var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect(); 1895 if (locTexture && locRect.validRect && this._originalTexture) { 1896 locElement = locTexture.getHtmlElementObj(); 1897 if (!locElement) 1898 return; 1899 1900 var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj()); 1901 if (cacheTextureForColor) { 1902 this._colorized = true; 1903 //generate color texture cache 1904 if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor) 1905 cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement); 1906 else { 1907 locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect); 1908 locTexture = new cc.Texture2D(); 1909 locTexture.initWithElement(locElement); 1910 locTexture.handleLoadedTexture(); 1911 this.setTexture(locTexture); 1912 } 1913 } 1914 } 1915 }, 1916 1917 _setTextureCoords:function (rect) { 1918 rect = cc.RECT_POINTS_TO_PIXELS(rect); 1919 1920 var tex = this._batchNode ? this._textureAtlas.getTexture() : this._texture; 1921 if (!tex) 1922 return; 1923 1924 var atlasWidth = tex.getPixelsWide(); 1925 var atlasHeight = tex.getPixelsHigh(); 1926 1927 var left, right, top, bottom, tempSwap, locQuad = this._quad; 1928 if (this._rectRotated) { 1929 if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { 1930 left = (2 * rect.x + 1) / (2 * atlasWidth); 1931 right = left + (rect.height * 2 - 2) / (2 * atlasWidth); 1932 top = (2 * rect.y + 1) / (2 * atlasHeight); 1933 bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight); 1934 } else { 1935 left = rect.x / atlasWidth; 1936 right = (rect.x + rect.height) / atlasWidth; 1937 top = rect.y / atlasHeight; 1938 bottom = (rect.y + rect.width) / atlasHeight; 1939 }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1940 1941 if (this._flippedX) { 1942 tempSwap = top; 1943 top = bottom; 1944 bottom = tempSwap; 1945 } 1946 1947 if (this._flippedY) { 1948 tempSwap = left; 1949 left = right; 1950 right = tempSwap; 1951 } 1952 1953 locQuad.bl.texCoords.u = left; 1954 locQuad.bl.texCoords.v = top; 1955 locQuad.br.texCoords.u = left; 1956 locQuad.br.texCoords.v = bottom; 1957 locQuad.tl.texCoords.u = right; 1958 locQuad.tl.texCoords.v = top; 1959 locQuad.tr.texCoords.u = right; 1960 locQuad.tr.texCoords.v = bottom; 1961 } else { 1962 if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { 1963 left = (2 * rect.x + 1) / (2 * atlasWidth); 1964 right = left + (rect.width * 2 - 2) / (2 * atlasWidth); 1965 top = (2 * rect.y + 1) / (2 * atlasHeight); 1966 bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight); 1967 } else { 1968 left = rect.x / atlasWidth; 1969 right = (rect.x + rect.width) / atlasWidth; 1970 top = rect.y / atlasHeight; 1971 bottom = (rect.y + rect.height) / atlasHeight; 1972 } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1973 1974 if (this._flippedX) { 1975 tempSwap = left; 1976 left = right; 1977 right = tempSwap; 1978 } 1979 1980 if (this._flippedY) { 1981 tempSwap = top; 1982 top = bottom; 1983 bottom = tempSwap; 1984 } 1985 1986 locQuad.bl.texCoords.u = left; 1987 locQuad.bl.texCoords.v = bottom; 1988 locQuad.br.texCoords.u = right; 1989 locQuad.br.texCoords.v = bottom; 1990 locQuad.tl.texCoords.u = left; 1991 locQuad.tl.texCoords.v = top; 1992 locQuad.tr.texCoords.u = right; 1993 locQuad.tr.texCoords.v = top; 1994 } 1995 this._quadDirty = true; 1996 }, 1997 /** 1998 * draw sprite to canvas 1999 */ 2000 draw: null, 2001 2002 _drawForWebGL: function () { 2003 if (!this._textureLoaded) 2004 return; 2005 2006 var gl = cc.renderContext, locTexture = this._texture; 2007 //cc.Assert(!this._batchNode, "If cc.Sprite is being rendered by cc.SpriteBatchNode, cc.Sprite#draw SHOULD NOT be called"); 2008 2009 if (locTexture) { 2010 if (locTexture._isLoaded) { 2011 this._shaderProgram.use(); 2012 this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); 2013 2014 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 2015 //optimize performance for javascript 2016 cc.glBindTexture2DN(0, locTexture); // = cc.glBindTexture2D(locTexture); 2017 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); 2018 2019 gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); 2020 if (this._quadDirty) { 2021 gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.DYNAMIC_DRAW); 2022 this._quadDirty = false; 2023 } 2024 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0); //cc.VERTEX_ATTRIB_POSITION 2025 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 24, 12); //cc.VERTEX_ATTRIB_COLOR 2026 gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 24, 16); //cc.VERTEX_ATTRIB_TEX_COORDS 2027 2028 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 2029 } 2030 } else { 2031 this._shaderProgram.use(); 2032 this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); 2033 2034 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 2035 cc.glBindTexture2D(null); 2036 2037 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR); 2038 2039 gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); 2040 if (this._quadDirty) { 2041 cc.renderContext.bufferData(cc.renderContext.ARRAY_BUFFER, this._quad.arrayBuffer, cc.renderContext.STATIC_DRAW); 2042 this._quadDirty = false; 2043 } 2044 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); 2045 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); 2046 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 2047 } 2048 cc.g_NumberOfDraws++; 2049 if (cc.SPRITE_DEBUG_DRAW === 0) 2050 return; 2051 2052 if (cc.SPRITE_DEBUG_DRAW === 1) { 2053 // draw bounding box 2054 var locQuad = this._quad; 2055 var verticesG1 = [ 2056 cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y), 2057 cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y), 2058 cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y), 2059 cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y) 2060 ]; 2061 cc.drawingUtil.drawPoly(verticesG1, 4, true); 2062 } else if (cc.SPRITE_DEBUG_DRAW === 2) { 2063 // draw texture box 2064 var drawSizeG2 = this.getTextureRect()._size; 2065 var offsetPixG2 = this.getOffsetPosition(); 2066 var verticesG2 = [cc.p(offsetPixG2.x, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y), 2067 cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y + drawSizeG2.height), cc.p(offsetPixG2.x, offsetPixG2.y + drawSizeG2.height)]; 2068 cc.drawingUtil.drawPoly(verticesG2, 4, true); 2069 } // CC_SPRITE_DEBUG_DRAW 2070 }, 2071 2072 _drawForCanvas: function (ctx) { 2073 if (!this._textureLoaded) 2074 return; 2075 2076 var context = ctx || cc.renderContext; 2077 if (this._isLighterMode) 2078 context.globalCompositeOperation = 'lighter'; 2079 2080 var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY(); 2081 2082 context.globalAlpha = this._displayedOpacity / 255; 2083 var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition, locDrawSizeCanvas = this._drawSize_Canvas; 2084 var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = this._textureRect_Canvas; 2085 locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX; 2086 locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY; 2087 2088 if (this._flippedX || this._flippedY) { 2089 context.save(); 2090 if (this._flippedX) { 2091 flipXOffset = -locOffsetPosition.x - locRect.width; 2092 context.scale(-1, 1); 2093 } 2094 if (this._flippedY) { 2095 flipYOffset = locOffsetPosition.y; 2096 context.scale(1, -1); 2097 } 2098 } 2099 2100 flipXOffset *= locEGL_ScaleX; 2101 flipYOffset *= locEGL_ScaleY; 2102 2103 if (this._texture && locTextureCoord.validRect) { 2104 var image = this._texture.getHtmlElementObj(); 2105 if (this._colorized) { 2106 context.drawImage(image, 2107 0, 0, locTextureCoord.width, locTextureCoord.height, 2108 flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height); 2109 } else { 2110 context.drawImage(image, 2111 locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height, 2112 flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height); 2113 } 2114 } else if (locContentSize.width !== 0) { 2115 var curColor = this.getColor(); 2116 context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)"; 2117 context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY); 2118 } 2119 2120 if (cc.SPRITE_DEBUG_DRAW === 1) { 2121 // draw bounding box 2122 context.strokeStyle = "rgba(0,255,0,1)"; 2123 flipXOffset /= locEGL_ScaleX; 2124 flipYOffset /= locEGL_ScaleY; 2125 flipYOffset = -flipYOffset; 2126 var vertices1 = [cc.p(flipXOffset, flipYOffset), 2127 cc.p(flipXOffset + locRect.width, flipYOffset), 2128 cc.p(flipXOffset + locRect.width, flipYOffset - locRect.height), 2129 cc.p(flipXOffset, flipYOffset - locRect.height)]; 2130 cc.drawingUtil.drawPoly(vertices1, 4, true); 2131 } else if (cc.SPRITE_DEBUG_DRAW === 2) { 2132 // draw texture box 2133 context.strokeStyle = "rgba(0,255,0,1)"; 2134 var drawSize = this._rect._size; 2135 flipYOffset = -flipYOffset; 2136 var vertices2 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + drawSize.width, flipYOffset), 2137 cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; 2138 cc.drawingUtil.drawPoly(vertices2, 4, true); 2139 } 2140 if (this._flippedX || this._flippedY) 2141 context.restore(); 2142 cc.g_NumberOfDraws++; 2143 } 2144 }); 2145 2146 if(cc.Browser.supportWebGL){ 2147 cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForWebGL; 2148 cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForWebGL; 2149 cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForWebGL; 2150 cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForWebGL; 2151 cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForWebGL; 2152 cc.Sprite.prototype.init = cc.Sprite.prototype._initForWebGL; 2153 cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForWebGL; 2154 cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForWebGL; 2155 cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL; 2156 cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForWebGL; 2157 cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForWebGL; 2158 cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForWebGL; 2159 cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForWebGL; 2160 cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForWebGL; 2161 cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForWebGL; 2162 cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForWebGL; 2163 cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForWebGL; 2164 cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForWebGL; 2165 cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForWebGL; 2166 }else{ 2167 cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForCanvas; 2168 cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForCanvas; 2169 cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForCanvas; 2170 cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForCanvas; 2171 cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForCanvas; 2172 cc.Sprite.prototype.init = cc.Sprite.prototype._initForCanvas; 2173 cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForCanvas; 2174 cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForCanvas; 2175 cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForCanvas; 2176 cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForCanvas; 2177 cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForCanvas; 2178 cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForCanvas; 2179 cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForCanvas; 2180 cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForCanvas; 2181 cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForCanvas; 2182 cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForCanvas; 2183 cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas; 2184 cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas; 2185 cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas; 2186 } 2187 2188 /** 2189 * <p> 2190 * Creates a sprite with an exsiting texture contained in a CCTexture2D object <br/> 2191 * After creation, the rect will be the size of the texture, and the offset will be (0,0). 2192 * </p> 2193 * @constructs 2194 * @param {cc.Texture2D} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. 2195 * @param {cc.Rect} rect Only the contents inside the rect of this texture will be applied for this sprite. 2196 * @return {cc.Sprite} A valid sprite object 2197 * @example 2198 * //get an image 2199 * var img = cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); 2200 * 2201 * //create a sprite with texture 2202 * var sprite1 = cc.Sprite.createWithTexture(img); 2203 * 2204 * //create a sprite with texture and rect 2205 * var sprite2 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320)); 2206 * 2207 */ 2208 cc.Sprite.createWithTexture = function (texture, rect) { 2209 var argnum = arguments.length; 2210 var sprite = new cc.Sprite(); 2211 switch (argnum) { 2212 case 1: 2213 /** Creates an sprite with a texture. 2214 The rect used will be the size of the texture. 2215 The offset will be (0,0). 2216 */ 2217 if (sprite && sprite.initWithTexture(texture)) 2218 return sprite; 2219 return null; 2220 break; 2221 2222 case 2: 2223 /** Creates an sprite with a texture and a rect. 2224 The offset will be (0,0). 2225 */ 2226 if (sprite && sprite.initWithTexture(texture, rect)) 2227 return sprite; 2228 return null; 2229 break; 2230 2231 default: 2232 throw "Sprite.createWithTexture(): Argument must be non-nil "; 2233 break; 2234 } 2235 }; 2236 2237 /** 2238 * Create a sprite with filename and rect 2239 * @constructs 2240 * @param {String} fileName The string which indicates a path to image file, e.g., "scene1/monster.png". 2241 * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite. 2242 * @return {cc.Sprite} A valid sprite object 2243 * @example 2244 * //create a sprite with filename 2245 * var sprite1 = cc.Sprite.create("HelloHTML5World.png"); 2246 * 2247 * //create a sprite with filename and rect 2248 * var sprite2 = cc.Sprite.create("HelloHTML5World.png",cc.rect(0,0,480,320)); 2249 */ 2250 cc.Sprite.create = function (fileName, rect) { 2251 var argnum = arguments.length; 2252 var sprite = new cc.Sprite(); 2253 if (argnum === 0) { 2254 if (sprite.init()) 2255 return sprite; 2256 } else { 2257 /** Creates an sprite with an image filename. 2258 If the rect equal undefined, the rect used will be the size of the image. 2259 The offset will be (0,0). 2260 */ 2261 if (sprite && sprite.init(fileName, rect)) 2262 return sprite; 2263 } 2264 return null; 2265 }; 2266 2267 /** 2268 * <p> 2269 * Creates a sprite with a sprite frame. <br/> 2270 * <br/> 2271 * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param. <br/> 2272 * If the CCSpriteFrame doesn't exist it will raise an exception. 2273 * </p> 2274 * @param {String} spriteFrameName A sprite frame which involves a texture and a rect 2275 * @return {cc.Sprite} A valid sprite object 2276 * @example 2277 * 2278 * //create a sprite with a sprite frame 2279 * var sprite = cc.Sprite.createWithSpriteFrameName('grossini_dance_01.png'); 2280 */ 2281 cc.Sprite.createWithSpriteFrameName = function (spriteFrameName) { 2282 var spriteFrame = null; 2283 if (typeof(spriteFrameName) == 'string') { 2284 spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); 2285 if (!spriteFrame) { 2286 cc.log("Invalid spriteFrameName: " + spriteFrameName); 2287 return null; 2288 } 2289 } else { 2290 cc.log("Invalid argument. Expecting string."); 2291 return null; 2292 } 2293 var sprite = new cc.Sprite(); 2294 if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { 2295 return sprite; 2296 } 2297 return null; 2298 }; 2299 2300 /** 2301 * <p> 2302 * Creates a sprite with a sprite frame. <br/> 2303 * <br/> 2304 * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param. <br/> 2305 * If the CCSpriteFrame doesn't exist it will raise an exception. 2306 * </p> 2307 * @param {cc.SpriteFrame} spriteFrame A sprite frame which involves a texture and a rect 2308 * @return {cc.Sprite} A valid sprite object 2309 * @example 2310 * //get a sprite frame 2311 * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png"); 2312 * 2313 * //create a sprite with a sprite frame 2314 * var sprite = cc.Sprite.createWithSpriteFrame(spriteFrame); 2315 */ 2316 cc.Sprite.createWithSpriteFrame = function (spriteFrame) { 2317 var sprite = new cc.Sprite(); 2318 if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { 2319 return sprite; 2320 } 2321 return null; 2322 }; 2323