CCSpriteFrame.js 15 KB

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