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 * <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 * @example 39 * var texture = cc.TextureCache.getInstance().addImage(s_dragon_animation); 40 * var frame0 = cc.SpriteFrame.createWithTexture(texture, cc.rect(132 * 0, 132 * 0, 132, 132)); 41 */ 42 cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ 43 _offset:null, 44 _originalSize:null, 45 _rectInPixels:null, 46 _rotated:false, 47 _rect:null, 48 _offsetInPixels:null, 49 _originalSizeInPixels:null, 50 _texture:null, 51 _textureFilename:"", 52 _textureLoaded:false, 53 _eventListeners:null, 54 55 ctor:function () { 56 this._offset = cc._pConst(0, 0); 57 this._offsetInPixels = cc._pConst(0, 0); 58 this._originalSize = cc._sizeConst(0, 0); 59 this._rotated = false; 60 this._originalSizeInPixels = cc._sizeConst(0, 0); 61 this._textureFilename = ""; 62 this._texture = null; 63 this._textureLoaded = false; 64 }, 65 66 // attributes 67 textureLoaded:function(){ 68 return this._textureLoaded; 69 }, 70 71 addLoadedEventListener:function(callback, target){ 72 if (this._eventListeners == null){ 73 this._eventListeners = []; 74 } 75 this._eventListeners.push({eventCallback:callback, eventTarget:target}); 76 }, 77 78 _callLoadedEventCallbacks:function(){ 79 var locListeners = this._eventListeners; 80 if (!locListeners) return; 81 for(var i = 0, len = locListeners.length; i < len; i++){ 82 var selCallback = locListeners[i]; 83 selCallback.eventCallback.call(selCallback.eventTarget, this); 84 } 85 locListeners.length = 0; 86 }, 87 88 /** 89 * @return {cc.Rect} 90 */ 91 getRectInPixels:function () { 92 var locRectInPixels = this._rectInPixels; 93 return cc.rect(locRectInPixels.x, locRectInPixels.y, locRectInPixels.width, locRectInPixels.height); 94 }, 95 96 /** 97 * @param {cc.Rect} rectInPixels 98 */ 99 setRectInPixels:function (rectInPixels) { 100 if (!this._rectInPixels){ 101 this._rectInPixels = cc.rect(0,0,0,0); 102 } 103 this._rectInPixels.x = rectInPixels.x; 104 this._rectInPixels.y = rectInPixels.y; 105 this._rectInPixels.width = rectInPixels.width; 106 this._rectInPixels.height = rectInPixels.height; 107 this._rect = cc.RECT_PIXELS_TO_POINTS(rectInPixels); 108 }, 109 110 /** 111 * <p> 112 * return is rotated of SpriteFrame. <br/> 113 * </p> 114 * @return {Boolean} 115 */ 116 isRotated:function () { 117 return this._rotated; 118 }, 119 120 /** 121 * set SpriteFrame is rotated 122 * @param {Boolean} bRotated 123 */ 124 setRotated:function (bRotated) { 125 this._rotated = bRotated; 126 }, 127 128 /** 129 * get rect of the frame 130 * @return {cc.Rect} 131 */ 132 getRect:function () { 133 var locRect = this._rect; 134 return cc.rect(locRect.x, locRect.y, locRect.width, locRect.height); 135 }, 136 137 /** 138 * set rect of the frame 139 * @param {cc.Rect} rect 140 */ 141 setRect:function (rect) { 142 if (!this._rect){ 143 this._rect = cc.rect(0,0,0,0); 144 } 145 this._rect.x = rect.x; 146 this._rect.y = rect.y; 147 this._rect.width = rect.width; 148 this._rect.height = rect.height; 149 this._rectInPixels = cc.RECT_POINTS_TO_PIXELS(this._rect); 150 }, 151 152 /** 153 * get offset of the frame 154 * @return {cc.Point} 155 */ 156 getOffsetInPixels:function () { 157 return this._offsetInPixels; 158 }, 159 160 /** 161 * set offset of the frame 162 * @param {cc.Point} offsetInPixels 163 */ 164 setOffsetInPixels:function (offsetInPixels) { 165 this._offsetInPixels._x = offsetInPixels.x; 166 this._offsetInPixels._y = offsetInPixels.y; 167 cc._POINT_PIXELS_TO_POINTS_OUT(this._offsetInPixels, this._offset); 168 }, 169 170 /** 171 * get original size of the trimmed image 172 * @const 173 * @return {cc.Size} 174 */ 175 getOriginalSizeInPixels:function () { 176 return this._originalSizeInPixels; 177 }, 178 179 /** 180 * set original size of the trimmed image 181 * @param {cc.Size} sizeInPixels 182 */ 183 setOriginalSizeInPixels:function (sizeInPixels) { 184 this._originalSizeInPixels._width = sizeInPixels.width; 185 this._originalSizeInPixels._height = sizeInPixels.height; 186 }, 187 188 /** 189 * get original size of the trimmed image 190 * @const 191 * @return {cc.Size} 192 */ 193 getOriginalSize:function () { 194 return this._originalSize; 195 }, 196 197 /** 198 * set original size of the trimmed image 199 * @param {cc.Size} sizeInPixels 200 */ 201 setOriginalSize:function (sizeInPixels) { 202 this._originalSize._width = sizeInPixels.width; 203 this._originalSize._height = sizeInPixels.height; 204 }, 205 206 /** 207 * get texture of the frame 208 * @return {cc.Texture2D} 209 */ 210 getTexture:function () { 211 if (this._texture) 212 return this._texture; 213 if (this._textureFilename !== "") { 214 var locTexture = cc.TextureCache.getInstance().addImage(this._textureFilename); 215 if (locTexture) 216 this._textureLoaded = locTexture.isLoaded(); 217 return locTexture; 218 } 219 return null; 220 }, 221 222 /** 223 * set texture of the frame, the texture is retained 224 * @param {cc.Texture2D} texture 225 */ 226 setTexture:function (texture) { 227 if (this._texture != texture) { 228 var locLoaded = texture.isLoaded(); 229 this._textureLoaded = locLoaded; 230 this._texture = texture; 231 if(!locLoaded){ 232 texture.addLoadedEventListener(function(sender){ 233 this._textureLoaded = true; 234 if(this._rotated && cc.renderContextType === cc.CANVAS){ 235 var tempElement = sender.getHtmlElementObj(); 236 tempElement = cc.cutRotateImageToCanvas(tempElement, this.getRect()); 237 var tempTexture = new cc.Texture2D(); 238 tempTexture.initWithElement(tempElement); 239 tempTexture.handleLoadedTexture(); 240 this.setTexture(tempTexture); 241 242 var rect = this.getRect(); 243 this.setRect(cc.rect(0, 0, rect.width, rect.height)); 244 } 245 var locRect = this._rect; 246 if(locRect.width === 0 && locRect.height === 0){ 247 var locContentSize = sender.getContentSize(); 248 this._rect.width = locContentSize.width; 249 this._rect.height = locContentSize.height; 250 this._rectInPixels = cc.RECT_POINTS_TO_PIXELS(this._rect); 251 this._originalSizeInPixels._width = this._rectInPixels.width; 252 this._originalSizeInPixels._height = this._rectInPixels.height; 253 this._originalSize._width = locContentSize.width; 254 this._originalSize._height = locContentSize.height; 255 } 256 this._callLoadedEventCallbacks(); 257 }, this); 258 } 259 } 260 }, 261 262 /** 263 * Offset getter 264 * @const 265 * @return {cc.Point} 266 */ 267 getOffset:function () { 268 return this._offset; 269 }, 270 271 /** 272 * offset setter 273 * @param {cc.Point} offsets 274 */ 275 setOffset:function (offsets) { 276 this._offset._x = offsets.x; 277 this._offset._y = offsets.y; 278 }, 279 280 clone: function(){ 281 var frame = new cc.SpriteFrame(); 282 frame.initWithTextureFilename(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels); 283 frame.setTexture(this._texture); 284 return frame; 285 }, 286 287 /** 288 * copy a new SpriteFrame 289 * @return {cc.SpriteFrame} 290 */ 291 copyWithZone:function () { 292 var copy = new cc.SpriteFrame(); 293 copy.initWithTextureFilename(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels); 294 copy.setTexture(this._texture); 295 return copy; 296 }, 297 298 copy:function () { 299 return this.copyWithZone(); 300 }, 301 302 /** 303 * Initializes SpriteFrame with Texture, rect, rotated, offset and originalSize in pixels. 304 * @param {cc.Texture2D} texture 305 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 306 * @param {Boolean} [rotated=false] 307 * @param {cc.Point} [offset=cc.p(0,0)] 308 * @param {cc.Size} [originalSize=rect.size] 309 * @return {Boolean} 310 */ 311 initWithTexture:function (texture, rect, rotated, offset, originalSize) { 312 if(arguments.length === 2) 313 rect = cc.RECT_POINTS_TO_PIXELS(rect); 314 315 offset = offset || cc.p(0, 0); 316 originalSize = originalSize || rect._size; 317 318 this.setTexture(texture); 319 this._rectInPixels = rect; 320 this._rect = cc.RECT_PIXELS_TO_POINTS(rect); 321 this._offsetInPixels._x = offset.x; 322 this._offsetInPixels._y = offset.y; 323 cc._POINT_PIXELS_TO_POINTS_OUT(offset, this._offset); 324 this._originalSizeInPixels._width = originalSize.width; 325 this._originalSizeInPixels._height = originalSize.height; 326 cc._SIZE_PIXELS_TO_POINTS_OUT(originalSize, this._originalSize); 327 this._rotated = rotated || false; 328 return true; 329 }, 330 331 /** 332 * <p> 333 * Initializes a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.<br/> 334 * The originalSize is the size in pixels of the frame before being trimmed. 335 * </p> 336 * @param {string} filename 337 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 338 * @param {Boolean} rotated 339 * @param {cc.Point} [offset=cc.p(0,0)] 340 * @param {cc.Size} [originalSize=rect.size] 341 */ 342 initWithTextureFilename:function (filename, rect, rotated, offset, originalSize) { 343 if(arguments.length === 2) 344 rect = cc.RECT_POINTS_TO_PIXELS(rect); 345 346 offset = offset || cc.p(0, 0); 347 originalSize = originalSize || rect._size; 348 349 this._texture = null; 350 this._textureFilename = filename; 351 this._rectInPixels = rect; 352 this._rect = cc.RECT_PIXELS_TO_POINTS(rect); 353 this._rotated = rotated || false; 354 this._offsetInPixels._x = offset.x; 355 this._offsetInPixels._y = offset.y; 356 cc._POINT_PIXELS_TO_POINTS_OUT(offset, this._offset); 357 this._originalSizeInPixels._width = originalSize.width; 358 this._originalSizeInPixels._height = originalSize.height; 359 cc._SIZE_PIXELS_TO_POINTS_OUT(originalSize, this._originalSize); 360 return true; 361 } 362 }); 363 364 /** 365 * <p> 366 * Create a cc.SpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels.<br/> 367 * The originalSize is the size in pixels of the frame before being trimmed. 368 * </p> 369 * @param {string} filename 370 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 371 * @param {Boolean} rotated 372 * @param {cc.Point} offset 373 * @param {cc.Size} originalSize 374 * @return {cc.SpriteFrame} 375 */ 376 cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) { 377 var spriteFrame = new cc.SpriteFrame(); 378 switch (arguments.length) { 379 case 2: 380 spriteFrame.initWithTextureFilename(filename, rect); 381 break; 382 case 5: 383 spriteFrame.initWithTextureFilename(filename, rect, rotated, offset, originalSize); 384 break; 385 default: 386 throw "Argument must be non-nil "; 387 break; 388 } 389 return spriteFrame; 390 }; 391 392 /** 393 * Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. 394 * @param {cc.Texture2D} texture 395 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 396 * @param {Boolean} [rotated=] 397 * @param {cc.Point} [offset=] 398 * @param {cc.Size} [originalSize=] 399 * @return {cc.SpriteFrame} 400 * @example 401 * //Create a cc.SpriteFrame with a texture, rect in texture. 402 * var frame1 = cc.SpriteFrame.createWithTexture("grossini_dance.png",cc.rect(0,0,90,128)); 403 * 404 * //Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. 405 * var frame2 = cc.SpriteFrame.createWithTexture(texture, frameRect, rotated, offset, sourceSize); 406 */ 407 cc.SpriteFrame.createWithTexture = function (texture, rect, rotated, offset, originalSize) { 408 var spriteFrame = new cc.SpriteFrame(); 409 switch (arguments.length) { 410 case 2: 411 spriteFrame.initWithTexture(texture, rect); 412 break; 413 case 5: 414 spriteFrame.initWithTexture(texture, rect, rotated, offset, originalSize); 415 break; 416 default: 417 throw "Argument must be non-nil "; 418 break; 419 } 420 return spriteFrame; 421 }; 422 423 cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) { 424 var spriteFrame = new cc.SpriteFrame(); 425 spriteFrame._texture = texture; 426 spriteFrame._rectInPixels = rect; 427 spriteFrame._rect = cc.RECT_PIXELS_TO_POINTS(rect); 428 spriteFrame._offsetInPixels._x = offset.x; 429 spriteFrame._offsetInPixels._y = offset.y; 430 cc._POINT_PIXELS_TO_POINTS_OUT(spriteFrame._offsetInPixels, spriteFrame._offset); 431 spriteFrame._originalSizeInPixels._width = originalSize.width; 432 spriteFrame._originalSizeInPixels._height = originalSize.height; 433 cc._SIZE_PIXELS_TO_POINTS_OUT(spriteFrame._originalSizeInPixels, spriteFrame._originalSize); 434 spriteFrame._rotated = rotated; 435 return spriteFrame; 436 }; 437