1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p> 29 * A cc.SpriteFrame has:<br/> 30 * - texture: A cc.Texture2D that will be used by the cc.Sprite<br/> 31 * - rectangle: A rectangle of the texture<br/> 32 * <br/> 33 * You can modify the frame of a cc.Sprite by doing:<br/> 34 * </p> 35 * @class 36 * @extends cc.Class 37 * 38 * @param {String|cc.Texture2D} filename 39 * @param {cc.Rect} rect If parameters' length equal 2, rect in points, else rect in pixels 40 * @param {Boolean} [rotated] Whether the frame is rotated in the texture 41 * @param {cc.Point} [offset] The offset of the frame in the texture 42 * @param {cc.Size} [originalSize] The size of the frame in the texture 43 * 44 * @example 45 * // 1. Create a cc.SpriteFrame with image path 46 * var frame1 = new cc.SpriteFrame("res/grossini_dance.png",cc.rect(0,0,90,128)); 47 * var frame2 = new cc.SpriteFrame("res/grossini_dance.png",cc.rect(0,0,90,128),false,0,cc.size(90,128)); 48 * 49 * // 2. Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. 50 * var texture = cc.textureCache.addImage("res/grossini_dance.png"); 51 * var frame1 = new cc.SpriteFrame(texture, cc.rect(0,0,90,128)); 52 * var frame2 = new cc.SpriteFrame(texture, cc.rect(0,0,90,128),false,0,cc.size(90,128)); 53 */ 54 cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ 55 _offset:null, 56 _originalSize:null, 57 _rectInPixels:null, 58 _rotated:false, 59 _rect:null, 60 _offsetInPixels:null, 61 _originalSizeInPixels:null, 62 _texture:null, 63 _textureFilename:"", 64 _textureLoaded:false, 65 66 ctor:function (filename, rect, rotated, offset, originalSize) { 67 this._offset = cc.p(0, 0); 68 this._offsetInPixels = cc.p(0, 0); 69 this._originalSize = cc.size(0, 0); 70 this._rotated = false; 71 this._originalSizeInPixels = cc.size(0, 0); 72 this._textureFilename = ""; 73 this._texture = null; 74 this._textureLoaded = false; 75 76 if(filename !== undefined && rect !== undefined ){ 77 if(rotated === undefined || offset === undefined || originalSize === undefined) 78 this.initWithTexture(filename, rect); 79 else 80 this.initWithTexture(filename, rect, rotated, offset, originalSize) 81 } 82 }, 83 84 /** 85 * Returns whether the texture have been loaded 86 * @returns {boolean} 87 */ 88 textureLoaded:function(){ 89 return this._textureLoaded; 90 }, 91 92 /** 93 * Add a event listener for texture loaded event. 94 * @param {Function} callback 95 * @param {Object} target 96 * @deprecated since 3.1, please use addEventListener instead 97 */ 98 addLoadedEventListener:function(callback, target){ 99 this.addEventListener("load", callback, target); 100 }, 101 102 /** 103 * Gets the rect of the frame in the texture 104 * @return {cc.Rect} 105 */ 106 getRectInPixels:function () { 107 var locRectInPixels = this._rectInPixels; 108 return cc.rect(locRectInPixels.x, locRectInPixels.y, locRectInPixels.width, locRectInPixels.height); 109 }, 110 111 /** 112 * Sets the rect of the frame in the texture 113 * @param {cc.Rect} rectInPixels 114 */ 115 setRectInPixels:function (rectInPixels) { 116 if (!this._rectInPixels){ 117 this._rectInPixels = cc.rect(0,0,0,0); 118 } 119 this._rectInPixels.x = rectInPixels.x; 120 this._rectInPixels.y = rectInPixels.y; 121 this._rectInPixels.width = rectInPixels.width; 122 this._rectInPixels.height = rectInPixels.height; 123 this._rect = cc.rectPixelsToPoints(rectInPixels); 124 }, 125 126 /** 127 * Returns whether the sprite frame is rotated in the texture. 128 * @return {Boolean} 129 */ 130 isRotated:function () { 131 return this._rotated; 132 }, 133 134 /** 135 * Set whether the sprite frame is rotated in the texture. 136 * @param {Boolean} bRotated 137 */ 138 setRotated:function (bRotated) { 139 this._rotated = bRotated; 140 }, 141 142 /** 143 * Returns the rect of the sprite frame in the texture 144 * @return {cc.Rect} 145 */ 146 getRect:function () { 147 var locRect = this._rect; 148 return cc.rect(locRect.x, locRect.y, locRect.width, locRect.height); 149 }, 150 151 /** 152 * Sets the rect of the sprite frame in the texture 153 * @param {cc.Rect} rect 154 */ 155 setRect:function (rect) { 156 if (!this._rect){ 157 this._rect = cc.rect(0,0,0,0); 158 } 159 this._rect.x = rect.x; 160 this._rect.y = rect.y; 161 this._rect.width = rect.width; 162 this._rect.height = rect.height; 163 this._rectInPixels = cc.rectPointsToPixels(this._rect); 164 }, 165 166 /** 167 * Returns the offset of the sprite frame in the texture in pixel 168 * @return {cc.Point} 169 */ 170 getOffsetInPixels:function () { 171 return cc.p(this._offsetInPixels); 172 }, 173 174 /** 175 * Sets the offset of the sprite frame in the texture in pixel 176 * @param {cc.Point} offsetInPixels 177 */ 178 setOffsetInPixels:function (offsetInPixels) { 179 this._offsetInPixels.x = offsetInPixels.x; 180 this._offsetInPixels.y = offsetInPixels.y; 181 cc._pointPixelsToPointsOut(this._offsetInPixels, this._offset); 182 }, 183 184 /** 185 * Returns the original size of the trimmed image 186 * @return {cc.Size} 187 */ 188 getOriginalSizeInPixels:function () { 189 return cc.size(this._originalSizeInPixels); 190 }, 191 192 /** 193 * Sets the original size of the trimmed image 194 * @param {cc.Size} sizeInPixels 195 */ 196 setOriginalSizeInPixels:function (sizeInPixels) { 197 this._originalSizeInPixels.width = sizeInPixels.width; 198 this._originalSizeInPixels.height = sizeInPixels.height; 199 }, 200 201 /** 202 * Returns the original size of the trimmed image 203 * @return {cc.Size} 204 */ 205 getOriginalSize:function () { 206 return cc.size(this._originalSize); 207 }, 208 209 /** 210 * Sets the original size of the trimmed image 211 * @param {cc.Size} sizeInPixels 212 */ 213 setOriginalSize:function (sizeInPixels) { 214 this._originalSize.width = sizeInPixels.width; 215 this._originalSize.height = sizeInPixels.height; 216 }, 217 218 /** 219 * Returns the texture of the frame 220 * @return {cc.Texture2D} 221 */ 222 getTexture:function () { 223 if (this._texture) 224 return this._texture; 225 if (this._textureFilename !== "") { 226 var locTexture = cc.textureCache.addImage(this._textureFilename); 227 if (locTexture) 228 this._textureLoaded = locTexture.isLoaded(); 229 return locTexture; 230 } 231 return null; 232 }, 233 234 /** 235 * Sets the texture of the frame, the texture is retained automatically 236 * @param {cc.Texture2D} texture 237 */ 238 setTexture:function (texture) { 239 if (this._texture !== texture) { 240 var locLoaded = texture.isLoaded(); 241 this._textureLoaded = locLoaded; 242 this._texture = texture; 243 if(!locLoaded){ 244 texture.addEventListener("load", function(sender){ 245 this._textureLoaded = true; 246 if(this._rotated && cc._renderType === cc.game.RENDER_TYPE_CANVAS){ 247 var tempElement = sender.getHtmlElementObj(); 248 tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, this.getRect()); 249 var tempTexture = new cc.Texture2D(); 250 tempTexture.initWithElement(tempElement); 251 tempTexture.handleLoadedTexture(); 252 this.setTexture(tempTexture); 253 254 var rect = this.getRect(); 255 this.setRect(cc.rect(0, 0, rect.width, rect.height)); 256 } 257 var locRect = this._rect; 258 if(locRect.width === 0 && locRect.height === 0){ 259 var w = sender.width, h = sender.height; 260 this._rect.width = w; 261 this._rect.height = h; 262 this._rectInPixels = cc.rectPointsToPixels(this._rect); 263 this._originalSizeInPixels.width = this._rectInPixels.width; 264 this._originalSizeInPixels.height = this._rectInPixels.height; 265 this._originalSize.width = w; 266 this._originalSize.height = h; 267 } 268 //dispatch 'load' event of cc.SpriteFrame 269 this.dispatchEvent("load"); 270 }, this); 271 } 272 } 273 }, 274 275 /** 276 * Returns the offset of the frame in the texture 277 * @return {cc.Point} 278 */ 279 getOffset:function () { 280 return cc.p(this._offset); 281 }, 282 283 /** 284 * Sets the offset of the frame in the texture 285 * @param {cc.Point} offsets 286 */ 287 setOffset:function (offsets) { 288 this._offset.x = offsets.x; 289 this._offset.y = offsets.y; 290 }, 291 292 /** 293 * Clone the sprite frame 294 * @returns {SpriteFrame} 295 */ 296 clone: function(){ 297 var frame = new cc.SpriteFrame(); 298 frame.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels); 299 frame.setTexture(this._texture); 300 return frame; 301 }, 302 303 /** 304 * Copy the sprite frame 305 * @return {cc.SpriteFrame} 306 */ 307 copyWithZone:function () { 308 var copy = new cc.SpriteFrame(); 309 copy.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels); 310 copy.setTexture(this._texture); 311 return copy; 312 }, 313 314 /** 315 * Copy the sprite frame 316 * @returns {cc.SpriteFrame} 317 */ 318 copy:function () { 319 return this.copyWithZone(); 320 }, 321 322 /** 323 * Initializes SpriteFrame with Texture, rect, rotated, offset and originalSize in pixels.<br/> 324 * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself. 325 * @param {String|cc.Texture2D} texture 326 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 327 * @param {Boolean} [rotated=false] 328 * @param {cc.Point} [offset=cc.p(0,0)] 329 * @param {cc.Size} [originalSize=rect.size] 330 * @return {Boolean} 331 */ 332 initWithTexture:function (texture, rect, rotated, offset, originalSize) { 333 if(arguments.length === 2) 334 rect = cc.rectPointsToPixels(rect); 335 336 offset = offset || cc.p(0, 0); 337 originalSize = originalSize || rect; 338 rotated = rotated || false; 339 340 if (cc.isString(texture)){ 341 this._texture = null; 342 this._textureFilename = texture; 343 } else if (texture instanceof cc.Texture2D){ 344 this.setTexture(texture); 345 } 346 347 texture = this.getTexture(); 348 349 this._rectInPixels = rect; 350 rect = this._rect = cc.rectPixelsToPoints(rect); 351 352 if(texture && texture.url && texture.isLoaded()) { 353 var _x, _y; 354 if(rotated){ 355 _x = rect.x + rect.height; 356 _y = rect.y + rect.width; 357 }else{ 358 _x = rect.x + rect.width; 359 _y = rect.y + rect.height; 360 } 361 if(_x > texture.getPixelsWide()){ 362 cc.error(cc._LogInfos.RectWidth, texture.url); 363 } 364 if(_y > texture.getPixelsHigh()){ 365 cc.error(cc._LogInfos.RectHeight, texture.url); 366 } 367 } 368 369 this._offsetInPixels.x = offset.x; 370 this._offsetInPixels.y = offset.y; 371 cc._pointPixelsToPointsOut(offset, this._offset); 372 this._originalSizeInPixels.width = originalSize.width; 373 this._originalSizeInPixels.height = originalSize.height; 374 cc._sizePixelsToPointsOut(originalSize, this._originalSize); 375 this._rotated = rotated; 376 return true; 377 } 378 }); 379 380 cc.EventHelper.prototype.apply(cc.SpriteFrame.prototype); 381 382 /** 383 * <p> 384 * Create a cc.SpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels.<br/> 385 * The originalSize is the size in pixels of the frame before being trimmed. 386 * </p> 387 * @deprecated since v3.0, please use new construction instead 388 * @see cc.SpriteFrame 389 * @param {String|cc.Texture2D} filename 390 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 391 * @param {Boolean} rotated 392 * @param {cc.Point} offset 393 * @param {cc.Size} originalSize 394 * @return {cc.SpriteFrame} 395 */ 396 cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) { 397 return new cc.SpriteFrame(filename,rect,rotated,offset,originalSize); 398 }; 399 400 /** 401 * @deprecated since v3.0, please use new construction instead 402 * @see cc.SpriteFrame 403 * @function 404 */ 405 cc.SpriteFrame.createWithTexture = cc.SpriteFrame.create; 406 407 cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) { 408 var spriteFrame = new cc.SpriteFrame(); 409 spriteFrame._texture = texture; 410 spriteFrame._rectInPixels = rect; 411 spriteFrame._rect = cc.rectPixelsToPoints(rect); 412 spriteFrame._offsetInPixels.x = offset.x; 413 spriteFrame._offsetInPixels.y = offset.y; 414 cc._pointPixelsToPointsOut(spriteFrame._offsetInPixels, spriteFrame._offset); 415 spriteFrame._originalSizeInPixels.width = originalSize.width; 416 spriteFrame._originalSizeInPixels.height = originalSize.height; 417 cc._sizePixelsToPointsOut(spriteFrame._originalSizeInPixels, spriteFrame._originalSize); 418 spriteFrame._rotated = rotated; 419 return spriteFrame; 420 }; 421