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.hasOwnProperty('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 selCallback.eventCallback.call(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 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 return this.initWithSpriteFrame(frame); 511 }, 512 513 /** 514 * tell the sprite to use batch node render. 515 * @param {cc.SpriteBatchNode} batchNode 516 */ 517 useBatchNode:function (batchNode) { 518 this._textureAtlas = batchNode.getTextureAtlas(); // weak ref 519 this._batchNode = batchNode; 520 }, 521 522 /** 523 * <p> 524 * set the vertex rect.<br/> 525 * It will be called internally by setTextureRect. <br/> 526 * Useful if you want to create 2x images from SD images in Retina Display. <br/> 527 * Do not call it manually. Use setTextureRect instead. <br/> 528 * (override this method to generate "double scale" sprites) 529 * </p> 530 * @param {cc.Rect} rect 531 */ 532 setVertexRect:function (rect) { 533 this._rect.x = rect.x; 534 this._rect.y = rect.y; 535 this._rect.width = rect.width; 536 this._rect.height = rect.height; 537 }, 538 539 sortAllChildren:function () { 540 if (this._reorderChildDirty) { 541 var j, tempItem, locChildren = this._children, tempChild; 542 for (var i = 1; i < locChildren.length; i++) { 543 tempItem = locChildren[i]; 544 j = i - 1; 545 tempChild = locChildren[j]; 546 547 //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller 548 while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || 549 ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { 550 locChildren[j + 1] = tempChild; 551 j = j - 1; 552 tempChild = locChildren[j]; 553 } 554 locChildren[j + 1] = tempItem; 555 } 556 557 if (this._batchNode) { 558 this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); 559 } 560 this._reorderChildDirty = false; 561 } 562 }, 563 564 /** 565 * Reorders a child according to a new z value. (override cc.Node ) 566 * @param {cc.Node} child 567 * @param {Number} zOrder 568 * @override 569 */ 570 reorderChild:function (child, zOrder) { 571 if(!child) 572 throw "cc.Sprite.reorderChild(): child should be non-null"; 573 if(this._children.indexOf(child) === -1){ 574 cc.log("cc.Sprite.reorderChild(): this child is not in children list"); 575 return; 576 } 577 578 if (zOrder === child.getZOrder()) 579 return; 580 581 if (this._batchNode && !this._reorderChildDirty) { 582 this._setReorderChildDirtyRecursively(); 583 this._batchNode.reorderBatch(true); 584 } 585 cc.Node.prototype.reorderChild.call(this, child, zOrder); 586 }, 587 588 /** 589 * Removes a child from the sprite. (override cc.Node ) 590 * @param child 591 * @param cleanup whether or not cleanup all running actions 592 * @override 593 */ 594 removeChild:function (child, cleanup) { 595 if (this._batchNode) 596 this._batchNode.removeSpriteFromAtlas(child); 597 cc.Node.prototype.removeChild.call(this, child, cleanup); 598 }, 599 600 /** 601 * Removes all children from the container (override cc.Node ) 602 * @param cleanup whether or not cleanup all running actions 603 * @override 604 */ 605 removeAllChildren:function (cleanup) { 606 var locChildren = this._children, locBatchNode = this._batchNode; 607 if (locBatchNode && locChildren != null) { 608 for (var i = 0, len = locChildren.length; i < len; i++) 609 locBatchNode.removeSpriteFromAtlas(locChildren[i]); 610 } 611 612 cc.Node.prototype.removeAllChildren.call(this, cleanup); 613 this._hasChildren = false; 614 }, 615 616 // 617 // cc.Node property overloads 618 // 619 620 /** 621 * set Recursively is or isn't Dirty 622 * used only when parent is cc.SpriteBatchNode 623 * @param {Boolean} value 624 */ 625 setDirtyRecursively:function (value) { 626 this._recursiveDirty = value; 627 this.setDirty(value); 628 // recursively set dirty 629 var locChildren = this._children; 630 if (locChildren != null) { 631 for (var i = 0; i < locChildren.length; i++) { 632 if (locChildren[i] instanceof cc.Sprite) 633 locChildren[i].setDirtyRecursively(true); 634 } 635 } 636 }, 637 638 /** 639 * HACK: optimization 640 */ 641 SET_DIRTY_RECURSIVELY:function () { 642 if (this._batchNode && !this._recursiveDirty) { 643 this._recursiveDirty = true; 644 this._dirty = true; 645 if (this._hasChildren) 646 this.setDirtyRecursively(true); 647 } 648 }, 649 650 /** 651 * position setter (override cc.Node ) 652 * @param {cc.Point|Number} pos position or x value of position 653 * @param {Number} [yValue] y value of position 654 * @override 655 */ 656 setPosition:function (pos, yValue) { 657 if (arguments.length >= 2) 658 cc.Node.prototype.setPosition.call(this, pos, arguments[1]); 659 else 660 cc.Node.prototype.setPosition.call(this, pos); 661 this.SET_DIRTY_RECURSIVELY(); 662 }, 663 664 /** 665 * Rotation setter (override cc.Node ) 666 * @param {Number} rotation 667 * @override 668 */ 669 setRotation:function (rotation) { 670 cc.Node.prototype.setRotation.call(this, rotation); 671 this.SET_DIRTY_RECURSIVELY(); 672 }, 673 674 setRotationX:function (rotationX) { 675 cc.Node.prototype.setRotationX.call(this, rotationX); 676 this.SET_DIRTY_RECURSIVELY(); 677 }, 678 679 setRotationY:function (rotationY) { 680 cc.Node.prototype.setRotationY.call(this, rotationY); 681 this.SET_DIRTY_RECURSIVELY(); 682 }, 683 684 /** 685 * SkewX setter (override cc.Node ) 686 * @param {Number} sx SkewX value 687 * @override 688 */ 689 setSkewX:function (sx) { 690 cc.Node.prototype.setSkewX.call(this, sx); 691 this.SET_DIRTY_RECURSIVELY(); 692 }, 693 694 /** 695 * SkewY setter (override cc.Node ) 696 * @param {Number} sy SkewY value 697 * @override 698 */ 699 setSkewY:function (sy) { 700 cc.Node.prototype.setSkewY.call(this, sy); 701 this.SET_DIRTY_RECURSIVELY(); 702 }, 703 704 /** 705 * ScaleX setter (override cc.Node ) 706 * @param {Number} scaleX 707 * @override 708 */ 709 setScaleX:function (scaleX) { 710 cc.Node.prototype.setScaleX.call(this, scaleX); 711 this.SET_DIRTY_RECURSIVELY(); 712 }, 713 714 /** 715 * ScaleY setter (override cc.Node ) 716 * @param {Number} scaleY 717 * @override 718 */ 719 setScaleY:function (scaleY) { 720 cc.Node.prototype.setScaleY.call(this, scaleY); 721 this.SET_DIRTY_RECURSIVELY(); 722 }, 723 724 /** 725 * <p>The scale factor of the node. 1.0 is the default scale factor. <br/> 726 * It modifies the X and Y scale at the same time. (override cc.Node ) <p/> 727 * @param {Number} scale 728 * @param {Number|null} [scaleY=] 729 * @override 730 */ 731 setScale:function (scale, scaleY) { 732 cc.Node.prototype.setScale.call(this, scale, scaleY); 733 this.SET_DIRTY_RECURSIVELY(); 734 }, 735 736 /** 737 * VertexZ setter (override cc.Node ) 738 * @param {Number} vertexZ 739 * @override 740 */ 741 setVertexZ:function (vertexZ) { 742 cc.Node.prototype.setVertexZ.call(this, vertexZ); 743 this.SET_DIRTY_RECURSIVELY(); 744 }, 745 746 /** 747 * Sets the anchor point in percent. (override cc.Node ) 748 * @param {cc.Point|Number} anchor The anchor Sprite of Sprite or The anchor point.x of Sprite. 749 * @param {Number} [y] The anchor point.y of Sprite. 750 * @override 751 */ 752 setAnchorPoint:function (anchor, y) { 753 if(arguments.length === 2) 754 cc.Node.prototype.setAnchorPoint.call(this, anchor, y); 755 else 756 cc.Node.prototype.setAnchorPoint.call(this, anchor); 757 this.SET_DIRTY_RECURSIVELY(); 758 }, 759 760 /** 761 * visible setter (override cc.Node ) 762 * @param {Boolean} visible 763 * @override 764 */ 765 setVisible:function (visible) { 766 cc.Node.prototype.setVisible.call(this, visible); 767 this.SET_DIRTY_RECURSIVELY(); 768 }, 769 770 /** 771 * IsRelativeAnchorPoint setter (override cc.Node ) 772 * @param {Boolean} relative 773 * @override 774 */ 775 ignoreAnchorPointForPosition:function (relative) { 776 if(this._batchNode){ 777 cc.log("cc.Sprite.ignoreAnchorPointForPosition(): it is invalid in cc.Sprite when using SpriteBatchNode"); 778 return; 779 } 780 cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); 781 }, 782 783 /** 784 * Sets whether the sprite should be flipped horizontally or not. 785 * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise. 786 */ 787 setFlippedX:function (flippedX) { 788 if (this._flippedX != flippedX) { 789 this._flippedX = flippedX; 790 this.setTextureRect(this._rect, this._rectRotated, this._contentSize); 791 this.setNodeDirty(); 792 } 793 }, 794 795 /** 796 * Sets whether the sprite should be flipped vertically or not. 797 * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise. 798 */ 799 setFlippedY:function (flippedY) { 800 if (this._flippedY != flippedY) { 801 this._flippedY = flippedY; 802 this.setTextureRect(this._rect, this._rectRotated, this._contentSize); 803 this.setNodeDirty(); 804 } 805 }, 806 807 /** 808 * <p> 809 * Returns the flag which indicates whether the sprite is flipped horizontally or not. <br/> 810 * <br/> 811 * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/> 812 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 813 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 814 * sprite->setScaleX(sprite->getScaleX() * -1); <p/> 815 * @return {Boolean} true if the sprite is flipped horizaontally, false otherwise. 816 */ 817 isFlippedX:function () { 818 return this._flippedX; 819 }, 820 821 /** 822 * <p> 823 * Return the flag which indicates whether the sprite is flipped vertically or not. <br/> 824 * <br/> 825 * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/> 826 * Also, flipping the texture doesn't alter the anchorPoint. <br/> 827 * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/> 828 * sprite->setScaleY(sprite->getScaleY() * -1); <p/> 829 * @return {Boolean} true if the sprite is flipped vertically, flase otherwise. 830 */ 831 isFlippedY:function () { 832 return this._flippedY; 833 }, 834 835 // 836 // RGBA protocol 837 // 838 /** 839 * opacity: conforms to CCRGBAProtocol protocol 840 * @param {Boolean} modify 841 */ 842 setOpacityModifyRGB:null, 843 844 _setOpacityModifyRGBForWebGL: function (modify) { 845 if (this._opacityModifyRGB !== modify) { 846 this._opacityModifyRGB = modify; 847 this.updateColor(); 848 } 849 }, 850 851 _setOpacityModifyRGBForCanvas: function (modify) { 852 if (this._opacityModifyRGB !== modify) { 853 this._opacityModifyRGB = modify; 854 this.setNodeDirty(); 855 } 856 }, 857 858 /** 859 * return IsOpacityModifyRGB value 860 * @return {Boolean} 861 */ 862 isOpacityModifyRGB:function () { 863 return this._opacityModifyRGB; 864 }, 865 866 updateDisplayedOpacity: null, 867 _updateDisplayedOpacityForWebGL:function (parentOpacity) { 868 cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 869 this.updateColor(); 870 }, 871 872 _updateDisplayedOpacityForCanvas:function (parentOpacity) { 873 cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); 874 this._setNodeDirtyForCache(); 875 }, 876 877 // Animation 878 879 /** 880 * changes the display frame with animation name and index.<br/> 881 * The animation name will be get from the CCAnimationCache 882 * @param animationName 883 * @param frameIndex 884 */ 885 setDisplayFrameWithAnimationName:function (animationName, frameIndex) { 886 if(!animationName) 887 throw "cc.Sprite.setDisplayFrameWithAnimationName(): animationName must be non-null"; 888 var cache = cc.AnimationCache.getInstance().getAnimation(animationName); 889 if(!cache){ 890 cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Frame not found"); 891 return; 892 } 893 var animFrame = cache.getFrames()[frameIndex]; 894 if(!animFrame){ 895 cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Invalid frame index"); 896 return; 897 } 898 this.setDisplayFrame(animFrame.getSpriteFrame()); 899 }, 900 901 /** 902 * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode 903 * @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. 904 */ 905 getBatchNode:function () { 906 return this._batchNode; 907 }, 908 909 _setReorderChildDirtyRecursively:function () { 910 //only set parents flag the first time 911 if (!this._reorderChildDirty) { 912 this._reorderChildDirty = true; 913 var pNode = this._parent; 914 while (pNode && pNode != this._batchNode) { 915 pNode._setReorderChildDirtyRecursively(); 916 pNode = pNode.getParent(); 917 } 918 } 919 }, 920 921 // CCTextureProtocol 922 getTexture:function () { 923 return this._texture; 924 }, 925 926 _quad:null, // vertex coords, texture coords and color info 927 _quadWebBuffer:null, 928 _quadDirty:false, 929 _colorized:false, 930 _isLighterMode:false, 931 _originalTexture:null, 932 _textureRect_Canvas:null, 933 _drawSize_Canvas:null, 934 935 /** 936 * Constructor 937 * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter 938 */ 939 ctor: null, 940 941 _ctorForWebGL: function (fileName) { 942 cc.NodeRGBA.prototype.ctor.call(this); 943 this._shouldBeHidden = false; 944 this._offsetPosition = cc._pConst(0, 0); 945 this._unflippedOffsetPositionFromCenter = cc._pConst(0, 0); 946 this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; 947 this._rect = cc.rect(0,0,0,0); 948 949 this._quad = new cc.V3F_C4B_T2F_Quad(); 950 this._quadWebBuffer = cc.renderContext.createBuffer(); 951 this._quadDirty = true; 952 953 this._textureLoaded = true; 954 955 if (fileName) { 956 if (typeof(fileName) === "string") { 957 var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); 958 this.initWithSpriteFrame(frame); 959 } else if (typeof(fileName) === "object") { 960 if (fileName instanceof cc.SpriteFrame) { 961 this.initWithSpriteFrame(fileName); 962 } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { 963 var texture2d = new cc.Texture2D(); 964 texture2d.initWithElement(fileName); 965 texture2d.handleLoadedTexture(); 966 this.initWithTexture(texture2d); 967 } else if (fileName instanceof cc.Texture2D) { 968 this.initWithTexture(fileName); 969 } 970 } 971 } 972 }, 973 974 _ctorForCanvas: function (fileName) { 975 cc.NodeRGBA.prototype.ctor.call(this); 976 this._shouldBeHidden = false; 977 this._offsetPosition = cc._pConst(0, 0); 978 this._unflippedOffsetPositionFromCenter = cc._pConst(0, 0); 979 this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; 980 this._rect = cc.rect(0, 0, 0, 0); 981 982 this._newTextureWhenChangeColor = false; 983 this._textureLoaded = true; 984 this._textureRect_Canvas = {x: 0, y: 0, width: 0, height:0, validRect: false}; 985 this._drawSize_Canvas = cc.size(0, 0); 986 987 if (fileName) { 988 if (typeof(fileName) === "string") { 989 var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); 990 this.initWithSpriteFrame(frame); 991 } else if (typeof(fileName) === "object") { 992 if (fileName instanceof cc.SpriteFrame) { 993 this.initWithSpriteFrame(fileName); 994 } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { 995 var texture2d = new cc.Texture2D(); 996 texture2d.initWithElement(fileName); 997 texture2d.handleLoadedTexture(); 998 this.initWithTexture(texture2d); 999 } else if (fileName instanceof cc.Texture2D) { 1000 this.initWithTexture(fileName); 1001 } 1002 } 1003 } 1004 }, 1005 1006 /** 1007 * Returns the quad (tex coords, vertex coords and color) information. 1008 * @return {cc.V3F_C4B_T2F_Quad} 1009 */ 1010 getQuad:function () { 1011 return this._quad; 1012 }, 1013 1014 /** 1015 * conforms to cc.TextureProtocol protocol 1016 * @param {Number|cc.BlendFunc} src 1017 * @param {Number} dst 1018 */ 1019 setBlendFunc: null, 1020 1021 _setBlendFuncForWebGL: function (src, dst) { 1022 var locBlendFunc = this._blendFunc; 1023 if (arguments.length === 1) { 1024 locBlendFunc.src = src.src; 1025 locBlendFunc.dst = src.dst; 1026 } else { 1027 locBlendFunc.src = src; 1028 locBlendFunc.dst = dst; 1029 } 1030 }, 1031 1032 _setBlendFuncForCanvas: function (src, dst) { 1033 var locBlendFunc = this._blendFunc; 1034 if (arguments.length === 1) { 1035 locBlendFunc.src = src.src; 1036 locBlendFunc.dst = src.dst; 1037 } else { 1038 locBlendFunc.src = src; 1039 locBlendFunc.dst = dst; 1040 } 1041 this._isLighterMode = (locBlendFunc && 1042 (( locBlendFunc.src == gl.SRC_ALPHA && locBlendFunc.dst == gl.ONE) || (locBlendFunc.src == gl.ONE && locBlendFunc.dst == gl.ONE))); 1043 }, 1044 1045 /** 1046 * Initializes an empty sprite with nothing init. 1047 * @return {Boolean} 1048 */ 1049 init:null, 1050 1051 _initForWebGL: function () { 1052 if (arguments.length > 0) 1053 return this.initWithFile(arguments[0], arguments[1]); 1054 1055 cc.NodeRGBA.prototype.init.call(this); 1056 this._dirty = this._recursiveDirty = false; 1057 this._opacityModifyRGB = true; 1058 1059 this._blendFunc.src = cc.BLEND_SRC; 1060 this._blendFunc.dst = cc.BLEND_DST; 1061 1062 // update texture (calls _updateBlendFunc) 1063 this.setTexture(null); 1064 this._textureLoaded = true; 1065 this._flippedX = this._flippedY = false; 1066 1067 // default transform anchor: center 1068 this.setAnchorPoint(0.5, 0.5); 1069 1070 // zwoptex default values 1071 this._offsetPosition._x = 0; 1072 this._offsetPosition._y = 0; 1073 1074 this._hasChildren = false; 1075 1076 // Atlas: Color 1077 var tempColor = {r: 255, g: 255, b: 255, a: 255}; 1078 this._quad.bl.colors = tempColor; 1079 this._quad.br.colors = tempColor; 1080 this._quad.tl.colors = tempColor; 1081 this._quad.tr.colors = tempColor; 1082 this._quadDirty = true; 1083 1084 // updated in "useSelfRender" 1085 // Atlas: TexCoords 1086 this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); 1087 return true; 1088 }, 1089 1090 _initForCanvas: function () { 1091 if (arguments.length > 0) 1092 return this.initWithFile(arguments[0], arguments[1]); 1093 1094 cc.NodeRGBA.prototype.init.call(this); 1095 this._dirty = this._recursiveDirty = false; 1096 this._opacityModifyRGB = true; 1097 1098 this._blendFunc.src = cc.BLEND_SRC; 1099 this._blendFunc.dst = cc.BLEND_DST; 1100 1101 // update texture (calls _updateBlendFunc) 1102 this.setTexture(null); 1103 this._textureLoaded = true; 1104 this._flippedX = this._flippedY = false; 1105 1106 // default transform anchor: center 1107 this.setAnchorPoint(0.5, 0.5); 1108 1109 // zwoptex default values 1110 this._offsetPosition._x = 0; 1111 this._offsetPosition._y = 0; 1112 this._hasChildren = false; 1113 1114 // updated in "useSelfRender" 1115 // Atlas: TexCoords 1116 this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); 1117 return true; 1118 }, 1119 1120 /** 1121 * <p> 1122 * Initializes a sprite with an image filename. 1123 * 1124 * This method will find pszFilename from local file system, load its content to CCTexture2D, 1125 * then use CCTexture2D to create a sprite. 1126 * After initialization, the rect used will be the size of the image. The offset will be (0,0). 1127 * </p> 1128 * @param {String} filename The path to an image file in local file system 1129 * @param {cc.Rect} rect The rectangle assigned the content area from texture. 1130 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 1131 * @example 1132 * var mySprite = new cc.Sprite(); 1133 * mySprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); 1134 */ 1135 initWithFile:function (filename, rect) { 1136 if(!filename) 1137 throw "cc.Sprite.initWithFile(): filename should be non-null"; 1138 1139 var texture = cc.TextureCache.getInstance().textureForKey(filename); 1140 if (!texture) { 1141 texture = cc.TextureCache.getInstance().addImage(filename); 1142 return this.initWithTexture(texture, rect); 1143 } else { 1144 if (!rect) { 1145 var size = texture.getContentSize(); 1146 rect = cc.rect(0, 0, size.width, size.height); 1147 } 1148 return this.initWithTexture(texture, rect); 1149 } 1150 }, 1151 1152 /** 1153 * Initializes a sprite with a texture and a rect in points, optionally rotated. <br/> 1154 * After initialization, the rect used will be the size of the texture, and the offset will be (0,0). 1155 * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. 1156 * @param {cc.Rect} rect Only the contents inside rect of this texture will be applied for this sprite. 1157 * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated. 1158 * @return {Boolean} true if the sprite is initialized properly, false otherwise. 1159 * @example 1160 * var img =cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); 1161 * var mySprite = new cc.Sprite(); 1162 * mySprite.initWithTexture(img,cc.rect(0,0,480,320)); 1163 */ 1164 initWithTexture: null, 1165 1166 _initWithTextureForWebGL: function (texture, rect, rotated) { 1167 var argnum = arguments.length; 1168 if (argnum == 0) 1169 throw "Sprite.initWithTexture(): Argument must be non-nil "; 1170 1171 rotated = rotated || false; 1172 1173 if (!cc.NodeRGBA.prototype.init.call(this)) 1174 return false; 1175 1176 this._batchNode = null; 1177 this._recursiveDirty = false; 1178 this._dirty = false; 1179 this._opacityModifyRGB = true; 1180 1181 this._blendFunc.src = cc.BLEND_SRC; 1182 this._blendFunc.dst = cc.BLEND_DST; 1183 1184 this._flippedX = this._flippedY = false; 1185 1186 // default transform anchor: center 1187 this.setAnchorPoint(0.5, 0.5); 1188 1189 // zwoptex default values 1190 this._offsetPosition._x = 0; 1191 this._offsetPosition._y = 0; 1192 this._hasChildren = false; 1193 1194 // Atlas: Color 1195 var tmpColor = new cc.Color4B(255, 255, 255, 255); 1196 var locQuad = this._quad; 1197 locQuad.bl.colors = tmpColor; 1198 locQuad.br.colors = tmpColor; 1199 locQuad.tl.colors = tmpColor; 1200 locQuad.tr.colors = tmpColor; 1201 1202 var locTextureLoaded = texture.isLoaded(); 1203 this._textureLoaded = locTextureLoaded; 1204 1205 if (!locTextureLoaded) { 1206 this._rectRotated = rotated || false; 1207 if (rect) { 1208 var locRect = this._rect; 1209 locRect.x = rect.x; 1210 locRect.y = rect.y; 1211 locRect.width = rect.width; 1212 locRect.height = rect.height; 1213 } 1214 texture.addLoadedEventListener(this._textureLoadedCallback, this); 1215 return true; 1216 } 1217 1218 if (!rect) { 1219 var locSize1 = texture.getContentSize(); 1220 rect = cc.rect(0, 0, locSize1.width, locSize1.height); 1221 } 1222 this.setTexture(texture); 1223 this.setTextureRect(rect, rotated, rect._size); 1224 1225 // by default use "Self Render". 1226 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1227 this.setBatchNode(null); 1228 this._quadDirty = true; 1229 return true; 1230 }, 1231 1232 _initWithTextureForCanvas: function (texture, rect, rotated) { 1233 var argnum = arguments.length; 1234 if (argnum == 0) 1235 throw "Sprite.initWithTexture(): Argument must be non-nil "; 1236 1237 rotated = rotated || false; 1238 1239 if (!cc.NodeRGBA.prototype.init.call(this)) 1240 return false; 1241 1242 this._batchNode = null; 1243 1244 this._recursiveDirty = false; 1245 this._dirty = false; 1246 this._opacityModifyRGB = true; 1247 1248 this._blendFunc.src = cc.BLEND_SRC; 1249 this._blendFunc.dst = cc.BLEND_DST; 1250 1251 this._flippedX = this._flippedY = false; 1252 1253 // default transform anchor: center 1254 this.setAnchorPoint(0.5, 0.5); 1255 1256 // zwoptex default values 1257 this._offsetPosition._x = 0; 1258 this._offsetPosition._y = 0; 1259 this._hasChildren = false; 1260 1261 var locTextureLoaded = texture.isLoaded(); 1262 this._textureLoaded = locTextureLoaded; 1263 1264 if (!locTextureLoaded) { 1265 this._rectRotated = rotated || false; 1266 if (rect) { 1267 this._rect.x = rect.x; 1268 this._rect.y = rect.y; 1269 this._rect.width = rect.width; 1270 this._rect.height = rect.height; 1271 } 1272 texture.addLoadedEventListener(this._textureLoadedCallback, this); 1273 return true; 1274 } 1275 1276 if (!rect) { 1277 var locSize1 = texture.getContentSize(); 1278 rect = cc.rect(0, 0, locSize1.width, locSize1.height); 1279 } 1280 this._originalTexture = texture; 1281 1282 this.setTexture(texture); 1283 this.setTextureRect(rect, rotated, rect._size); 1284 1285 // by default use "Self Render". 1286 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1287 this.setBatchNode(null); 1288 return true; 1289 }, 1290 1291 _textureLoadedCallback: null, 1292 1293 _textureLoadedCallbackForWebGL: function (sender) { 1294 if(this._textureLoaded) 1295 return; 1296 1297 this._textureLoaded = true; 1298 var locRect = this._rect; 1299 if (!locRect) { 1300 var locSize1 = sender.getContentSize(); 1301 locRect = cc.rect(0, 0, locSize1.width, locSize1.height); 1302 } else if (cc._rectEqualToZero(locRect)) { 1303 var locSize2 = sender.getContentSize(); 1304 locRect.width = locSize2.width; 1305 locRect.height = locSize2.height; 1306 } 1307 1308 this.setTexture(sender); 1309 this.setTextureRect(locRect, this._rectRotated, locRect._size); 1310 1311 // by default use "Self Render". 1312 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1313 this.setBatchNode(null); 1314 this._quadDirty = true; 1315 this._callLoadedEventCallbacks(); 1316 }, 1317 1318 _textureLoadedCallbackForCanvas: function (sender) { 1319 if(this._textureLoaded) 1320 return; 1321 1322 this._textureLoaded = true; 1323 var locRect = this._rect; 1324 if (!locRect) { 1325 var locSize1 = sender.getContentSize(); 1326 locRect = cc.rect(0, 0, locSize1.width, locSize1.height); 1327 } else if (cc._rectEqualToZero(locRect)) { 1328 var locSize2 = sender.getContentSize(); 1329 locRect.width = locSize2.width; 1330 locRect.height = locSize2.height; 1331 } 1332 this._originalTexture = sender; 1333 1334 this.setTexture(sender); 1335 this.setTextureRect(locRect, this._rectRotated, locRect._size); 1336 1337 // by default use "Self Render". 1338 // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" 1339 this.setBatchNode(null); 1340 this._callLoadedEventCallbacks(); 1341 }, 1342 1343 /** 1344 * updates the texture rect of the CCSprite in points. 1345 * @param {cc.Rect} rect a rect of texture 1346 * @param {Boolean} rotated 1347 * @param {cc.Size} untrimmedSize 1348 */ 1349 setTextureRect:null, 1350 1351 _setTextureRectForWebGL:function (rect, rotated, untrimmedSize) { 1352 this._rectRotated = rotated || false; 1353 untrimmedSize = untrimmedSize || rect._size; 1354 1355 this.setContentSize(untrimmedSize); 1356 this.setVertexRect(rect); 1357 this._setTextureCoords(rect); 1358 1359 var relativeOffset = this._unflippedOffsetPositionFromCenter; 1360 if (this._flippedX) 1361 relativeOffset._x = -relativeOffset._x; 1362 if (this._flippedY) 1363 relativeOffset._y = -relativeOffset._y; 1364 1365 var locRect = this._rect; 1366 this._offsetPosition._x = relativeOffset._x + (this._contentSize._width - locRect.width) / 2; 1367 this._offsetPosition._y = relativeOffset._y + (this._contentSize._height - locRect.height) / 2; 1368 1369 // rendering using batch node 1370 if (this._batchNode) { 1371 // update dirty_, don't update recursiveDirty_ 1372 //this.setDirty(true); 1373 this._dirty = true; 1374 } else { 1375 // self rendering 1376 // Atlas: Vertex 1377 var x1 = 0 + this._offsetPosition._x; 1378 var y1 = 0 + this._offsetPosition._y; 1379 var x2 = x1 + locRect.width; 1380 var y2 = y1 + locRect.height; 1381 1382 // Don't update Z. 1383 var locQuad = this._quad; 1384 locQuad.bl.vertices = {x:x1, y:y1, z:0}; 1385 locQuad.br.vertices = {x:x2, y:y1, z:0}; 1386 locQuad.tl.vertices = {x:x1, y:y2, z:0}; 1387 locQuad.tr.vertices = {x:x2, y:y2, z:0}; 1388 1389 this._quadDirty = true; 1390 } 1391 }, 1392 1393 _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) { 1394 this._rectRotated = rotated || false; 1395 untrimmedSize = untrimmedSize || rect._size; 1396 1397 this.setContentSize(untrimmedSize); 1398 this.setVertexRect(rect); 1399 1400 var locTextureRect = this._textureRect_Canvas, scaleFactor = cc.CONTENT_SCALE_FACTOR(); 1401 locTextureRect.x = 0 | (rect.x * scaleFactor); 1402 locTextureRect.y = 0 | (rect.y * scaleFactor); 1403 locTextureRect.width = 0 | (rect.width * scaleFactor); 1404 locTextureRect.height = 0 | (rect.height * scaleFactor); 1405 locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0); 1406 1407 var relativeOffset = this._unflippedOffsetPositionFromCenter; 1408 if (this._flippedX) 1409 relativeOffset._x = -relativeOffset._x; 1410 if (this._flippedY) 1411 relativeOffset._y = -relativeOffset._y; 1412 this._offsetPosition._x = relativeOffset._x + (this._contentSize._width - this._rect.width) / 2; 1413 this._offsetPosition._y = relativeOffset._y + (this._contentSize._height - this._rect.height) / 2; 1414 1415 // rendering using batch node 1416 if (this._batchNode) { 1417 // update dirty_, don't update recursiveDirty_ 1418 //this.setDirty(true); 1419 this._dirty = true; 1420 } 1421 }, 1422 1423 // BatchNode methods 1424 /** 1425 * updates the quad according the the rotation, position, scale values. 1426 */ 1427 updateTransform: null, 1428 1429 _updateTransformForWebGL: function () { 1430 //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); 1431 1432 // recaculate matrix only if it is dirty 1433 if (this.isDirty()) { 1434 var locQuad = this._quad, locParent = this._parent; 1435 // If it is not visible, or one of its ancestors is not visible, then do nothing: 1436 if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { 1437 locQuad.br.vertices = {x: 0, y: 0, z: 0}; 1438 locQuad.tl.vertices = {x: 0, y: 0, z: 0}; 1439 locQuad.tr.vertices = {x: 0, y: 0, z: 0}; 1440 locQuad.bl.vertices = {x: 0, y: 0, z: 0}; 1441 this._shouldBeHidden = true; 1442 } else { 1443 this._shouldBeHidden = false; 1444 1445 if (!locParent || locParent == this._batchNode) { 1446 this._transformToBatch = this.nodeToParentTransform(); 1447 } else { 1448 //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); 1449 this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); 1450 } 1451 1452 // 1453 // calculate the Quad based on the Affine Matrix 1454 // 1455 var locTransformToBatch = this._transformToBatch; 1456 var size = this._rect._size; 1457 var x1 = this._offsetPosition._x; 1458 var y1 = this._offsetPosition._y; 1459 1460 var x2 = x1 + size.width; 1461 var y2 = y1 + size.height; 1462 var x = locTransformToBatch.tx; 1463 var y = locTransformToBatch.ty; 1464 1465 var cr = locTransformToBatch.a; 1466 var sr = locTransformToBatch.b; 1467 var cr2 = locTransformToBatch.d; 1468 var sr2 = -locTransformToBatch.c; 1469 var ax = x1 * cr - y1 * sr2 + x; 1470 var ay = x1 * sr + y1 * cr2 + y; 1471 1472 var bx = x2 * cr - y1 * sr2 + x; 1473 var by = x2 * sr + y1 * cr2 + y; 1474 1475 var cx = x2 * cr - y2 * sr2 + x; 1476 var cy = x2 * sr + y2 * cr2 + y; 1477 1478 var dx = x1 * cr - y2 * sr2 + x; 1479 var dy = x1 * sr + y2 * cr2 + y; 1480 1481 var locVertexZ = this._vertexZ; 1482 locQuad.bl.vertices = {x: cc.RENDER_IN_SUBPIXEL(ax), y: cc.RENDER_IN_SUBPIXEL(ay), z: locVertexZ}; 1483 locQuad.br.vertices = {x: cc.RENDER_IN_SUBPIXEL(bx), y: cc.RENDER_IN_SUBPIXEL(by), z: locVertexZ}; 1484 locQuad.tl.vertices = {x: cc.RENDER_IN_SUBPIXEL(dx), y: cc.RENDER_IN_SUBPIXEL(dy), z: locVertexZ}; 1485 locQuad.tr.vertices = {x: cc.RENDER_IN_SUBPIXEL(cx), y: cc.RENDER_IN_SUBPIXEL(cy), z: locVertexZ}; 1486 } 1487 this._textureAtlas.updateQuad(locQuad, this._atlasIndex); 1488 this._recursiveDirty = false; 1489 this.setDirty(false); 1490 } 1491 1492 // recursively iterate over children 1493 if (this._hasChildren) 1494 this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); 1495 1496 if (cc.SPRITE_DEBUG_DRAW) { 1497 // draw bounding box 1498 var vertices = [ 1499 cc.p(this._quad.bl.vertices.x, this._quad.bl.vertices.y), 1500 cc.p(this._quad.br.vertices.x, this._quad.br.vertices.y), 1501 cc.p(this._quad.tr.vertices.x, this._quad.tr.vertices.y), 1502 cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y) 1503 ]; 1504 cc.drawingUtil.drawPoly(vertices, 4, true); 1505 } 1506 }, 1507 1508 _updateTransformForCanvas: function () { 1509 //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); 1510 1511 // recaculate matrix only if it is dirty 1512 if (this._dirty) { 1513 // If it is not visible, or one of its ancestors is not visible, then do nothing: 1514 var locParent = this._parent; 1515 if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { 1516 this._shouldBeHidden = true; 1517 } else { 1518 this._shouldBeHidden = false; 1519 1520 if (!locParent || locParent == this._batchNode) { 1521 this._transformToBatch = this.nodeToParentTransform(); 1522 } else { 1523 //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); 1524 this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); 1525 } 1526 } 1527 this._recursiveDirty = false; 1528 this._dirty = false; 1529 } 1530 1531 // recursively iterate over children 1532 if (this._hasChildren) 1533 this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); 1534 }, 1535 1536 /** 1537 * Add child to sprite (override cc.Node ) 1538 * @param {cc.Sprite} child 1539 * @param {Number} zOrder child's zOrder 1540 * @param {String} tag child's tag 1541 * @override 1542 */ 1543 addChild: null, 1544 1545 _addChildForWebGL:function (child, zOrder, tag) { 1546 if(!child) 1547 throw "cc.Sprite.addChild(): child should be non-null"; 1548 if (zOrder == null) 1549 zOrder = child._zOrder; 1550 if (tag == null) 1551 tag = child._tag; 1552 1553 if (this._batchNode) { 1554 if(!(child instanceof cc.Sprite)){ 1555 cc.log("cc.Sprite.addChild(): cc.Sprite only supports cc.Sprites as children when using cc.SpriteBatchNode"); 1556 return; 1557 } 1558 if(child.getTexture()._webTextureObj !== this._textureAtlas.getTexture()._webTextureObj) 1559 cc.log("cc.Sprite.addChild(): cc.Sprite only supports a sprite using same texture as children when using cc.SpriteBatchNode"); 1560 1561 //put it in descendants array of batch node 1562 this._batchNode.appendChild(child); 1563 if (!this._reorderChildDirty) 1564 this._setReorderChildDirtyRecursively(); 1565 } 1566 1567 //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check 1568 cc.Node.prototype.addChild.call(this, child, zOrder, tag); 1569 this._hasChildren = true; 1570 }, 1571 1572 _addChildForCanvas: function (child, zOrder, tag) { 1573 if(!child) 1574 throw "cc.Sprite.addChild(): child should be non-null"; 1575 if (zOrder == null) 1576 zOrder = child._zOrder; 1577 if (tag == null) 1578 tag = child._tag; 1579 1580 //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check 1581 cc.Node.prototype.addChild.call(this, child, zOrder, tag); 1582 this._hasChildren = true; 1583 }, 1584 1585 /** 1586 * Update sprite's color 1587 */ 1588 updateColor:function () { 1589 var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity; 1590 var color4 = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: locDisplayedOpacity}; 1591 // special opacity for premultiplied textures 1592 if (this._opacityModifyRGB) { 1593 color4.r *= locDisplayedOpacity / 255.0; 1594 color4.g *= locDisplayedOpacity / 255.0; 1595 color4.b *= locDisplayedOpacity / 255.0; 1596 } 1597 var locQuad = this._quad; 1598 locQuad.bl.colors = color4; 1599 locQuad.br.colors = color4; 1600 locQuad.tl.colors = color4; 1601 locQuad.tr.colors = color4; 1602 1603 // renders using Sprite Manager 1604 if (this._batchNode) { 1605 if (this._atlasIndex != cc.SPRITE_INDEX_NOT_INITIALIZED) { 1606 this._textureAtlas.updateQuad(locQuad, this._atlasIndex) 1607 } else { 1608 // no need to set it recursively 1609 // update dirty_, don't update recursiveDirty_ 1610 //this.setDirty(true); 1611 this._dirty = true; 1612 } 1613 } 1614 // self render 1615 // do nothing 1616 this._quadDirty = true; 1617 }, 1618 1619 /** 1620 * opacity setter 1621 * @param {Number} opacity 1622 */ 1623 setOpacity:null, 1624 1625 _setOpacityForWebGL: function (opacity) { 1626 cc.NodeRGBA.prototype.setOpacity.call(this, opacity); 1627 this.updateColor(); 1628 }, 1629 1630 _setOpacityForCanvas: function (opacity) { 1631 cc.NodeRGBA.prototype.setOpacity.call(this, opacity); 1632 this._setNodeDirtyForCache(); 1633 }, 1634 1635 /** 1636 * color setter 1637 * @param {cc.Color3B} color3 1638 */ 1639 setColor: null, 1640 1641 _setColorForWebGL: function (color3) { 1642 cc.NodeRGBA.prototype.setColor.call(this, color3); 1643 this.updateColor(); 1644 }, 1645 1646 _setColorForCanvas: function (color3) { 1647 var curColor = this.getColor(); 1648 if ((curColor.r === color3.r) && (curColor.g === color3.g) && (curColor.b === color3.b)) 1649 return; 1650 1651 cc.NodeRGBA.prototype.setColor.call(this, color3); 1652 this._changeTextureColor(); 1653 this._setNodeDirtyForCache(); 1654 }, 1655 1656 updateDisplayedColor: null, 1657 1658 _updateDisplayedColorForWebGL: function (parentColor) { 1659 cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); 1660 this.updateColor(); 1661 }, 1662 1663 _updateDisplayedColorForCanvas: function (parentColor) { 1664 var oldColor = this.getColor(); 1665 cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); 1666 var newColor = this._displayedColor; 1667 if ((oldColor.r === newColor.r) && (oldColor.g === newColor.g) && (oldColor.b === newColor.b)) 1668 return; 1669 this._changeTextureColor(); 1670 this._setNodeDirtyForCache(); 1671 }, 1672 1673 // Frames 1674 /** 1675 * Sets a new display frame to the cc.Sprite. 1676 * @param {cc.SpriteFrame} newFrame 1677 */ 1678 setDisplayFrame: null, 1679 1680 _setDisplayFrameForWebGL: function (newFrame) { 1681 this.setNodeDirty(); 1682 var frameOffset = newFrame.getOffset(); 1683 this._unflippedOffsetPositionFromCenter._x = frameOffset.x; 1684 this._unflippedOffsetPositionFromCenter._y = frameOffset.y; 1685 1686 var pNewTexture = newFrame.getTexture(); 1687 var locTextureLoaded = newFrame.textureLoaded(); 1688 if (!locTextureLoaded) { 1689 this._textureLoaded = false; 1690 newFrame.addLoadedEventListener(function (sender) { 1691 this._textureLoaded = true; 1692 var locNewTexture = sender.getTexture(); 1693 if (locNewTexture != this._texture) 1694 this.setTexture(locNewTexture); 1695 this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); 1696 1697 this._callLoadedEventCallbacks(); 1698 }, this); 1699 } 1700 // update texture before updating texture rect 1701 if (pNewTexture != this._texture) 1702 this.setTexture(pNewTexture); 1703 1704 // update rect 1705 this._rectRotated = newFrame.isRotated(); 1706 this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); 1707 }, 1708 1709 _setDisplayFrameForCanvas: function (newFrame) { 1710 this.setNodeDirty(); 1711 1712 var frameOffset = newFrame.getOffset(); 1713 this._unflippedOffsetPositionFromCenter._x = frameOffset.x; 1714 this._unflippedOffsetPositionFromCenter._y = frameOffset.y; 1715 1716 // update rect 1717 this._rectRotated = newFrame.isRotated(); 1718 1719 var pNewTexture = newFrame.getTexture(); 1720 var locTextureLoaded = newFrame.textureLoaded(); 1721 if (!locTextureLoaded) { 1722 this._textureLoaded = false; 1723 newFrame.addLoadedEventListener(function (sender) { 1724 this._textureLoaded = true; 1725 var locNewTexture = sender.getTexture(); 1726 if (locNewTexture != this._texture) 1727 this.setTexture(locNewTexture); 1728 this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); 1729 this._callLoadedEventCallbacks(); 1730 }, this); 1731 } 1732 // update texture before updating texture rect 1733 if (pNewTexture != this._texture) 1734 this.setTexture(pNewTexture); 1735 1736 if (this._rectRotated) 1737 this._originalTexture = pNewTexture; 1738 1739 this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); 1740 this._colorized = false; 1741 if (locTextureLoaded) { 1742 var curColor = this.getColor(); 1743 if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) 1744 this._changeTextureColor(); 1745 } 1746 }, 1747 1748 /** 1749 * Returns whether or not a cc.SpriteFrame is being displayed 1750 * @param {cc.SpriteFrame} frame 1751 * @return {Boolean} 1752 */ 1753 isFrameDisplayed: null, 1754 1755 _isFrameDisplayedForWebGL: function (frame) { 1756 return (cc.rectEqualToRect(frame.getRect(), this._rect) && frame.getTexture().getName() == this._texture.getName() 1757 && cc.pointEqualToPoint(frame.getOffset(), this._unflippedOffsetPositionFromCenter)); 1758 }, 1759 1760 _isFrameDisplayedForCanvas: function (frame) { 1761 if (frame.getTexture() != this._texture) 1762 return false; 1763 return cc.rectEqualToRect(frame.getRect(), this._rect); 1764 }, 1765 1766 /** 1767 * Returns the current displayed frame. 1768 * @return {cc.SpriteFrame} 1769 */ 1770 displayFrame: function () { 1771 return cc.SpriteFrame.createWithTexture(this._texture, 1772 cc.RECT_POINTS_TO_PIXELS(this._rect), 1773 this._rectRotated, 1774 cc.POINT_POINTS_TO_PIXELS(this._unflippedOffsetPositionFromCenter), 1775 cc.SIZE_POINTS_TO_PIXELS(this._contentSize)); 1776 }, 1777 1778 /** 1779 * Sets the batch node to sprite 1780 * @param {cc.SpriteBatchNode|null} spriteBatchNode 1781 * @example 1782 * var batch = cc.SpriteBatchNode.create("Images/grossini_dance_atlas.png", 15); 1783 * var sprite = cc.Sprite.createWithTexture(batch.getTexture(), cc.rect(0, 0, 57, 57)); 1784 * batch.addChild(sprite); 1785 * layer.addChild(batch); 1786 */ 1787 setBatchNode:null, 1788 1789 _setBatchNodeForWebGL:function (spriteBatchNode) { 1790 this._batchNode = spriteBatchNode; // weak reference 1791 1792 // self render 1793 if (!this._batchNode) { 1794 this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; 1795 this.setTextureAtlas(null); 1796 this._recursiveDirty = false; 1797 this.setDirty(false); 1798 1799 var x1 = this._offsetPosition._x; 1800 var y1 = this._offsetPosition._y; 1801 var x2 = x1 + this._rect.width; 1802 var y2 = y1 + this._rect.height; 1803 var locQuad = this._quad; 1804 locQuad.bl.vertices = {x:x1, y:y1, z:0}; 1805 locQuad.br.vertices = {x:x2, y:y1, z:0}; 1806 locQuad.tl.vertices = {x:x1, y:y2, z:0}; 1807 locQuad.tr.vertices = {x:x2, y:y2, z:0}; 1808 1809 this._quadDirty = true; 1810 } else { 1811 // using batch 1812 this._transformToBatch = cc.AffineTransformIdentity(); 1813 this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref 1814 } 1815 }, 1816 1817 _setBatchNodeForCanvas:function (spriteBatchNode) { 1818 this._batchNode = spriteBatchNode; // weak reference 1819 1820 // self render 1821 if (!this._batchNode) { 1822 this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; 1823 this.setTextureAtlas(null); 1824 this._recursiveDirty = false; 1825 this.setDirty(false); 1826 } else { 1827 // using batch 1828 this._transformToBatch = cc.AffineTransformIdentity(); 1829 this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref 1830 } 1831 }, 1832 1833 // CCTextureProtocol 1834 /** 1835 * Texture of sprite setter 1836 * @param {cc.Texture2D} texture 1837 */ 1838 setTexture: null, 1839 1840 _setTextureForWebGL: function (texture) { 1841 // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet 1842 if(texture && !(texture instanceof cc.Texture2D)) 1843 throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; 1844 1845 // If batchnode, then texture id should be the same 1846 if(this._batchNode && this._batchNode.getTexture() != texture) { 1847 cc.log("cc.Sprite.setTexture(): Batched sprites should use the same texture as the batchnode"); 1848 return; 1849 } 1850 1851 if (texture) 1852 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); 1853 else 1854 this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); 1855 1856 if (!this._batchNode && this._texture != texture) { 1857 this._texture = texture; 1858 this._updateBlendFunc(); 1859 } 1860 }, 1861 1862 _setTextureForCanvas: function (texture) { 1863 // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet 1864 if(texture && !(texture instanceof cc.Texture2D)) 1865 throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; 1866 1867 if (this._texture != texture) { 1868 if (texture && texture.getHtmlElementObj() instanceof HTMLImageElement) { 1869 this._originalTexture = texture; 1870 } 1871 this._texture = texture; 1872 } 1873 }, 1874 1875 // Texture protocol 1876 _updateBlendFunc:function () { 1877 if(this._batchNode){ 1878 cc.log("cc.Sprite._updateBlendFunc(): _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode"); 1879 return; 1880 } 1881 1882 // it's possible to have an untextured sprite 1883 if (!this._texture || !this._texture.hasPremultipliedAlpha()) { 1884 this._blendFunc.src = gl.SRC_ALPHA; 1885 this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; 1886 this.setOpacityModifyRGB(false); 1887 } else { 1888 this._blendFunc.src = cc.BLEND_SRC; 1889 this._blendFunc.dst = cc.BLEND_DST; 1890 this.setOpacityModifyRGB(true); 1891 } 1892 }, 1893 1894 _changeTextureColor: function () { 1895 var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect(); 1896 if (locTexture && locRect.validRect && this._originalTexture) { 1897 locElement = locTexture.getHtmlElementObj(); 1898 if (!locElement) 1899 return; 1900 1901 var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj()); 1902 if (cacheTextureForColor) { 1903 this._colorized = true; 1904 //generate color texture cache 1905 if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor) 1906 cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement); 1907 else { 1908 locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect); 1909 locTexture = new cc.Texture2D(); 1910 locTexture.initWithElement(locElement); 1911 locTexture.handleLoadedTexture(); 1912 this.setTexture(locTexture); 1913 } 1914 } 1915 } 1916 }, 1917 1918 _setTextureCoords:function (rect) { 1919 rect = cc.RECT_POINTS_TO_PIXELS(rect); 1920 1921 var tex = this._batchNode ? this._textureAtlas.getTexture() : this._texture; 1922 if (!tex) 1923 return; 1924 1925 var atlasWidth = tex.getPixelsWide(); 1926 var atlasHeight = tex.getPixelsHigh(); 1927 1928 var left, right, top, bottom, tempSwap, locQuad = this._quad; 1929 if (this._rectRotated) { 1930 if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { 1931 left = (2 * rect.x + 1) / (2 * atlasWidth); 1932 right = left + (rect.height * 2 - 2) / (2 * atlasWidth); 1933 top = (2 * rect.y + 1) / (2 * atlasHeight); 1934 bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight); 1935 } else { 1936 left = rect.x / atlasWidth; 1937 right = (rect.x + rect.height) / atlasWidth; 1938 top = rect.y / atlasHeight; 1939 bottom = (rect.y + rect.width) / atlasHeight; 1940 }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1941 1942 if (this._flippedX) { 1943 tempSwap = top; 1944 top = bottom; 1945 bottom = tempSwap; 1946 } 1947 1948 if (this._flippedY) { 1949 tempSwap = left; 1950 left = right; 1951 right = tempSwap; 1952 } 1953 1954 locQuad.bl.texCoords.u = left; 1955 locQuad.bl.texCoords.v = top; 1956 locQuad.br.texCoords.u = left; 1957 locQuad.br.texCoords.v = bottom; 1958 locQuad.tl.texCoords.u = right; 1959 locQuad.tl.texCoords.v = top; 1960 locQuad.tr.texCoords.u = right; 1961 locQuad.tr.texCoords.v = bottom; 1962 } else { 1963 if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { 1964 left = (2 * rect.x + 1) / (2 * atlasWidth); 1965 right = left + (rect.width * 2 - 2) / (2 * atlasWidth); 1966 top = (2 * rect.y + 1) / (2 * atlasHeight); 1967 bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight); 1968 } else { 1969 left = rect.x / atlasWidth; 1970 right = (rect.x + rect.width) / atlasWidth; 1971 top = rect.y / atlasHeight; 1972 bottom = (rect.y + rect.height) / atlasHeight; 1973 } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1974 1975 if (this._flippedX) { 1976 tempSwap = left; 1977 left = right; 1978 right = tempSwap; 1979 } 1980 1981 if (this._flippedY) { 1982 tempSwap = top; 1983 top = bottom; 1984 bottom = tempSwap; 1985 } 1986 1987 locQuad.bl.texCoords.u = left; 1988 locQuad.bl.texCoords.v = bottom; 1989 locQuad.br.texCoords.u = right; 1990 locQuad.br.texCoords.v = bottom; 1991 locQuad.tl.texCoords.u = left; 1992 locQuad.tl.texCoords.v = top; 1993 locQuad.tr.texCoords.u = right; 1994 locQuad.tr.texCoords.v = top; 1995 } 1996 this._quadDirty = true; 1997 }, 1998 /** 1999 * draw sprite to canvas 2000 */ 2001 draw: null, 2002 2003 _drawForWebGL: function () { 2004 if (!this._textureLoaded) 2005 return; 2006 2007 var gl = cc.renderContext, locTexture = this._texture; 2008 //cc.Assert(!this._batchNode, "If cc.Sprite is being rendered by cc.SpriteBatchNode, cc.Sprite#draw SHOULD NOT be called"); 2009 2010 if (locTexture) { 2011 if (locTexture._isLoaded) { 2012 this._shaderProgram.use(); 2013 this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); 2014 2015 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 2016 //optimize performance for javascript 2017 cc.glBindTexture2DN(0, locTexture); // = cc.glBindTexture2D(locTexture); 2018 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX); 2019 2020 gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); 2021 if (this._quadDirty) { 2022 gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.DYNAMIC_DRAW); 2023 this._quadDirty = false; 2024 } 2025 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0); //cc.VERTEX_ATTRIB_POSITION 2026 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 24, 12); //cc.VERTEX_ATTRIB_COLOR 2027 gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 24, 16); //cc.VERTEX_ATTRIB_TEX_COORDS 2028 2029 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 2030 } 2031 } else { 2032 this._shaderProgram.use(); 2033 this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); 2034 2035 cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); 2036 cc.glBindTexture2D(null); 2037 2038 cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR); 2039 2040 gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); 2041 if (this._quadDirty) { 2042 cc.renderContext.bufferData(cc.renderContext.ARRAY_BUFFER, this._quad.arrayBuffer, cc.renderContext.STATIC_DRAW); 2043 this._quadDirty = false; 2044 } 2045 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); 2046 gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); 2047 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 2048 } 2049 cc.g_NumberOfDraws++; 2050 if (cc.SPRITE_DEBUG_DRAW === 0) 2051 return; 2052 2053 if (cc.SPRITE_DEBUG_DRAW === 1) { 2054 // draw bounding box 2055 var locQuad = this._quad; 2056 var verticesG1 = [ 2057 cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y), 2058 cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y), 2059 cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y), 2060 cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y) 2061 ]; 2062 cc.drawingUtil.drawPoly(verticesG1, 4, true); 2063 } else if (cc.SPRITE_DEBUG_DRAW === 2) { 2064 // draw texture box 2065 var drawSizeG2 = this.getTextureRect()._size; 2066 var offsetPixG2 = this.getOffsetPosition(); 2067 var verticesG2 = [cc.p(offsetPixG2.x, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y), 2068 cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y + drawSizeG2.height), cc.p(offsetPixG2.x, offsetPixG2.y + drawSizeG2.height)]; 2069 cc.drawingUtil.drawPoly(verticesG2, 4, true); 2070 } // CC_SPRITE_DEBUG_DRAW 2071 }, 2072 2073 _drawForCanvas: function (ctx) { 2074 if (!this._textureLoaded) 2075 return; 2076 2077 var context = ctx || cc.renderContext; 2078 if (this._isLighterMode) 2079 context.globalCompositeOperation = 'lighter'; 2080 2081 var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY(); 2082 2083 context.globalAlpha = this._displayedOpacity / 255; 2084 var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition, locDrawSizeCanvas = this._drawSize_Canvas; 2085 var flipXOffset = 0 | (locOffsetPosition._x), flipYOffset = -locOffsetPosition._y - locRect.height, locTextureCoord = this._textureRect_Canvas; 2086 locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX; 2087 locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY; 2088 2089 if (this._flippedX || this._flippedY) { 2090 context.save(); 2091 if (this._flippedX) { 2092 flipXOffset = -locOffsetPosition._x - locRect.width; 2093 context.scale(-1, 1); 2094 } 2095 if (this._flippedY) { 2096 flipYOffset = locOffsetPosition._y; 2097 context.scale(1, -1); 2098 } 2099 } 2100 2101 flipXOffset *= locEGL_ScaleX; 2102 flipYOffset *= locEGL_ScaleY; 2103 2104 if (this._texture && locTextureCoord.validRect) { 2105 var image = this._texture.getHtmlElementObj(); 2106 if (this._colorized) { 2107 context.drawImage(image, 2108 0, 0, locTextureCoord.width, locTextureCoord.height, 2109 flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height); 2110 } else { 2111 context.drawImage(image, 2112 locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height, 2113 flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height); 2114 } 2115 } else if (locContentSize._width !== 0) { 2116 var curColor = this.getColor(); 2117 context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)"; 2118 context.fillRect(flipXOffset, flipYOffset, locContentSize._width * locEGL_ScaleX, locContentSize._height * locEGL_ScaleY); 2119 } 2120 2121 if (cc.SPRITE_DEBUG_DRAW === 1) { 2122 // draw bounding box 2123 context.strokeStyle = "rgba(0,255,0,1)"; 2124 flipXOffset /= locEGL_ScaleX; 2125 flipYOffset /= locEGL_ScaleY; 2126 flipYOffset = -flipYOffset; 2127 var vertices1 = [cc.p(flipXOffset, flipYOffset), 2128 cc.p(flipXOffset + locRect.width, flipYOffset), 2129 cc.p(flipXOffset + locRect.width, flipYOffset - locRect.height), 2130 cc.p(flipXOffset, flipYOffset - locRect.height)]; 2131 cc.drawingUtil.drawPoly(vertices1, 4, true); 2132 } else if (cc.SPRITE_DEBUG_DRAW === 2) { 2133 // draw texture box 2134 context.strokeStyle = "rgba(0,255,0,1)"; 2135 var drawSize = this._rect._size; 2136 flipYOffset = -flipYOffset; 2137 var vertices2 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + drawSize.width, flipYOffset), 2138 cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; 2139 cc.drawingUtil.drawPoly(vertices2, 4, true); 2140 } 2141 if (this._flippedX || this._flippedY) 2142 context.restore(); 2143 cc.g_NumberOfDraws++; 2144 } 2145 }); 2146 2147 if(cc.Browser.supportWebGL){ 2148 cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForWebGL; 2149 cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForWebGL; 2150 cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForWebGL; 2151 cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForWebGL; 2152 cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForWebGL; 2153 cc.Sprite.prototype.init = cc.Sprite.prototype._initForWebGL; 2154 cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForWebGL; 2155 cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForWebGL; 2156 cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL; 2157 cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForWebGL; 2158 cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForWebGL; 2159 cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForWebGL; 2160 cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForWebGL; 2161 cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForWebGL; 2162 cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForWebGL; 2163 cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForWebGL; 2164 cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForWebGL; 2165 cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForWebGL; 2166 cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForWebGL; 2167 }else{ 2168 cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForCanvas; 2169 cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForCanvas; 2170 cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForCanvas; 2171 cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForCanvas; 2172 cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForCanvas; 2173 cc.Sprite.prototype.init = cc.Sprite.prototype._initForCanvas; 2174 cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForCanvas; 2175 cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForCanvas; 2176 cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForCanvas; 2177 cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForCanvas; 2178 cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForCanvas; 2179 cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForCanvas; 2180 cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForCanvas; 2181 cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForCanvas; 2182 cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForCanvas; 2183 cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForCanvas; 2184 cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas; 2185 cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas; 2186 cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas; 2187 } 2188 2189 /** 2190 * <p> 2191 * Creates a sprite with an exsiting texture contained in a CCTexture2D object <br/> 2192 * After creation, the rect will be the size of the texture, and the offset will be (0,0). 2193 * </p> 2194 * @constructs 2195 * @param {cc.Texture2D} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. 2196 * @param {cc.Rect} rect Only the contents inside the rect of this texture will be applied for this sprite. 2197 * @return {cc.Sprite} A valid sprite object 2198 * @example 2199 * //get an image 2200 * var img = cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); 2201 * 2202 * //create a sprite with texture 2203 * var sprite1 = cc.Sprite.createWithTexture(img); 2204 * 2205 * //create a sprite with texture and rect 2206 * var sprite2 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320)); 2207 * 2208 */ 2209 cc.Sprite.createWithTexture = function (texture, rect) { 2210 var argnum = arguments.length; 2211 var sprite = new cc.Sprite(); 2212 switch (argnum) { 2213 case 1: 2214 /** Creates an sprite with a texture. 2215 The rect used will be the size of the texture. 2216 The offset will be (0,0). 2217 */ 2218 if (sprite && sprite.initWithTexture(texture)) 2219 return sprite; 2220 return null; 2221 break; 2222 2223 case 2: 2224 /** Creates an sprite with a texture and a rect. 2225 The offset will be (0,0). 2226 */ 2227 if (sprite && sprite.initWithTexture(texture, rect)) 2228 return sprite; 2229 return null; 2230 break; 2231 2232 default: 2233 throw "Sprite.createWithTexture(): Argument must be non-nil "; 2234 break; 2235 } 2236 }; 2237 2238 /** 2239 * Create a sprite with filename and rect 2240 * @constructs 2241 * @param {String} fileName The string which indicates a path to image file, e.g., "scene1/monster.png". 2242 * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite. 2243 * @return {cc.Sprite} A valid sprite object 2244 * @example 2245 * //create a sprite with filename 2246 * var sprite1 = cc.Sprite.create("HelloHTML5World.png"); 2247 * 2248 * //create a sprite with filename and rect 2249 * var sprite2 = cc.Sprite.create("HelloHTML5World.png",cc.rect(0,0,480,320)); 2250 */ 2251 cc.Sprite.create = function (fileName, rect) { 2252 var argnum = arguments.length; 2253 var sprite = new cc.Sprite(); 2254 if (argnum === 0) { 2255 if (sprite.init()) 2256 return sprite; 2257 } else { 2258 /** Creates an sprite with an image filename. 2259 If the rect equal undefined, the rect used will be the size of the image. 2260 The offset will be (0,0). 2261 */ 2262 if (sprite && sprite.init(fileName, rect)) 2263 return sprite; 2264 } 2265 return null; 2266 }; 2267 2268 /** 2269 * <p> 2270 * Creates a sprite with a sprite frame. <br/> 2271 * <br/> 2272 * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param. <br/> 2273 * If the CCSpriteFrame doesn't exist it will raise an exception. 2274 * </p> 2275 * @param {String} spriteFrameName A sprite frame which involves a texture and a rect 2276 * @return {cc.Sprite} A valid sprite object 2277 * @example 2278 * 2279 * //create a sprite with a sprite frame 2280 * var sprite = cc.Sprite.createWithSpriteFrameName('grossini_dance_01.png'); 2281 */ 2282 cc.Sprite.createWithSpriteFrameName = function (spriteFrameName) { 2283 var spriteFrame = null; 2284 if (typeof(spriteFrameName) == 'string') { 2285 spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); 2286 if (!spriteFrame) { 2287 cc.log("Invalid spriteFrameName: " + spriteFrameName); 2288 return null; 2289 } 2290 } else { 2291 cc.log("Invalid argument. Expecting string."); 2292 return null; 2293 } 2294 var sprite = new cc.Sprite(); 2295 if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { 2296 return sprite; 2297 } 2298 return null; 2299 }; 2300 2301 /** 2302 * <p> 2303 * Creates a sprite with a sprite frame. <br/> 2304 * <br/> 2305 * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param. <br/> 2306 * If the CCSpriteFrame doesn't exist it will raise an exception. 2307 * </p> 2308 * @param {cc.SpriteFrame} spriteFrame A sprite frame which involves a texture and a rect 2309 * @return {cc.Sprite} A valid sprite object 2310 * @example 2311 * //get a sprite frame 2312 * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png"); 2313 * 2314 * //create a sprite with a sprite frame 2315 * var sprite = cc.Sprite.createWithSpriteFrame(spriteFrame); 2316 */ 2317 cc.Sprite.createWithSpriteFrame = function (spriteFrame) { 2318 var sprite = new cc.Sprite(); 2319 if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { 2320 return sprite; 2321 } 2322 return null; 2323 }; 2324