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