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