1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p>A class that implements a Texture Atlas. <br /> 29 * Supported features: <br /> 30 * The atlas file can be a PNG, JPG. <br /> 31 * Quads can be updated in runtime <br /> 32 * Quads can be added in runtime <br /> 33 * Quads can be removed in runtime <br /> 34 * Quads can be re-ordered in runtime <br /> 35 * The TextureAtlas capacity can be increased or decreased in runtime.</p> 36 * @class 37 * @extends cc.Class 38 * 39 * @property {Boolean} dirty - Indicates whether or not the array buffer of the VBO needs to be updated. 40 * @property {Image} texture - Image texture for cc.TextureAtlas. 41 * @property {Number} capacity - <@readonly> Quantity of quads that can be stored with the current texture atlas size. 42 * @property {Number} totalQuads - <@readonly> Quantity of quads that are going to be drawn. 43 * @property {Array} quads - <@readonly> Quads that are going to be rendered 44 */ 45 cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ 46 dirty: false, 47 texture: null, 48 49 _indices: null, 50 //0: vertex 1: indices 51 _buffersVBO: null, 52 _capacity: 0, 53 54 _quads: null, 55 _quadsArrayBuffer: null, 56 _quadsWebBuffer: null, 57 _quadsReader: null, 58 59 /** 60 * <p>Creates a TextureAtlas with an filename and with an initial capacity for Quads. <br /> 61 * The TextureAtlas capacity can be increased in runtime. </p> 62 * Constructor of cc.TextureAtlas 63 * @param {String|cc.Texture2D} fileName 64 * @param {Number} capacity 65 * @example 66 * 1. 67 * //creates a TextureAtlas with filename 68 * var textureAtlas = new cc.TextureAtlas("res/hello.png", 3); 69 * 2. 70 * //creates a TextureAtlas with texture 71 * var texture = cc.textureCache.addImage("hello.png"); 72 * var textureAtlas = new cc.TextureAtlas(texture, 3); 73 */ 74 ctor: function (fileName, capacity) { 75 this._buffersVBO = []; 76 77 if (typeof(fileName) == "string") { 78 this.initWithFile(fileName, capacity); 79 } 80 else if (fileName instanceof cc.Texture2D) { 81 this.initWithTexture(fileName, capacity); 82 } 83 }, 84 85 /** 86 * Quantity of quads that are going to be drawn. 87 * @return {Number} 88 */ 89 getTotalQuads: function () { 90 //return this._quads.length; 91 return this._totalQuads; 92 }, 93 94 /** 95 * Quantity of quads that can be stored with the current texture atlas size 96 * @return {Number} 97 */ 98 getCapacity: function () { 99 return this._capacity; 100 }, 101 102 /** 103 * Texture of the texture atlas 104 * @return {Image} 105 */ 106 getTexture: function () { 107 return this.texture; 108 }, 109 110 /** 111 * @param {Image} texture 112 */ 113 setTexture: function (texture) { 114 this.texture = texture; 115 }, 116 117 /** 118 * specify if the array buffer of the VBO needs to be updated 119 * @param {Boolean} dirty 120 */ 121 setDirty: function (dirty) { 122 this.dirty = dirty; 123 }, 124 125 /** 126 * whether or not the array buffer of the VBO needs to be updated 127 * @returns {boolean} 128 */ 129 isDirty: function () { 130 return this.dirty; 131 }, 132 133 /** 134 * Quads that are going to be rendered 135 * @return {Array} 136 */ 137 getQuads: function () { 138 return this._quads; 139 }, 140 141 /** 142 * @param {Array} quads 143 */ 144 setQuads: function (quads) { 145 this._quads = quads; 146 //TODO need re-binding 147 }, 148 149 _copyQuadsToTextureAtlas: function (quads, index) { 150 if (!quads) 151 return; 152 153 for (var i = 0; i < quads.length; i++) 154 this._setQuadToArray(quads[i], index + i); 155 }, 156 157 _setQuadToArray: function (quad, index) { 158 var locQuads = this._quads; 159 if (!locQuads[index]) { 160 locQuads[index] = new cc.V3F_C4B_T2F_Quad(quad.tl, quad.bl, quad.tr, quad.br, this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT); 161 return; 162 } 163 locQuads[index].bl = quad.bl; 164 locQuads[index].br = quad.br; 165 locQuads[index].tl = quad.tl; 166 locQuads[index].tr = quad.tr; 167 }, 168 169 /** 170 * Description 171 * @return {String} 172 */ 173 description: function () { 174 return '<cc.TextureAtlas | totalQuads =' + this._totalQuads + '>'; 175 }, 176 177 _setupIndices: function () { 178 if (this._capacity === 0) 179 return; 180 var locIndices = this._indices, locCapacity = this._capacity; 181 for (var i = 0; i < locCapacity; i++) { 182 if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP) { 183 locIndices[i * 6 + 0] = i * 4 + 0; 184 locIndices[i * 6 + 1] = i * 4 + 0; 185 locIndices[i * 6 + 2] = i * 4 + 2; 186 locIndices[i * 6 + 3] = i * 4 + 1; 187 locIndices[i * 6 + 4] = i * 4 + 3; 188 locIndices[i * 6 + 5] = i * 4 + 3; 189 } else { 190 locIndices[i * 6 + 0] = i * 4 + 0; 191 locIndices[i * 6 + 1] = i * 4 + 1; 192 locIndices[i * 6 + 2] = i * 4 + 2; 193 194 // inverted index. issue #179 195 locIndices[i * 6 + 3] = i * 4 + 3; 196 locIndices[i * 6 + 4] = i * 4 + 2; 197 locIndices[i * 6 + 5] = i * 4 + 1; 198 } 199 } 200 }, 201 202 _setupVBO: function () { 203 var gl = cc._renderContext; 204 //create WebGLBuffer 205 this._buffersVBO[0] = gl.createBuffer(); 206 this._buffersVBO[1] = gl.createBuffer(); 207 208 this._quadsWebBuffer = gl.createBuffer(); 209 this._mapBuffers(); 210 }, 211 212 _mapBuffers: function () { 213 var gl = cc._renderContext; 214 215 gl.bindBuffer(gl.ARRAY_BUFFER, this._quadsWebBuffer); 216 gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW); 217 218 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); 219 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW); 220 }, 221 222 /** 223 * <p>Initializes a TextureAtlas with a filename and with a certain capacity for Quads.<br /> 224 * The TextureAtlas capacity can be increased in runtime.<br /> 225 * WARNING: Do not reinitialize the TextureAtlas because it will leak memory. </p> 226 * @param {String} file 227 * @param {Number} capacity 228 * @return {Boolean} 229 * @example 230 * //example 231 * var textureAtlas = new cc.TextureAtlas(); 232 * textureAtlas.initWithTexture("hello.png", 3); 233 */ 234 initWithFile: function (file, capacity) { 235 // retained in property 236 var texture = cc.textureCache.addImage(file); 237 if (texture) 238 return this.initWithTexture(texture, capacity); 239 else { 240 cc.log(cc._LogInfos.TextureAtlas_initWithFile, file); 241 return false; 242 } 243 }, 244 245 /** 246 * <p>Initializes a TextureAtlas with a previously initialized Texture2D object, and<br /> 247 * with an initial capacity for Quads.<br /> 248 * The TextureAtlas capacity can be increased in runtime.<br /> 249 * WARNING: Do not reinitialize the TextureAtlas because it will leak memory</p> 250 * @param {Image} texture 251 * @param {Number} capacity 252 * @return {Boolean} 253 * @example 254 * //example 255 * var texture = cc.textureCache.addImage("hello.png"); 256 * var textureAtlas = new cc.TextureAtlas(); 257 * textureAtlas.initWithTexture(texture, 3); 258 */ 259 initWithTexture: function (texture, capacity) { 260 261 cc.assert(texture, cc._LogInfos.TextureAtlas_initWithTexture); 262 263 capacity = 0 | (capacity); 264 this._capacity = capacity; 265 this._totalQuads = 0; 266 267 // retained in property 268 this.texture = texture; 269 270 // Re-initialization is not allowed 271 this._quads = []; 272 this._indices = new Uint16Array(capacity * 6); 273 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 274 this._quadsArrayBuffer = new ArrayBuffer(quadSize * capacity); 275 this._quadsReader = new Uint8Array(this._quadsArrayBuffer); 276 277 if (!( this._quads && this._indices) && capacity > 0) 278 return false; 279 280 var locQuads = this._quads; 281 for (var i = 0; i < capacity; i++) 282 locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize); 283 284 this._setupIndices(); 285 this._setupVBO(); 286 this.dirty = true; 287 return true; 288 }, 289 290 /** 291 * <p>Updates a Quad (texture, vertex and color) at a certain index <br /> 292 * index must be between 0 and the atlas capacity - 1 </p> 293 * @param {cc.V3F_C4B_T2F_Quad} quad 294 * @param {Number} index 295 */ 296 updateQuad: function (quad, index) { 297 298 cc.assert(quad, cc._LogInfos.TextureAtlas_updateQuad); 299 300 cc.assert(index >= 0 && index < this._capacity, cc._LogInfos.TextureAtlas_updateQuad_2); 301 302 this._totalQuads = Math.max(index + 1, this._totalQuads); 303 this._setQuadToArray(quad, index); 304 this.dirty = true; 305 }, 306 307 /** 308 * <p>Inserts a Quad (texture, vertex and color) at a certain index<br /> 309 * index must be between 0 and the atlas capacity - 1 </p> 310 * @param {cc.V3F_C4B_T2F_Quad} quad 311 * @param {Number} index 312 */ 313 insertQuad: function (quad, index) { 314 315 cc.assert(index < this._capacity, cc._LogInfos.TextureAtlas_insertQuad_2); 316 317 this._totalQuads++; 318 if (this._totalQuads > this._capacity) { 319 cc.log(cc._LogInfos.TextureAtlas_insertQuad); 320 return; 321 } 322 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 323 // issue #575. index can be > totalQuads 324 var remaining = (this._totalQuads - 1) - index; 325 var startOffset = index * quadSize; 326 var moveLength = remaining * quadSize; 327 this._quads[this._totalQuads - 1] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize); 328 this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize); 329 330 this._setQuadToArray(quad, index); 331 this.dirty = true; 332 }, 333 334 /** 335 * <p> 336 * Inserts a c array of quads at a given index <br /> 337 * index must be between 0 and the atlas capacity - 1 <br /> 338 * this method doesn't enlarge the array when amount + index > totalQuads <br /> 339 * </p> 340 * @param {Array} quads 341 * @param {Number} index 342 * @param {Number} amount 343 */ 344 insertQuads: function (quads, index, amount) { 345 amount = amount || quads.length; 346 347 cc.assert((index + amount) <= this._capacity, cc._LogInfos.TextureAtlas_insertQuads); 348 349 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 350 this._totalQuads += amount; 351 if (this._totalQuads > this._capacity) { 352 cc.log(cc._LogInfos.TextureAtlas_insertQuad); 353 return; 354 } 355 356 // issue #575. index can be > totalQuads 357 var remaining = (this._totalQuads - 1) - index - amount; 358 var startOffset = index * quadSize; 359 var moveLength = remaining * quadSize; 360 var lastIndex = (this._totalQuads - 1) - amount; 361 362 var i; 363 for (i = 0; i < amount; i++) 364 this._quads[lastIndex + i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize); 365 this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize * amount); 366 for (i = 0; i < amount; i++) 367 this._setQuadToArray(quads[i], index + i); 368 369 this.dirty = true; 370 }, 371 372 /** 373 * <p>Removes the quad that is located at a certain index and inserts it at a new index <br /> 374 * This operation is faster than removing and inserting in a quad in 2 different steps</p> 375 * @param {Number} fromIndex 376 * @param {Number} newIndex 377 */ 378 insertQuadFromIndex: function (fromIndex, newIndex) { 379 if (fromIndex === newIndex) 380 return; 381 382 cc.assert(newIndex >= 0 || newIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex); 383 384 cc.assert(fromIndex >= 0 || fromIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex_2); 385 386 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 387 var locQuadsReader = this._quadsReader; 388 var sourceArr = locQuadsReader.subarray(fromIndex * quadSize, quadSize); 389 var startOffset, moveLength; 390 if (fromIndex > newIndex) { 391 startOffset = newIndex * quadSize; 392 moveLength = (fromIndex - newIndex) * quadSize; 393 locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize); 394 locQuadsReader.set(sourceArr, startOffset); 395 } else { 396 startOffset = (fromIndex + 1) * quadSize; 397 moveLength = (newIndex - fromIndex) * quadSize; 398 locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize); 399 locQuadsReader.set(sourceArr, newIndex * quadSize); 400 } 401 this.dirty = true; 402 }, 403 404 /** 405 * <p>Removes a quad at a given index number.<br /> 406 * The capacity remains the same, but the total number of quads to be drawn is reduced in 1 </p> 407 * @param {Number} index 408 */ 409 removeQuadAtIndex: function (index) { 410 411 cc.assert(index < this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadAtIndex); 412 413 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 414 this._totalQuads--; 415 this._quads.length = this._totalQuads; 416 if (index !== this._totalQuads) { 417 //move data 418 var startOffset = (index + 1) * quadSize; 419 var moveLength = (this._totalQuads - index) * quadSize; 420 this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize); 421 } 422 this.dirty = true; 423 }, 424 425 removeQuadsAtIndex: function (index, amount) { 426 427 cc.assert(index + amount <= this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadsAtIndex); 428 429 this._totalQuads -= amount; 430 431 if (index !== this._totalQuads) { 432 //move data 433 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 434 var srcOffset = (index + amount) * quadSize; 435 var moveLength = (this._totalQuads - index) * quadSize; 436 var dstOffset = index * quadSize; 437 this._quadsReader.set(this._quadsReader.subarray(srcOffset, srcOffset + moveLength), dstOffset); 438 } 439 this.dirty = true; 440 }, 441 442 /** 443 * <p>Removes all Quads. <br /> 444 * The TextureAtlas capacity remains untouched. No memory is freed.<br /> 445 * The total number of quads to be drawn will be 0</p> 446 */ 447 removeAllQuads: function () { 448 this._quads.length = 0; 449 this._totalQuads = 0; 450 }, 451 452 _setDirty: function (dirty) { 453 this.dirty = dirty; 454 }, 455 456 /** 457 * <p>Resize the capacity of the CCTextureAtlas.<br /> 458 * The new capacity can be lower or higher than the current one<br /> 459 * It returns YES if the resize was successful. <br /> 460 * If it fails to resize the capacity it will return NO with a new capacity of 0. <br /> 461 * no used for js</p> 462 * @param {Number} newCapacity 463 * @return {Boolean} 464 */ 465 resizeCapacity: function (newCapacity) { 466 if (newCapacity == this._capacity) 467 return true; 468 469 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 470 var oldCapacity = this._capacity; 471 // update capacity and totolQuads 472 this._totalQuads = Math.min(this._totalQuads, newCapacity); 473 this._capacity = 0 | newCapacity; 474 var i, capacity = this._capacity, locTotalQuads = this._totalQuads; 475 476 if (this._quads == null) { 477 this._quads = []; 478 this._quadsArrayBuffer = new ArrayBuffer(quadSize * capacity); 479 this._quadsReader = new Uint8Array(this._quadsArrayBuffer); 480 for (i = 0; i < capacity; i++) 481 this._quads = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize); 482 } else { 483 var newQuads, newArrayBuffer, quads = this._quads; 484 if (capacity > oldCapacity) { 485 newQuads = []; 486 newArrayBuffer = new ArrayBuffer(quadSize * capacity); 487 for (i = 0; i < locTotalQuads; i++) { 488 newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl, quads[i].bl, quads[i].tr, quads[i].br, 489 newArrayBuffer, i * quadSize); 490 } 491 for (; i < capacity; i++) 492 newQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, newArrayBuffer, i * quadSize); 493 494 this._quadsReader = new Uint8Array(newArrayBuffer); 495 this._quads = newQuads; 496 this._quadsArrayBuffer = newArrayBuffer; 497 } else { 498 var count = Math.max(locTotalQuads, capacity); 499 newQuads = []; 500 newArrayBuffer = new ArrayBuffer(quadSize * capacity); 501 for (i = 0; i < count; i++) { 502 newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl, quads[i].bl, quads[i].tr, quads[i].br, 503 newArrayBuffer, i * quadSize); 504 } 505 this._quadsReader = new Uint8Array(newArrayBuffer); 506 this._quads = newQuads; 507 this._quadsArrayBuffer = newArrayBuffer; 508 } 509 } 510 511 if (this._indices == null) { 512 this._indices = new Uint16Array(capacity * 6); 513 } else { 514 if (capacity > oldCapacity) { 515 var tempIndices = new Uint16Array(capacity * 6); 516 tempIndices.set(this._indices, 0); 517 this._indices = tempIndices; 518 } else { 519 this._indices = this._indices.subarray(0, capacity * 6); 520 } 521 } 522 523 this._setupIndices(); 524 this._mapBuffers(); 525 this.dirty = true; 526 return true; 527 }, 528 529 /** 530 * Used internally by CCParticleBatchNode <br/> 531 * don't use this unless you know what you're doing 532 * @param {Number} amount 533 */ 534 increaseTotalQuadsWith: function (amount) { 535 this._totalQuads += amount; 536 }, 537 538 /** 539 * Moves an amount of quads from oldIndex at newIndex 540 * @param {Number} oldIndex 541 * @param {Number} amount 542 * @param {Number} newIndex 543 */ 544 moveQuadsFromIndex: function (oldIndex, amount, newIndex) { 545 if (newIndex === undefined) { 546 newIndex = amount; 547 amount = this._totalQuads - oldIndex; 548 549 cc.assert((newIndex + (this._totalQuads - oldIndex)) <= this._capacity, cc._LogInfos.TextureAtlas_moveQuadsFromIndex); 550 551 if (amount === 0) 552 return; 553 } else { 554 555 cc.assert((newIndex + amount) <= this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_2); 556 557 cc.assert(oldIndex < this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_3); 558 559 if (oldIndex == newIndex) 560 return; 561 } 562 563 var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 564 var srcOffset = oldIndex * quadSize; 565 var srcLength = amount * quadSize; 566 var locQuadsReader = this._quadsReader; 567 var sourceArr = locQuadsReader.subarray(srcOffset, srcOffset + srcLength); 568 var dstOffset = newIndex * quadSize; 569 var moveLength, moveStart; 570 if (newIndex < oldIndex) { 571 moveLength = (oldIndex - newIndex) * quadSize; 572 moveStart = newIndex * quadSize; 573 locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), moveStart + srcLength) 574 } else { 575 moveLength = (newIndex - oldIndex) * quadSize; 576 moveStart = (oldIndex + amount) * quadSize; 577 locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), srcOffset); 578 } 579 locQuadsReader.set(sourceArr, dstOffset); 580 this.dirty = true; 581 }, 582 583 /** 584 * Ensures that after a realloc quads are still empty <br/> 585 * Used internally by CCParticleBatchNode 586 * @param {Number} index 587 * @param {Number} amount 588 */ 589 fillWithEmptyQuadsFromIndex: function (index, amount) { 590 var count = amount * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; 591 var clearReader = new Uint8Array(this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT, count); 592 for (var i = 0; i < count; i++) 593 clearReader[i] = 0; 594 }, 595 596 // TextureAtlas - Drawing 597 598 /** 599 * Draws all the Atlas's Quads 600 */ 601 drawQuads: function () { 602 this.drawNumberOfQuads(this._totalQuads, 0); 603 }, 604 605 _releaseBuffer: function () { 606 var gl = cc._renderContext; 607 if (this._buffersVBO) { 608 if (this._buffersVBO[0]) 609 gl.deleteBuffer(this._buffersVBO[0]); 610 if (this._buffersVBO[1]) 611 gl.deleteBuffer(this._buffersVBO[1]) 612 } 613 if (this._quadsWebBuffer) 614 gl.deleteBuffer(this._quadsWebBuffer); 615 } 616 }); 617 618 var _p = cc.TextureAtlas.prototype; 619 620 // Extended properties 621 /** @expose */ 622 _p.totalQuads; 623 cc.defineGetterSetter(_p, "totalQuads", _p.getTotalQuads); 624 /** @expose */ 625 _p.capacity; 626 cc.defineGetterSetter(_p, "capacity", _p.getCapacity); 627 /** @expose */ 628 _p.quads; 629 cc.defineGetterSetter(_p, "quads", _p.getQuads, _p.setQuads); 630 631 /** 632 * <p>Creates a TextureAtlas with an filename and with an initial capacity for Quads. <br /> 633 * The TextureAtlas capacity can be increased in runtime. </p> 634 * @param {String|cc.Texture2D} fileName 635 * @param {Number} capacity 636 * @return {cc.TextureAtlas|Null} 637 * @example 638 * 1. 639 * //creates a TextureAtlas with filename 640 * var textureAtlas = cc.TextureAtlas.create("res/hello.png", 3); 641 * 2. 642 * //creates a TextureAtlas with texture 643 * var texture = cc.textureCache.addImage("hello.png"); 644 * var textureAtlas = cc.TextureAtlas.create(texture, 3); 645 */ 646 cc.TextureAtlas.create = function (fileName, capacity) { 647 return new cc.TextureAtlas(fileName, capacity); 648 }; 649 650 if (cc._renderType === cc._RENDER_TYPE_WEBGL) { 651 cc.assert(typeof cc._tmp.WebGLTextureAtlas === "function", cc._LogInfos.MissingFile, "TexturesWebGL.js"); 652 cc._tmp.WebGLTextureAtlas(); 653 delete cc._tmp.WebGLTextureAtlas; 654 } 655 656 cc.assert(typeof cc._tmp.PrototypeTextureAtlas === "function", cc._LogInfos.MissingFile, "TexturesPropertyDefine.js"); 657 cc._tmp.PrototypeTextureAtlas(); 658 delete cc._tmp.PrototypeTextureAtlas;