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;