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.addImage(s_dragon_animation); 40 * var frame0 = cc.SpriteFrame.create(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.p(0, 0); 57 this._offsetInPixels = cc.p(0, 0); 58 this._originalSize = cc.size(0, 0); 59 this._rotated = false; 60 this._originalSizeInPixels = cc.size(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.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._renderType === cc._RENDER_TYPE_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 w = sender.width, h = sender.height; 248 this._rect.width = w; 249 this._rect.height = h; 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 = w; 254 this._originalSize.height = h; 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.initWithTexture(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.initWithTexture(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 {String|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; 317 rotated = rotated || false; 318 319 if (typeof(texture) == "string"){ 320 this._texture = null; 321 this._textureFilename = texture; 322 } else if (texture instanceof cc.Texture2D){ 323 this.setTexture(texture); 324 } 325 326 this._rectInPixels = rect; 327 this._rect = cc.RECT_PIXELS_TO_POINTS(rect); 328 this._offsetInPixels.x = offset.x; 329 this._offsetInPixels.y = offset.y; 330 cc._POINT_PIXELS_TO_POINTS_OUT(offset, this._offset); 331 this._originalSizeInPixels.width = originalSize.width; 332 this._originalSizeInPixels.height = originalSize.height; 333 cc._SIZE_PIXELS_TO_POINTS_OUT(originalSize, this._originalSize); 334 this._rotated = rotated; 335 return true; 336 } 337 }); 338 339 /** 340 * <p> 341 * Create a cc.SpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels.<br/> 342 * The originalSize is the size in pixels of the frame before being trimmed. 343 * </p> 344 * @param {String|cc.Texture2D} filename 345 * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels 346 * @param {Boolean} rotated 347 * @param {cc.Point} offset 348 * @param {cc.Size} originalSize 349 * @return {cc.SpriteFrame} 350 * @example 351 * 1. 352 * //Create a cc.SpriteFrame with image path 353 * var frame1 = cc.SpriteFrame.create("res/grossini_dance.png",cc.rect(0,0,90,128)); 354 * var frame2 = cc.SpriteFrame.create("res/grossini_dance.png",cc.rect(0,0,90,128),false,0,cc.size(90,128)); 355 * 356 * 2. 357 * //Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. 358 * var texture = cc.textureCache.addImage("res/grossini_dance.png"); 359 * var frame1 = cc.SpriteFrame.create(texture, cc.rect(0,0,90,128)); 360 * var frame2 = cc.SpriteFrame.create(texture, cc.rect(0,0,90,128),false,0,cc.size(90,128)); 361 */ 362 cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) { 363 var spriteFrame = new cc.SpriteFrame(); 364 switch (arguments.length) { 365 case 2: 366 spriteFrame.initWithTexture(filename, rect); 367 break; 368 case 5: 369 spriteFrame.initWithTexture(filename, rect, rotated, offset, originalSize); 370 break; 371 default: 372 throw "Argument must be non-nil "; 373 break; 374 } 375 return spriteFrame; 376 }; 377 378 cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) { 379 var spriteFrame = new cc.SpriteFrame(); 380 spriteFrame._texture = texture; 381 spriteFrame._rectInPixels = rect; 382 spriteFrame._rect = cc.RECT_PIXELS_TO_POINTS(rect); 383 spriteFrame._offsetInPixels.x = offset.x; 384 spriteFrame._offsetInPixels.y = offset.y; 385 cc._POINT_PIXELS_TO_POINTS_OUT(spriteFrame._offsetInPixels, spriteFrame._offset); 386 spriteFrame._originalSizeInPixels.width = originalSize.width; 387 spriteFrame._originalSizeInPixels.height = originalSize.height; 388 cc._SIZE_PIXELS_TO_POINTS_OUT(spriteFrame._originalSizeInPixels, spriteFrame._originalSize); 389 spriteFrame._rotated = rotated; 390 return spriteFrame; 391 }; 392