CCSprite.js 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722
  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. * Tint a texture using the "multiply" operation
  24. * @param {HTMLImageElement} image
  25. * @param {cc.Color} color
  26. * @param {cc.Rect} [rect]
  27. * @param {HTMLCanvasElement} renderCanvas
  28. * @returns {HTMLCanvasElement}
  29. */
  30. cc.generateTintImageWithMultiply = function(image, color, rect, renderCanvas){
  31. renderCanvas = renderCanvas || cc.newElement("canvas");
  32. rect = rect || cc.rect(0,0, image.width, image.height);
  33. var context = renderCanvas.getContext( "2d" );
  34. if(renderCanvas.width != rect.width || renderCanvas.height != rect.height){
  35. renderCanvas.width = rect.width;
  36. renderCanvas.height = rect.height;
  37. }else{
  38. context.globalCompositeOperation = "source-over";
  39. }
  40. context.fillStyle = "rgb(" + (0|color.r) + "," + (0|color.g) + "," + (0|color.b) + ")";
  41. context.fillRect(0, 0, rect.width, rect.height);
  42. context.globalCompositeOperation = "multiply";
  43. context.drawImage(image,
  44. rect.x,
  45. rect.y,
  46. rect.width,
  47. rect.height,
  48. 0,
  49. 0,
  50. rect.width,
  51. rect.height);
  52. context.globalCompositeOperation = "destination-atop";
  53. context.drawImage(image,
  54. rect.x,
  55. rect.y,
  56. rect.width,
  57. rect.height,
  58. 0,
  59. 0,
  60. rect.width,
  61. rect.height);
  62. return renderCanvas;
  63. };
  64. /**
  65. * Generate tinted texture with lighter.
  66. * lighter: The source and destination colors are added to each other, resulting in brighter colors,
  67. * moving towards color values of 1 (maximum brightness for that color).
  68. * @function
  69. * @param {HTMLImageElement} texture
  70. * @param {Array} tintedImgCache
  71. * @param {cc.Color} color
  72. * @param {cc.Rect} rect
  73. * @param {HTMLCanvasElement} [renderCanvas]
  74. * @return {HTMLCanvasElement}
  75. */
  76. cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCanvas) {
  77. if (!rect)
  78. rect = cc.rect(0, 0, texture.width, texture.height);
  79. var r = color.r / 255;
  80. var g = color.g / 255;
  81. var b = color.b / 255;
  82. var w = Math.min(rect.width, tintedImgCache[0].width);
  83. var h = Math.min(rect.height, tintedImgCache[0].height);
  84. var buff = renderCanvas;
  85. var ctx;
  86. // Create a new buffer if required
  87. if (!buff) {
  88. buff = cc.newElement("canvas");
  89. buff.width = w;
  90. buff.height = h;
  91. ctx = buff.getContext("2d");
  92. } else {
  93. ctx = buff.getContext("2d");
  94. ctx.clearRect(0, 0, w, h);
  95. }
  96. ctx.save();
  97. ctx.globalCompositeOperation = 'lighter';
  98. // Make sure to keep the renderCanvas alpha in mind in case of overdraw
  99. var a = ctx.globalAlpha;
  100. if (r > 0) {
  101. ctx.globalAlpha = r * a;
  102. ctx.drawImage(tintedImgCache[0], rect.x, rect.y, w, h, 0, 0, w, h);
  103. }
  104. if (g > 0) {
  105. ctx.globalAlpha = g * a;
  106. ctx.drawImage(tintedImgCache[1], rect.x, rect.y, w, h, 0, 0, w, h);
  107. }
  108. if (b > 0) {
  109. ctx.globalAlpha = b * a;
  110. ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h);
  111. }
  112. if (r + g + b < 1) {
  113. ctx.globalAlpha = a;
  114. ctx.drawImage(tintedImgCache[3], rect.x, rect.y, w, h, 0, 0, w, h);
  115. }
  116. ctx.restore();
  117. return buff;
  118. };
  119. /**
  120. * Generates texture's cache for texture tint
  121. * @function
  122. * @param {HTMLImageElement} texture
  123. * @return {Array}
  124. */
  125. cc.generateTextureCacheForColor = function (texture) {
  126. if (texture.channelCache) {
  127. return texture.channelCache;
  128. }
  129. var textureCache = [
  130. cc.newElement("canvas"),
  131. cc.newElement("canvas"),
  132. cc.newElement("canvas"),
  133. cc.newElement("canvas")
  134. ];
  135. function renderToCache() {
  136. var ref = cc.generateTextureCacheForColor;
  137. var w = texture.width;
  138. var h = texture.height;
  139. textureCache[0].width = w;
  140. textureCache[0].height = h;
  141. textureCache[1].width = w;
  142. textureCache[1].height = h;
  143. textureCache[2].width = w;
  144. textureCache[2].height = h;
  145. textureCache[3].width = w;
  146. textureCache[3].height = h;
  147. ref.canvas.width = w;
  148. ref.canvas.height = h;
  149. var ctx = ref.canvas.getContext("2d");
  150. ctx.drawImage(texture, 0, 0);
  151. ref.tempCanvas.width = w;
  152. ref.tempCanvas.height = h;
  153. var pixels = ctx.getImageData(0, 0, w, h).data;
  154. for (var rgbI = 0; rgbI < 4; rgbI++) {
  155. var cacheCtx = textureCache[rgbI].getContext('2d');
  156. cacheCtx.getImageData(0, 0, w, h).data;
  157. ref.tempCtx.drawImage(texture, 0, 0);
  158. var to = ref.tempCtx.getImageData(0, 0, w, h);
  159. var toData = to.data;
  160. for (var i = 0; i < pixels.length; i += 4) {
  161. toData[i ] = (rgbI === 0) ? pixels[i ] : 0;
  162. toData[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0;
  163. toData[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0;
  164. toData[i + 3] = pixels[i + 3];
  165. }
  166. cacheCtx.putImageData(to, 0, 0);
  167. }
  168. texture.onload = null;
  169. }
  170. try {
  171. renderToCache();
  172. } catch (e) {
  173. texture.onload = renderToCache;
  174. }
  175. texture.channelCache = textureCache;
  176. return textureCache;
  177. };
  178. cc.generateTextureCacheForColor.canvas = cc.newElement('canvas');
  179. cc.generateTextureCacheForColor.tempCanvas = cc.newElement('canvas');
  180. cc.generateTextureCacheForColor.tempCtx = cc.generateTextureCacheForColor.tempCanvas.getContext('2d');
  181. cc.cutRotateImageToCanvas = function (texture, rect) {
  182. if (!texture)
  183. return null;
  184. if (!rect)
  185. return texture;
  186. var nCanvas = cc.newElement("canvas");
  187. nCanvas.width = rect.width;
  188. nCanvas.height = rect.height;
  189. var ctx = nCanvas.getContext("2d");
  190. ctx.translate(nCanvas.width / 2, nCanvas.height / 2);
  191. ctx.rotate(-1.5707963267948966);
  192. ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width);
  193. return nCanvas;
  194. };
  195. cc._getCompositeOperationByBlendFunc = function(blendFunc){
  196. if(!blendFunc)
  197. return "source";
  198. else{
  199. if(( blendFunc.src == cc.SRC_ALPHA && blendFunc.dst == cc.ONE) || (blendFunc.src == cc.ONE && blendFunc.dst == cc.ONE))
  200. return "lighter";
  201. else if(blendFunc.src == cc.ZERO && blendFunc.dst == cc.SRC_ALPHA)
  202. return "destination-in";
  203. else if(blendFunc.src == cc.ZERO && blendFunc.dst == cc.ONE_MINUS_SRC_ALPHA)
  204. return "destination-out";
  205. else
  206. return "source";
  207. }
  208. };
  209. /**
  210. * <p>cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) <br/>
  211. *
  212. * cc.Sprite can be created with an image, or with a sub-rectangle of an image. <br/>
  213. *
  214. * If the parent or any of its ancestors is a cc.SpriteBatchNode then the following features/limitations are valid <br/>
  215. * - Features when the parent is a cc.BatchNode: <br/>
  216. * - MUCH faster rendering, specially if the cc.SpriteBatchNode has many children. All the children will be drawn in a single batch. <br/>
  217. *
  218. * - Limitations <br/>
  219. * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work) <br/>
  220. * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl) <br/>
  221. * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property. <br/>
  222. * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property. <br/>
  223. * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite. <br/>
  224. *
  225. * If the parent is an standard cc.Node, then cc.Sprite behaves like any other cc.Node: <br/>
  226. * - It supports blending functions <br/>
  227. * - It supports aliasing / antialiasing <br/>
  228. * - But the rendering will be slower: 1 draw per children. <br/>
  229. *
  230. * The default anchorPoint in cc.Sprite is (0.5, 0.5). </p>
  231. * @class
  232. * @extends cc.Node
  233. *
  234. * @param {String|cc.SpriteFrame|HTMLImageElement|cc.Texture2D} fileName The string which indicates a path to image file, e.g., "scene1/monster.png".
  235. * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite.
  236. * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
  237. * @example
  238. *
  239. * 1.Create a sprite with image path and rect
  240. * var sprite1 = new cc.Sprite("res/HelloHTML5World.png");
  241. * var sprite2 = new cc.Sprite("res/HelloHTML5World.png",cc.rect(0,0,480,320));
  242. *
  243. * 2.Create a sprite with a sprite frame name. Must add "#" before frame name.
  244. * var sprite = new cc.Sprite('#grossini_dance_01.png');
  245. *
  246. * 3.Create a sprite with a sprite frame
  247. * var spriteFrame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
  248. * var sprite = new cc.Sprite(spriteFrame);
  249. *
  250. * 4.Create a sprite with an existing texture contained in a CCTexture2D object
  251. * After creation, the rect will be the size of the texture, and the offset will be (0,0).
  252. * var texture = cc.textureCache.addImage("HelloHTML5World.png");
  253. * var sprite1 = new cc.Sprite(texture);
  254. * var sprite2 = new cc.Sprite(texture, cc.rect(0,0,480,320));
  255. *
  256. * @property {Boolean} dirty - Indicates whether the sprite needs to be updated.
  257. * @property {Boolean} flippedX - Indicates whether or not the spirte is flipped on x axis.
  258. * @property {Boolean} flippedY - Indicates whether or not the spirte is flipped on y axis.
  259. * @property {Number} offsetX - <@readonly> The offset position on x axis of the sprite in texture. Calculated automatically by editors like Zwoptex.
  260. * @property {Number} offsetY - <@readonly> The offset position on x axis of the sprite in texture. Calculated automatically by editors like Zwoptex.
  261. * @property {Number} atlasIndex - The index used on the TextureAtlas.
  262. * @property {cc.Texture2D} texture - Texture used to render the sprite.
  263. * @property {Boolean} textureRectRotated - <@readonly> Indicate whether the texture rectangle is rotated.
  264. * @property {cc.TextureAtlas} textureAtlas - The weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode.
  265. * @property {cc.SpriteBatchNode} batchNode - The batch node object if this sprite is rendered by cc.SpriteBatchNode.
  266. * @property {cc.V3F_C4B_T2F_Quad} quad - <@readonly> The quad (tex coords, vertex coords and color) information.
  267. */
  268. cc.Sprite = cc.Node.extend(/** @lends cc.Sprite# */{
  269. dirty:false,
  270. atlasIndex:0,
  271. textureAtlas:null,
  272. _batchNode:null,
  273. _recursiveDirty:null, //Whether all of the sprite's children needs to be updated
  274. _hasChildren:null, //Whether the sprite contains children
  275. _shouldBeHidden:false, //should not be drawn because one of the ancestors is not visible
  276. _transformToBatch:null,
  277. //
  278. // Data used when the sprite is self-rendered
  279. //
  280. _blendFunc:null, //It's required for CCTextureProtocol inheritance
  281. _texture:null, //cc.Texture2D object that is used to render the sprite
  282. //
  283. // Shared data
  284. //
  285. // texture
  286. _rect:null, //Retangle of cc.Texture2D
  287. _rectRotated:false, //Whether the texture is rotated
  288. // Offset Position (used by Zwoptex)
  289. _offsetPosition:null, // absolute
  290. _unflippedOffsetPositionFromCenter:null,
  291. _opacityModifyRGB:false,
  292. // image is flipped
  293. _flippedX:false, //Whether the sprite is flipped horizontally or not.
  294. _flippedY:false, //Whether the sprite is flipped vertically or not.
  295. _textureLoaded:false,
  296. _loadedEventListeners: null,
  297. _newTextureWhenChangeColor: null, //hack property for LabelBMFont
  298. _className:"Sprite",
  299. //Only for texture update judgment
  300. _oldDisplayColor: cc.color.WHITE,
  301. /**
  302. * Returns whether the texture have been loaded
  303. * @returns {boolean}
  304. */
  305. textureLoaded:function(){
  306. return this._textureLoaded;
  307. },
  308. /**
  309. * Add a event listener for texture loaded event.
  310. * @param {Function} callback
  311. * @param {Object} target
  312. */
  313. addLoadedEventListener:function(callback, target){
  314. if(!this._loadedEventListeners)
  315. this._loadedEventListeners = [];
  316. this._loadedEventListeners.push({eventCallback:callback, eventTarget:target});
  317. },
  318. _callLoadedEventCallbacks:function(){
  319. if(!this._loadedEventListeners)
  320. return;
  321. var locListeners = this._loadedEventListeners;
  322. for(var i = 0, len = locListeners.length; i < len; i++){
  323. var selCallback = locListeners[i];
  324. selCallback.eventCallback.call(selCallback.eventTarget, this);
  325. }
  326. locListeners.length = 0;
  327. },
  328. /**
  329. * Returns whether or not the Sprite needs to be updated in the Atlas
  330. * @return {Boolean} True if the sprite needs to be updated in the Atlas, false otherwise.
  331. */
  332. isDirty:function () {
  333. return this.dirty;
  334. },
  335. /**
  336. * Makes the sprite to be updated in the Atlas.
  337. * @param {Boolean} bDirty
  338. */
  339. setDirty:function (bDirty) {
  340. this.dirty = bDirty;
  341. },
  342. /**
  343. * Returns whether or not the texture rectangle is rotated.
  344. * @return {Boolean}
  345. */
  346. isTextureRectRotated:function () {
  347. return this._rectRotated;
  348. },
  349. /**
  350. * Returns the index used on the TextureAtlas.
  351. * @return {Number}
  352. */
  353. getAtlasIndex:function () {
  354. return this.atlasIndex;
  355. },
  356. /**
  357. * Sets the index used on the TextureAtlas.
  358. * @warning Don't modify this value unless you know what you are doing
  359. * @param {Number} atlasIndex
  360. */
  361. setAtlasIndex:function (atlasIndex) {
  362. this.atlasIndex = atlasIndex;
  363. },
  364. /**
  365. * Returns the rect of the cc.Sprite in points
  366. * @return {cc.Rect}
  367. */
  368. getTextureRect:function () {
  369. return cc.rect(this._rect.x, this._rect.y, this._rect.width, this._rect.height);
  370. },
  371. /**
  372. * Returns the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
  373. * @return {cc.TextureAtlas}
  374. */
  375. getTextureAtlas:function () {
  376. return this.textureAtlas;
  377. },
  378. /**
  379. * Sets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
  380. * @param {cc.TextureAtlas} textureAtlas
  381. */
  382. setTextureAtlas:function (textureAtlas) {
  383. this.textureAtlas = textureAtlas;
  384. },
  385. /**
  386. * Returns the offset position of the sprite. Calculated automatically by editors like Zwoptex.
  387. * @return {cc.Point}
  388. */
  389. getOffsetPosition:function () {
  390. return cc.p(this._offsetPosition);
  391. },
  392. _getOffsetX: function () {
  393. return this._offsetPosition.x;
  394. },
  395. _getOffsetY: function () {
  396. return this._offsetPosition.y;
  397. },
  398. /**
  399. * Returns the blend function
  400. * @return {cc.BlendFunc}
  401. */
  402. getBlendFunc:function () {
  403. return this._blendFunc;
  404. },
  405. /**
  406. * Initializes a sprite with an SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite.<br/>
  407. * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself,
  408. * @param {cc.SpriteFrame} spriteFrame A CCSpriteFrame object. It should includes a valid texture and a rect
  409. * @return {Boolean} true if the sprite is initialized properly, false otherwise.
  410. */
  411. initWithSpriteFrame:function (spriteFrame) {
  412. cc.assert(spriteFrame, cc._LogInfos.Sprite_initWithSpriteFrame);
  413. if(!spriteFrame.textureLoaded()){
  414. //add event listener
  415. this._textureLoaded = false;
  416. spriteFrame.addLoadedEventListener(this._spriteFrameLoadedCallback, this);
  417. }
  418. var rotated = cc._renderType === cc._RENDER_TYPE_CANVAS ? false : spriteFrame._rotated;
  419. var ret = this.initWithTexture(spriteFrame.getTexture(), spriteFrame.getRect(), rotated);
  420. this.setSpriteFrame(spriteFrame);
  421. return ret;
  422. },
  423. _spriteFrameLoadedCallback:null,
  424. /**
  425. * Initializes a sprite with a sprite frame name. <br/>
  426. * A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name. <br/>
  427. * If the cc.SpriteFrame doesn't exist it will raise an exception. <br/>
  428. * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
  429. * @param {String} spriteFrameName A key string that can fected a volid cc.SpriteFrame from cc.SpriteFrameCache
  430. * @return {Boolean} true if the sprite is initialized properly, false otherwise.
  431. * @example
  432. * var sprite = new cc.Sprite();
  433. * sprite.initWithSpriteFrameName("grossini_dance_01.png");
  434. */
  435. initWithSpriteFrameName:function (spriteFrameName) {
  436. cc.assert(spriteFrameName, cc._LogInfos.Sprite_initWithSpriteFrameName);
  437. var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
  438. cc.assert(frame, spriteFrameName + cc._LogInfos.Sprite_initWithSpriteFrameName1);
  439. return this.initWithSpriteFrame(frame);
  440. },
  441. /**
  442. * Tell the sprite to use batch node render.
  443. * @param {cc.SpriteBatchNode} batchNode
  444. */
  445. useBatchNode:function (batchNode) {
  446. this.textureAtlas = batchNode.textureAtlas; // weak ref
  447. this._batchNode = batchNode;
  448. },
  449. /**
  450. * <p>
  451. * set the vertex rect.<br/>
  452. * It will be called internally by setTextureRect. <br/>
  453. * Useful if you want to create 2x images from SD images in Retina Display. <br/>
  454. * Do not call it manually. Use setTextureRect instead. <br/>
  455. * (override this method to generate "double scale" sprites)
  456. * </p>
  457. * @param {cc.Rect} rect
  458. */
  459. setVertexRect:function (rect) {
  460. this._rect.x = rect.x;
  461. this._rect.y = rect.y;
  462. this._rect.width = rect.width;
  463. this._rect.height = rect.height;
  464. },
  465. /**
  466. * Sort all children of this sprite node.
  467. * @override
  468. */
  469. sortAllChildren:function () {
  470. if (this._reorderChildDirty) {
  471. var _children = this._children;
  472. // insertion sort
  473. var len = _children.length, i, j, tmp;
  474. for(i=1; i<len; i++){
  475. tmp = _children[i];
  476. j = i - 1;
  477. //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
  478. while(j >= 0){
  479. if(tmp._localZOrder < _children[j]._localZOrder){
  480. _children[j+1] = _children[j];
  481. }else if(tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder){
  482. _children[j+1] = _children[j];
  483. }else{
  484. break;
  485. }
  486. j--;
  487. }
  488. _children[j+1] = tmp;
  489. }
  490. if (this._batchNode) {
  491. this._arrayMakeObjectsPerformSelector(_children, cc.Node._StateCallbackType.sortAllChildren);
  492. }
  493. //don't need to check children recursively, that's done in visit of each child
  494. this._reorderChildDirty = false;
  495. }
  496. },
  497. /**
  498. * Reorders a child according to a new z value. (override cc.Node )
  499. * @param {cc.Node} child
  500. * @param {Number} zOrder
  501. * @override
  502. */
  503. reorderChild:function (child, zOrder) {
  504. cc.assert(child, cc._LogInfos.Sprite_reorderChild_2);
  505. if(this._children.indexOf(child) === -1){
  506. cc.log(cc._LogInfos.Sprite_reorderChild);
  507. return;
  508. }
  509. if (zOrder === child.zIndex)
  510. return;
  511. if (this._batchNode && !this._reorderChildDirty) {
  512. this._setReorderChildDirtyRecursively();
  513. this._batchNode.reorderBatch(true);
  514. }
  515. cc.Node.prototype.reorderChild.call(this, child, zOrder);
  516. },
  517. /**
  518. * Removes a child from the sprite.
  519. * @param child
  520. * @param cleanup whether or not cleanup all running actions
  521. * @override
  522. */
  523. removeChild:function (child, cleanup) {
  524. if (this._batchNode)
  525. this._batchNode.removeSpriteFromAtlas(child);
  526. cc.Node.prototype.removeChild.call(this, child, cleanup);
  527. },
  528. /**
  529. * Sets whether the sprite is visible or not.
  530. * @param {Boolean} visible
  531. * @override
  532. */
  533. setVisible:function (visible) {
  534. cc.Node.prototype.setVisible.call(this, visible);
  535. this.setDirtyRecursively(true);
  536. },
  537. /**
  538. * Removes all children from the container.
  539. * @param cleanup whether or not cleanup all running actions
  540. * @override
  541. */
  542. removeAllChildren:function (cleanup) {
  543. var locChildren = this._children, locBatchNode = this._batchNode;
  544. if (locBatchNode && locChildren != null) {
  545. for (var i = 0, len = locChildren.length; i < len; i++)
  546. locBatchNode.removeSpriteFromAtlas(locChildren[i]);
  547. }
  548. cc.Node.prototype.removeAllChildren.call(this, cleanup);
  549. this._hasChildren = false;
  550. },
  551. //
  552. // cc.Node property overloads
  553. //
  554. /**
  555. * Sets recursively the dirty flag.
  556. * Used only when parent is cc.SpriteBatchNode
  557. * @param {Boolean} value
  558. */
  559. setDirtyRecursively:function (value) {
  560. this._recursiveDirty = value;
  561. this.dirty = value;
  562. // recursively set dirty
  563. var locChildren = this._children, child, l = locChildren ? locChildren.length : 0;
  564. for (var i = 0; i < l; i++) {
  565. child = locChildren[i];
  566. (child instanceof cc.Sprite) && child.setDirtyRecursively(true);
  567. }
  568. },
  569. /**
  570. * Make the node dirty
  571. * @param {Boolean} norecursive When true children will not be set dirty recursively, by default, they will be.
  572. * @override
  573. */
  574. setNodeDirty: function(norecursive) {
  575. cc.Node.prototype.setNodeDirty.call(this);
  576. // Lazy set dirty
  577. if (!norecursive && this._batchNode && !this._recursiveDirty) {
  578. if (this._hasChildren)
  579. this.setDirtyRecursively(true);
  580. else {
  581. this._recursiveDirty = true;
  582. this.dirty = true;
  583. }
  584. }
  585. },
  586. /**
  587. * Sets whether ignore anchor point for positioning
  588. * @param {Boolean} relative
  589. * @override
  590. */
  591. ignoreAnchorPointForPosition:function (relative) {
  592. if(this._batchNode){
  593. cc.log(cc._LogInfos.Sprite_ignoreAnchorPointForPosition);
  594. return;
  595. }
  596. cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative);
  597. },
  598. /**
  599. * Sets whether the sprite should be flipped horizontally or not.
  600. * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise.
  601. */
  602. setFlippedX:function (flippedX) {
  603. if (this._flippedX != flippedX) {
  604. this._flippedX = flippedX;
  605. this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
  606. this.setNodeDirty(true);
  607. }
  608. },
  609. /**
  610. * Sets whether the sprite should be flipped vertically or not.
  611. * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise.
  612. */
  613. setFlippedY:function (flippedY) {
  614. if (this._flippedY != flippedY) {
  615. this._flippedY = flippedY;
  616. this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
  617. this.setNodeDirty(true);
  618. }
  619. },
  620. /**
  621. * <p>
  622. * Returns the flag which indicates whether the sprite is flipped horizontally or not. <br/>
  623. * <br/>
  624. * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/>
  625. * Also, flipping the texture doesn't alter the anchorPoint. <br/>
  626. * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/>
  627. * sprite.setScaleX(sprite.getScaleX() * -1); <p/>
  628. * @return {Boolean} true if the sprite is flipped horizontally, false otherwise.
  629. */
  630. isFlippedX:function () {
  631. return this._flippedX;
  632. },
  633. /**
  634. * <p>
  635. * Return the flag which indicates whether the sprite is flipped vertically or not. <br/>
  636. * <br/>
  637. * It only flips the texture of the sprite, and not the texture of the sprite's children. <br/>
  638. * Also, flipping the texture doesn't alter the anchorPoint. <br/>
  639. * If you want to flip the anchorPoint too, and/or to flip the children too use: <br/>
  640. * sprite.setScaleY(sprite.getScaleY() * -1); <p/>
  641. * @return {Boolean} true if the sprite is flipped vertically, false otherwise.
  642. */
  643. isFlippedY:function () {
  644. return this._flippedY;
  645. },
  646. //
  647. // RGBA protocol
  648. //
  649. /**
  650. * Sets whether opacity modify color or not.
  651. * @function
  652. * @param {Boolean} modify
  653. */
  654. setOpacityModifyRGB:null,
  655. /**
  656. * Returns whether opacity modify color or not.
  657. * @return {Boolean}
  658. */
  659. isOpacityModifyRGB:function () {
  660. return this._opacityModifyRGB;
  661. },
  662. /**
  663. * Update the display opacity.
  664. * @function
  665. */
  666. updateDisplayedOpacity: null,
  667. // Animation
  668. /**
  669. * Changes the display frame with animation name and index.<br/>
  670. * The animation name will be get from the CCAnimationCache
  671. * @param {String} animationName
  672. * @param {Number} frameIndex
  673. */
  674. setDisplayFrameWithAnimationName:function (animationName, frameIndex) {
  675. cc.assert(animationName, cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_3);
  676. var cache = cc.animationCache.getAnimation(animationName);
  677. if(!cache){
  678. cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName);
  679. return;
  680. }
  681. var animFrame = cache.getFrames()[frameIndex];
  682. if(!animFrame){
  683. cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_2);
  684. return;
  685. }
  686. this.setSpriteFrame(animFrame.getSpriteFrame());
  687. },
  688. /**
  689. * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode
  690. * @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.
  691. */
  692. getBatchNode:function () {
  693. return this._batchNode;
  694. },
  695. _setReorderChildDirtyRecursively:function () {
  696. //only set parents flag the first time
  697. if (!this._reorderChildDirty) {
  698. this._reorderChildDirty = true;
  699. var pNode = this._parent;
  700. while (pNode && pNode != this._batchNode) {
  701. pNode._setReorderChildDirtyRecursively();
  702. pNode = pNode.parent;
  703. }
  704. }
  705. },
  706. // CCTextureProtocol
  707. /**
  708. * Returns the texture of the sprite node
  709. * @returns {cc.Texture2D}
  710. */
  711. getTexture:function () {
  712. return this._texture;
  713. },
  714. _quad: null, // vertex coords, texture coords and color info
  715. _quadWebBuffer: null,
  716. _quadDirty: false,
  717. _colorized: false,
  718. _blendFuncStr: "source",
  719. _originalTexture: null,
  720. _textureRect_Canvas: null,
  721. _drawSize_Canvas: null,
  722. ctor: null,
  723. _softInit: function (fileName, rect, rotated) {
  724. if (fileName === undefined)
  725. cc.Sprite.prototype.init.call(this);
  726. else if (typeof(fileName) === "string") {
  727. if (fileName[0] === "#") {
  728. // Init with a sprite frame name
  729. var frameName = fileName.substr(1, fileName.length - 1);
  730. var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
  731. this.initWithSpriteFrame(spriteFrame);
  732. } else {
  733. // Init with filename and rect
  734. cc.Sprite.prototype.init.call(this, fileName, rect);
  735. }
  736. }
  737. else if (typeof(fileName) === "object") {
  738. if (fileName instanceof cc.Texture2D) {
  739. // Init with texture and rect
  740. this.initWithTexture(fileName, rect, rotated);
  741. } else if (fileName instanceof cc.SpriteFrame) {
  742. // Init with a sprite frame
  743. this.initWithSpriteFrame(fileName);
  744. } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) {
  745. // Init with a canvas or image element
  746. var texture2d = new cc.Texture2D();
  747. texture2d.initWithElement(fileName);
  748. texture2d.handleLoadedTexture();
  749. this.initWithTexture(texture2d);
  750. }
  751. }
  752. },
  753. /**
  754. * Returns the quad (tex coords, vertex coords and color) information.
  755. * @return {cc.V3F_C4B_T2F_Quad}
  756. */
  757. getQuad:function () {
  758. return this._quad;
  759. },
  760. /**
  761. * conforms to cc.TextureProtocol protocol
  762. * @function
  763. * @param {Number|cc.BlendFunc} src
  764. * @param {Number} dst
  765. */
  766. setBlendFunc: null,
  767. /**
  768. * Initializes an empty sprite with nothing init.<br/>
  769. * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
  770. * @function
  771. * @return {Boolean}
  772. */
  773. init:null,
  774. /**
  775. * <p>
  776. * Initializes a sprite with an image filename.<br/>
  777. *
  778. * This method will find pszFilename from local file system, load its content to CCTexture2D,<br/>
  779. * then use CCTexture2D to create a sprite.<br/>
  780. * After initialization, the rect used will be the size of the image. The offset will be (0,0).<br/>
  781. * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
  782. * </p>
  783. * @param {String} filename The path to an image file in local file system
  784. * @param {cc.Rect} rect The rectangle assigned the content area from texture.
  785. * @return {Boolean} true if the sprite is initialized properly, false otherwise.
  786. */
  787. initWithFile:function (filename, rect) {
  788. cc.assert(filename, cc._LogInfos.Sprite_initWithFile);
  789. var tex = cc.textureCache.getTextureForKey(filename);
  790. if (!tex) {
  791. tex = cc.textureCache.addImage(filename);
  792. return this.initWithTexture(tex, rect || cc.rect(0, 0, tex._contentSize.width, tex._contentSize.height));
  793. } else {
  794. if (!rect) {
  795. var size = tex.getContentSize();
  796. rect = cc.rect(0, 0, size.width, size.height);
  797. }
  798. return this.initWithTexture(tex, rect);
  799. }
  800. },
  801. /**
  802. * Initializes a sprite with a texture and a rect in points, optionally rotated. <br/>
  803. * After initialization, the rect used will be the size of the texture, and the offset will be (0,0).<br/>
  804. * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
  805. * @function
  806. * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites.
  807. * @param {cc.Rect} rect Only the contents inside rect of this texture will be applied for this sprite.
  808. * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
  809. * @return {Boolean} true if the sprite is initialized properly, false otherwise.
  810. */
  811. initWithTexture: null,
  812. _textureLoadedCallback: null,
  813. /**
  814. * Updates the texture rect of the CCSprite in points.
  815. * @function
  816. * @param {cc.Rect} rect a rect of texture
  817. * @param {Boolean} [rotated] Whether or not the texture is rotated
  818. * @param {cc.Size} [untrimmedSize] The original pixels size of the texture
  819. */
  820. setTextureRect:null,
  821. // BatchNode methods
  822. /**
  823. * Updates the quad according the the rotation, position, scale values.
  824. * @function
  825. */
  826. updateTransform: null,
  827. /**
  828. * Add child to sprite (override cc.Node)
  829. * @function
  830. * @param {cc.Sprite} child
  831. * @param {Number} localZOrder child's zOrder
  832. * @param {String} tag child's tag
  833. * @override
  834. */
  835. addChild: null,
  836. /**
  837. * Update sprite's color
  838. */
  839. updateColor:function () {
  840. var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity;
  841. var color4 = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: locDisplayedOpacity};
  842. // special opacity for premultiplied textures
  843. if (this._opacityModifyRGB) {
  844. color4.r *= locDisplayedOpacity / 255.0;
  845. color4.g *= locDisplayedOpacity / 255.0;
  846. color4.b *= locDisplayedOpacity / 255.0;
  847. }
  848. var locQuad = this._quad;
  849. locQuad.bl.colors = color4;
  850. locQuad.br.colors = color4;
  851. locQuad.tl.colors = color4;
  852. locQuad.tr.colors = color4;
  853. // renders using Sprite Manager
  854. if (this._batchNode) {
  855. if (this.atlasIndex != cc.Sprite.INDEX_NOT_INITIALIZED) {
  856. this.textureAtlas.updateQuad(locQuad, this.atlasIndex)
  857. } else {
  858. // no need to set it recursively
  859. // update dirty_, don't update recursiveDirty_
  860. this.dirty = true;
  861. }
  862. }
  863. // self render
  864. // do nothing
  865. this._quadDirty = true;
  866. },
  867. /**
  868. * Sets opacity of the sprite
  869. * @function
  870. * @param {Number} opacity
  871. */
  872. setOpacity:null,
  873. /**
  874. * Sets color of the sprite
  875. * @function
  876. * @param {cc.Color} color3
  877. */
  878. setColor: null,
  879. /**
  880. * Updates the display color
  881. * @function
  882. */
  883. updateDisplayedColor: null,
  884. // Frames
  885. /**
  886. * Sets a new sprite frame to the sprite.
  887. * @function
  888. * @param {cc.SpriteFrame|String} newFrame
  889. */
  890. setSpriteFrame: null,
  891. /**
  892. * Sets a new display frame to the sprite.
  893. * @param {cc.SpriteFrame|String} newFrame
  894. * @deprecated
  895. */
  896. setDisplayFrame: function(newFrame){
  897. cc.log(cc._LogInfos.Sprite_setDisplayFrame);
  898. this.setSpriteFrame(newFrame);
  899. },
  900. /**
  901. * Returns whether or not a cc.SpriteFrame is being displayed
  902. * @function
  903. * @param {cc.SpriteFrame} frame
  904. * @return {Boolean}
  905. */
  906. isFrameDisplayed: null,
  907. /**
  908. * Returns the current displayed frame.
  909. * @return {cc.SpriteFrame}
  910. */
  911. displayFrame: function () {
  912. return cc.SpriteFrame.create(this._texture,
  913. cc.rectPointsToPixels(this._rect),
  914. this._rectRotated,
  915. cc.pointPointsToPixels(this._unflippedOffsetPositionFromCenter),
  916. cc.sizePointsToPixels(this._contentSize));
  917. },
  918. /**
  919. * Sets the batch node to sprite
  920. * @function
  921. * @param {cc.SpriteBatchNode|null} spriteBatchNode
  922. * @example
  923. * var batch = cc.SpriteBatchNode.create("Images/grossini_dance_atlas.png", 15);
  924. * var sprite = cc.Sprite.create(batch.texture, cc.rect(0, 0, 57, 57));
  925. * batch.addChild(sprite);
  926. * layer.addChild(batch);
  927. */
  928. setBatchNode:null,
  929. // CCTextureProtocol
  930. /**
  931. * Sets the texture of sprite
  932. * @function
  933. * @param {cc.Texture2D|String} texture
  934. */
  935. setTexture: null,
  936. // Texture protocol
  937. _updateBlendFunc:function () {
  938. if(this._batchNode){
  939. cc.log(cc._LogInfos.Sprite__updateBlendFunc);
  940. return;
  941. }
  942. // it's possible to have an untextured sprite
  943. if (!this._texture || !this._texture.hasPremultipliedAlpha()) {
  944. this._blendFunc.src = cc.SRC_ALPHA;
  945. this._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
  946. this.opacityModifyRGB = false;
  947. } else {
  948. this._blendFunc.src = cc.BLEND_SRC;
  949. this._blendFunc.dst = cc.BLEND_DST;
  950. this.opacityModifyRGB = true;
  951. }
  952. },
  953. _changeTextureColor: function () {
  954. var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect();
  955. if (locTexture && locRect.validRect && this._originalTexture) {
  956. locElement = locTexture.getHtmlElementObj();
  957. if (!locElement)
  958. return;
  959. this._colorized = true;
  960. if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor
  961. && this._originalTexture._htmlElementObj != locElement)
  962. cc.generateTintImageWithMultiply(this._originalTexture._htmlElementObj, this._displayedColor, locRect, locElement);
  963. else {
  964. locElement = cc.generateTintImageWithMultiply(this._originalTexture._htmlElementObj, this._displayedColor, locRect);
  965. locTexture = new cc.Texture2D();
  966. locTexture.initWithElement(locElement);
  967. locTexture.handleLoadedTexture();
  968. this.texture = locTexture;
  969. }
  970. }
  971. },
  972. _setTextureCoords:function (rect) {
  973. rect = cc.rectPointsToPixels(rect);
  974. var tex = this._batchNode ? this.textureAtlas.texture : this._texture;
  975. if (!tex)
  976. return;
  977. var atlasWidth = tex.pixelsWidth;
  978. var atlasHeight = tex.pixelsHeight;
  979. var left, right, top, bottom, tempSwap, locQuad = this._quad;
  980. if (this._rectRotated) {
  981. if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
  982. left = (2 * rect.x + 1) / (2 * atlasWidth);
  983. right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
  984. top = (2 * rect.y + 1) / (2 * atlasHeight);
  985. bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
  986. } else {
  987. left = rect.x / atlasWidth;
  988. right = (rect.x + rect.height) / atlasWidth;
  989. top = rect.y / atlasHeight;
  990. bottom = (rect.y + rect.width) / atlasHeight;
  991. }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
  992. if (this._flippedX) {
  993. tempSwap = top;
  994. top = bottom;
  995. bottom = tempSwap;
  996. }
  997. if (this._flippedY) {
  998. tempSwap = left;
  999. left = right;
  1000. right = tempSwap;
  1001. }
  1002. locQuad.bl.texCoords.u = left;
  1003. locQuad.bl.texCoords.v = top;
  1004. locQuad.br.texCoords.u = left;
  1005. locQuad.br.texCoords.v = bottom;
  1006. locQuad.tl.texCoords.u = right;
  1007. locQuad.tl.texCoords.v = top;
  1008. locQuad.tr.texCoords.u = right;
  1009. locQuad.tr.texCoords.v = bottom;
  1010. } else {
  1011. if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
  1012. left = (2 * rect.x + 1) / (2 * atlasWidth);
  1013. right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
  1014. top = (2 * rect.y + 1) / (2 * atlasHeight);
  1015. bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
  1016. } else {
  1017. left = rect.x / atlasWidth;
  1018. right = (rect.x + rect.width) / atlasWidth;
  1019. top = rect.y / atlasHeight;
  1020. bottom = (rect.y + rect.height) / atlasHeight;
  1021. } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
  1022. if (this._flippedX) {
  1023. tempSwap = left;
  1024. left = right;
  1025. right = tempSwap;
  1026. }
  1027. if (this._flippedY) {
  1028. tempSwap = top;
  1029. top = bottom;
  1030. bottom = tempSwap;
  1031. }
  1032. locQuad.bl.texCoords.u = left;
  1033. locQuad.bl.texCoords.v = bottom;
  1034. locQuad.br.texCoords.u = right;
  1035. locQuad.br.texCoords.v = bottom;
  1036. locQuad.tl.texCoords.u = left;
  1037. locQuad.tl.texCoords.v = top;
  1038. locQuad.tr.texCoords.u = right;
  1039. locQuad.tr.texCoords.v = top;
  1040. }
  1041. this._quadDirty = true;
  1042. },
  1043. /**
  1044. * draw sprite to canvas
  1045. * @function
  1046. */
  1047. draw: null
  1048. });
  1049. /**
  1050. * Create a sprite with image path or frame name or texture or spriteFrame.
  1051. * @deprecated since v3.0, please use new construction instead
  1052. * @see cc.Sprite
  1053. * @param {String|cc.SpriteFrame|HTMLImageElement|cc.Texture2D} fileName The string which indicates a path to image file, e.g., "scene1/monster.png".
  1054. * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite.
  1055. * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
  1056. * @return {cc.Sprite} A valid sprite object
  1057. */
  1058. cc.Sprite.create = function (fileName, rect, rotated) {
  1059. return new cc.Sprite(fileName, rect, rotated);
  1060. };
  1061. /**
  1062. * @deprecated since v3.0, please use new construction instead
  1063. * @see cc.Sprite
  1064. * @function
  1065. */
  1066. cc.Sprite.createWithTexture = cc.Sprite.create;
  1067. /**
  1068. * @deprecated since v3.0, please use new construction instead
  1069. * @see cc.Sprite
  1070. * @function
  1071. */
  1072. cc.Sprite.createWithSpriteFrameName = cc.Sprite.create;
  1073. /**
  1074. * @deprecated since v3.0, please use new construction instead
  1075. * @see cc.Sprite
  1076. * @function
  1077. */
  1078. cc.Sprite.createWithSpriteFrame = cc.Sprite.create;
  1079. /**
  1080. * cc.Sprite invalid index on the cc.SpriteBatchNode
  1081. * @constant
  1082. * @type {Number}
  1083. */
  1084. cc.Sprite.INDEX_NOT_INITIALIZED = -1;
  1085. if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
  1086. var _p = cc.Sprite.prototype;
  1087. _p._spriteFrameLoadedCallback = function(spriteFrame){
  1088. var _t = this;
  1089. _t.setNodeDirty(true);
  1090. _t.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize());
  1091. var curColor = _t.color;
  1092. if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255)
  1093. _t._changeTextureColor();
  1094. _t._callLoadedEventCallbacks();
  1095. };
  1096. _p.setOpacityModifyRGB = function (modify) {
  1097. if (this._opacityModifyRGB !== modify) {
  1098. this._opacityModifyRGB = modify;
  1099. this.setNodeDirty(true);
  1100. }
  1101. };
  1102. _p.updateDisplayedOpacity = function (parentOpacity) {
  1103. cc.Node.prototype.updateDisplayedOpacity.call(this, parentOpacity);
  1104. this._setNodeDirtyForCache();
  1105. };
  1106. _p.ctor = function (fileName, rect, rotated) {
  1107. var self = this;
  1108. cc.Node.prototype.ctor.call(self);
  1109. self._shouldBeHidden = false;
  1110. self._offsetPosition = cc.p(0, 0);
  1111. self._unflippedOffsetPositionFromCenter = cc.p(0, 0);
  1112. self._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
  1113. self._rect = cc.rect(0, 0, 0, 0);
  1114. self._newTextureWhenChangeColor = false;
  1115. self._textureLoaded = true;
  1116. self._textureRect_Canvas = {x: 0, y: 0, width: 0, height:0, validRect: false};
  1117. self._drawSize_Canvas = cc.size(0, 0);
  1118. self._softInit(fileName, rect, rotated);
  1119. };
  1120. _p.setBlendFunc = function (src, dst) {
  1121. var _t = this, locBlendFunc = this._blendFunc;
  1122. if (dst === undefined) {
  1123. locBlendFunc.src = src.src;
  1124. locBlendFunc.dst = src.dst;
  1125. } else {
  1126. locBlendFunc.src = src;
  1127. locBlendFunc.dst = dst;
  1128. }
  1129. if (cc._renderType === cc._RENDER_TYPE_CANVAS)
  1130. _t._blendFuncStr = cc._getCompositeOperationByBlendFunc(locBlendFunc);
  1131. };
  1132. _p.init = function () {
  1133. var _t = this;
  1134. if (arguments.length > 0)
  1135. return _t.initWithFile(arguments[0], arguments[1]);
  1136. cc.Node.prototype.init.call(_t);
  1137. _t.dirty = _t._recursiveDirty = false;
  1138. _t._opacityModifyRGB = true;
  1139. _t._blendFunc.src = cc.BLEND_SRC;
  1140. _t._blendFunc.dst = cc.BLEND_DST;
  1141. // update texture (calls _updateBlendFunc)
  1142. _t.texture = null;
  1143. _t._textureLoaded = true;
  1144. _t._flippedX = _t._flippedY = false;
  1145. // default transform anchor: center
  1146. _t.anchorX = 0.5;
  1147. _t.anchorY = 0.5;
  1148. // zwoptex default values
  1149. _t._offsetPosition.x = 0;
  1150. _t._offsetPosition.y = 0;
  1151. _t._hasChildren = false;
  1152. // updated in "useSelfRender"
  1153. // Atlas: TexCoords
  1154. _t.setTextureRect(cc.rect(0, 0, 0, 0), false, cc.size(0, 0));
  1155. return true;
  1156. };
  1157. _p.initWithTexture = function (texture, rect, rotated) {
  1158. var _t = this;
  1159. cc.assert(arguments.length != 0, cc._LogInfos.CCSpriteBatchNode_initWithTexture);
  1160. rotated = rotated || false;
  1161. if (rotated && texture.isLoaded()) {
  1162. var tempElement = texture.getHtmlElementObj();
  1163. tempElement = cc.cutRotateImageToCanvas(tempElement, rect);
  1164. var tempTexture = new cc.Texture2D();
  1165. tempTexture.initWithElement(tempElement);
  1166. tempTexture.handleLoadedTexture();
  1167. texture = tempTexture;
  1168. _t._rect = cc.rect(0, 0, rect.width, rect.height);
  1169. }
  1170. if (!cc.Node.prototype.init.call(_t))
  1171. return false;
  1172. _t._batchNode = null;
  1173. _t._recursiveDirty = false;
  1174. _t.dirty = false;
  1175. _t._opacityModifyRGB = true;
  1176. _t._blendFunc.src = cc.BLEND_SRC;
  1177. _t._blendFunc.dst = cc.BLEND_DST;
  1178. _t._flippedX = _t._flippedY = false;
  1179. // default transform anchor: center
  1180. _t.anchorX = 0.5;
  1181. _t.anchorY = 0.5;
  1182. // zwoptex default values
  1183. _t._offsetPosition.x = 0;
  1184. _t._offsetPosition.y = 0;
  1185. _t._hasChildren = false;
  1186. var locTextureLoaded = texture.isLoaded();
  1187. _t._textureLoaded = locTextureLoaded;
  1188. if (!locTextureLoaded) {
  1189. _t._rectRotated = rotated;
  1190. if (rect) {
  1191. _t._rect.x = rect.x;
  1192. _t._rect.y = rect.y;
  1193. _t._rect.width = rect.width;
  1194. _t._rect.height = rect.height;
  1195. }
  1196. if(_t.texture)
  1197. _t.texture.removeLoadedEventListener(_t);
  1198. texture.addLoadedEventListener(_t._textureLoadedCallback, _t);
  1199. _t.texture = texture;
  1200. return true;
  1201. }
  1202. if (!rect) {
  1203. rect = cc.rect(0, 0, texture.width, texture.height);
  1204. }
  1205. if(texture && texture.url) {
  1206. var _x = rect.x + rect.width, _y = rect.y + rect.height;
  1207. if(_x > texture.width){
  1208. cc.error(cc._LogInfos.RectWidth, texture.url);
  1209. }
  1210. if(_y > texture.height){
  1211. cc.error(cc._LogInfos.RectHeight, texture.url);
  1212. }
  1213. }
  1214. _t._originalTexture = texture;
  1215. _t.texture = texture;
  1216. _t.setTextureRect(rect, rotated);
  1217. // by default use "Self Render".
  1218. // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
  1219. _t.batchNode = null;
  1220. return true;
  1221. };
  1222. _p._textureLoadedCallback = function (sender) {
  1223. var _t = this;
  1224. if(_t._textureLoaded)
  1225. return;
  1226. _t._textureLoaded = true;
  1227. var locRect = _t._rect;
  1228. if (!locRect) {
  1229. locRect = cc.rect(0, 0, sender.width, sender.height);
  1230. } else if (cc._rectEqualToZero(locRect)) {
  1231. locRect.width = sender.width;
  1232. locRect.height = sender.height;
  1233. }
  1234. _t._originalTexture = sender;
  1235. _t.texture = sender;
  1236. _t.setTextureRect(locRect, _t._rectRotated);
  1237. //set the texture's color after the it loaded
  1238. var locColor = this._displayedColor;
  1239. if(locColor.r != 255 || locColor.g != 255 || locColor.b != 255)
  1240. _t._changeTextureColor();
  1241. // by default use "Self Render".
  1242. // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
  1243. _t.batchNode = _t._batchNode;
  1244. _t._callLoadedEventCallbacks();
  1245. };
  1246. _p.setTextureRect = function (rect, rotated, untrimmedSize) {
  1247. var _t = this;
  1248. _t._rectRotated = rotated || false;
  1249. _t.setContentSize(untrimmedSize || rect);
  1250. _t.setVertexRect(rect);
  1251. var locTextureRect = _t._textureRect_Canvas, scaleFactor = cc.contentScaleFactor();
  1252. locTextureRect.x = 0 | (rect.x * scaleFactor);
  1253. locTextureRect.y = 0 | (rect.y * scaleFactor);
  1254. locTextureRect.width = 0 | (rect.width * scaleFactor);
  1255. locTextureRect.height = 0 | (rect.height * scaleFactor);
  1256. locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0 || locTextureRect.x < 0 || locTextureRect.y < 0);
  1257. var relativeOffset = _t._unflippedOffsetPositionFromCenter;
  1258. if (_t._flippedX)
  1259. relativeOffset.x = -relativeOffset.x;
  1260. if (_t._flippedY)
  1261. relativeOffset.y = -relativeOffset.y;
  1262. _t._offsetPosition.x = relativeOffset.x + (_t._contentSize.width - _t._rect.width) / 2;
  1263. _t._offsetPosition.y = relativeOffset.y + (_t._contentSize.height - _t._rect.height) / 2;
  1264. // rendering using batch node
  1265. if (_t._batchNode) {
  1266. // update dirty, don't update _recursiveDirty
  1267. _t.dirty = true;
  1268. }
  1269. };
  1270. _p.updateTransform = function () {
  1271. var _t = this;
  1272. //cc.assert(_t._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode");
  1273. // recaculate matrix only if it is dirty
  1274. if (_t.dirty) {
  1275. // If it is not visible, or one of its ancestors is not visible, then do nothing:
  1276. var locParent = _t._parent;
  1277. if (!_t._visible || ( locParent && locParent != _t._batchNode && locParent._shouldBeHidden)) {
  1278. _t._shouldBeHidden = true;
  1279. } else {
  1280. _t._shouldBeHidden = false;
  1281. if (!locParent || locParent == _t._batchNode) {
  1282. _t._transformToBatch = _t.nodeToParentTransform();
  1283. } else {
  1284. //cc.assert(_t._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite");
  1285. _t._transformToBatch = cc.affineTransformConcat(_t.nodeToParentTransform(), locParent._transformToBatch);
  1286. }
  1287. }
  1288. _t._recursiveDirty = false;
  1289. _t.dirty = false;
  1290. }
  1291. // recursively iterate over children
  1292. if (_t._hasChildren)
  1293. _t._arrayMakeObjectsPerformSelector(_t._children, cc.Node._StateCallbackType.updateTransform);
  1294. };
  1295. _p.addChild = function (child, localZOrder, tag) {
  1296. cc.assert(child, cc._LogInfos.CCSpriteBatchNode_addChild_2);
  1297. if (localZOrder == null)
  1298. localZOrder = child._localZOrder;
  1299. if (tag == null)
  1300. tag = child.tag;
  1301. //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check
  1302. cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
  1303. this._hasChildren = true;
  1304. };
  1305. _p.setOpacity = function (opacity) {
  1306. cc.Node.prototype.setOpacity.call(this, opacity);
  1307. this._setNodeDirtyForCache();
  1308. };
  1309. _p.setColor = function (color3) {
  1310. var _t = this;
  1311. var curColor = _t.color;
  1312. this._oldDisplayColor = curColor;
  1313. if ((curColor.r === color3.r) && (curColor.g === color3.g) && (curColor.b === color3.b))
  1314. return;
  1315. cc.Node.prototype.setColor.call(_t, color3);
  1316. };
  1317. _p.updateDisplayedColor = function (parentColor) {
  1318. var _t = this;
  1319. cc.Node.prototype.updateDisplayedColor.call(_t, parentColor);
  1320. var oColor = _t._oldDisplayColor;
  1321. var nColor = _t._displayedColor;
  1322. if (oColor.r === nColor.r && oColor.g === nColor.g && oColor.b === nColor.b)
  1323. return;
  1324. _t._changeTextureColor();
  1325. _t._setNodeDirtyForCache();
  1326. };
  1327. _p.setSpriteFrame = function (newFrame) {
  1328. var _t = this;
  1329. if(typeof(newFrame) == "string"){
  1330. newFrame = cc.spriteFrameCache.getSpriteFrame(newFrame);
  1331. cc.assert(newFrame, cc._LogInfos.CCSpriteBatchNode_setSpriteFrame)
  1332. }
  1333. _t.setNodeDirty(true);
  1334. var frameOffset = newFrame.getOffset();
  1335. _t._unflippedOffsetPositionFromCenter.x = frameOffset.x;
  1336. _t._unflippedOffsetPositionFromCenter.y = frameOffset.y;
  1337. // update rect
  1338. _t._rectRotated = newFrame.isRotated();
  1339. var pNewTexture = newFrame.getTexture();
  1340. var locTextureLoaded = newFrame.textureLoaded();
  1341. if (!locTextureLoaded) {
  1342. _t._textureLoaded = false;
  1343. newFrame.addLoadedEventListener(function (sender) {
  1344. _t._textureLoaded = true;
  1345. var locNewTexture = sender.getTexture();
  1346. if (locNewTexture != _t._texture)
  1347. _t.texture = locNewTexture;
  1348. _t.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize());
  1349. _t._callLoadedEventCallbacks();
  1350. }, _t);
  1351. }
  1352. // update texture before updating texture rect
  1353. if (pNewTexture != _t._texture)
  1354. _t.texture = pNewTexture;
  1355. if (_t._rectRotated)
  1356. _t._originalTexture = pNewTexture;
  1357. _t.setTextureRect(newFrame.getRect(), _t._rectRotated, newFrame.getOriginalSize());
  1358. _t._colorized = false;
  1359. if (locTextureLoaded) {
  1360. var curColor = _t.color;
  1361. if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255)
  1362. _t._changeTextureColor();
  1363. }
  1364. };
  1365. _p.isFrameDisplayed = function (frame) {
  1366. if (frame.getTexture() != this._texture)
  1367. return false;
  1368. return cc.rectEqualToRect(frame.getRect(), this._rect);
  1369. };
  1370. _p.setBatchNode = function (spriteBatchNode) {
  1371. var _t = this;
  1372. _t._batchNode = spriteBatchNode; // weak reference
  1373. // self render
  1374. if (!_t._batchNode) {
  1375. _t.atlasIndex = cc.Sprite.INDEX_NOT_INITIALIZED;
  1376. _t.textureAtlas = null;
  1377. _t._recursiveDirty = false;
  1378. _t.dirty = false;
  1379. } else {
  1380. // using batch
  1381. _t._transformToBatch = cc.affineTransformIdentity();
  1382. _t.textureAtlas = _t._batchNode.textureAtlas; // weak ref
  1383. }
  1384. };
  1385. _p.setTexture = function (texture) {
  1386. var _t = this;
  1387. if(texture && (typeof(texture) === "string")){
  1388. texture = cc.textureCache.addImage(texture);
  1389. _t.setTexture(texture);
  1390. //TODO
  1391. var size = texture.getContentSize();
  1392. _t.setTextureRect(cc.rect(0,0, size.width, size.height));
  1393. return;
  1394. }
  1395. // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet
  1396. cc.assert(!texture || texture instanceof cc.Texture2D, cc._LogInfos.CCSpriteBatchNode_setTexture);
  1397. if (_t._texture != texture) {
  1398. if (texture && texture.getHtmlElementObj() instanceof HTMLImageElement) {
  1399. _t._originalTexture = texture;
  1400. }
  1401. _t._texture = texture;
  1402. }
  1403. };
  1404. _p.draw = function (ctx) {
  1405. var _t = this;
  1406. if (!_t._textureLoaded)
  1407. return;
  1408. var context = ctx || cc._renderContext;
  1409. if (_t._blendFuncStr != "source")
  1410. context.globalCompositeOperation = _t._blendFuncStr;
  1411. var locEGL_ScaleX = cc.view.getScaleX(), locEGL_ScaleY = cc.view.getScaleY();
  1412. context.globalAlpha = _t._displayedOpacity / 255;
  1413. var locRect = _t._rect, locContentSize = _t._contentSize, locOffsetPosition = _t._offsetPosition, locDrawSizeCanvas = _t._drawSize_Canvas;
  1414. var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = _t._textureRect_Canvas;
  1415. locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX;
  1416. locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY;
  1417. if (_t._flippedX || _t._flippedY) {
  1418. context.save();
  1419. if (_t._flippedX) {
  1420. flipXOffset = -locOffsetPosition.x - locRect.width;
  1421. context.scale(-1, 1);
  1422. }
  1423. if (_t._flippedY) {
  1424. flipYOffset = locOffsetPosition.y;
  1425. context.scale(1, -1);
  1426. }
  1427. }
  1428. flipXOffset *= locEGL_ScaleX;
  1429. flipYOffset *= locEGL_ScaleY;
  1430. if (_t._texture && locTextureCoord.validRect) {
  1431. var image = _t._texture.getHtmlElementObj();
  1432. if (_t._colorized) {
  1433. context.drawImage(image,
  1434. 0, 0, locTextureCoord.width, locTextureCoord.height,
  1435. flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height);
  1436. } else {
  1437. context.drawImage(image,
  1438. locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height,
  1439. flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height);
  1440. }
  1441. } else if (!_t._texture && locTextureCoord.validRect) {
  1442. var curColor = _t.color;
  1443. context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)";
  1444. context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY);
  1445. }
  1446. if (cc.SPRITE_DEBUG_DRAW === 1 || _t._showNode) {
  1447. // draw bounding box
  1448. context.strokeStyle = "rgba(0,255,0,1)";
  1449. flipXOffset /= locEGL_ScaleX;
  1450. flipYOffset /= locEGL_ScaleY;
  1451. flipYOffset = -flipYOffset;
  1452. var vertices1 = [cc.p(flipXOffset, flipYOffset),
  1453. cc.p(flipXOffset + locRect.width, flipYOffset),
  1454. cc.p(flipXOffset + locRect.width, flipYOffset - locRect.height),
  1455. cc.p(flipXOffset, flipYOffset - locRect.height)];
  1456. cc._drawingUtil.drawPoly(vertices1, 4, true);
  1457. } else if (cc.SPRITE_DEBUG_DRAW === 2) {
  1458. // draw texture box
  1459. context.strokeStyle = "rgba(0,255,0,1)";
  1460. var drawRect = _t._rect;
  1461. flipYOffset = -flipYOffset;
  1462. var vertices2 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + drawRect.width, flipYOffset),
  1463. cc.p(flipXOffset + drawRect.width, flipYOffset - drawRect.height), cc.p(flipXOffset, flipYOffset - drawRect.height)];
  1464. cc._drawingUtil.drawPoly(vertices2, 4, true);
  1465. }
  1466. if (_t._flippedX || _t._flippedY)
  1467. context.restore();
  1468. cc.g_NumberOfDraws++;
  1469. };
  1470. if(!cc.sys._supportCanvasNewBlendModes)
  1471. _p._changeTextureColor = function () {
  1472. var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect();
  1473. if (locTexture && locRect.validRect && this._originalTexture) {
  1474. locElement = locTexture.getHtmlElementObj();
  1475. if (!locElement)
  1476. return;
  1477. var cacheTextureForColor = cc.textureCache.getTextureColors(this._originalTexture.getHtmlElementObj());
  1478. if (cacheTextureForColor) {
  1479. this._colorized = true;
  1480. //generate color texture cache
  1481. if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor)
  1482. cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement);
  1483. else {
  1484. locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect);
  1485. locTexture = new cc.Texture2D();
  1486. locTexture.initWithElement(locElement);
  1487. locTexture.handleLoadedTexture();
  1488. this.texture = locTexture;
  1489. }
  1490. }
  1491. }
  1492. };
  1493. delete _p;
  1494. } else {
  1495. cc.assert(typeof cc._tmp.WebGLSprite === "function", cc._LogInfos.MissingFile, "SpritesWebGL.js");
  1496. cc._tmp.WebGLSprite();
  1497. delete cc._tmp.WebGLSprite;
  1498. }
  1499. cc.assert(typeof cc._tmp.PrototypeSprite === "function", cc._LogInfos.MissingFile, "SpritesPropertyDefine.js");
  1500. cc._tmp.PrototypeSprite();
  1501. delete cc._tmp.PrototypeSprite;