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