OSDN Git Service

Comments.
[mikumikustudio/libgdx-mikumikustudio.git] / gdx / src / com / badlogic / gdx / graphics / g2d / PolygonSpriteBatch.java
1 /*******************************************************************************\r
2  * Copyright 2011 See AUTHORS file.\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  * \r
8  *   http://www.apache.org/licenses/LICENSE-2.0\r
9  * \r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  ******************************************************************************/\r
16 \r
17 package com.badlogic.gdx.graphics.g2d;\r
18 \r
19 import static com.badlogic.gdx.graphics.g2d.Sprite.*;\r
20 \r
21 import com.badlogic.gdx.Gdx;\r
22 import com.badlogic.gdx.graphics.Color;\r
23 import com.badlogic.gdx.graphics.GL10;\r
24 import com.badlogic.gdx.graphics.GL11;\r
25 import com.badlogic.gdx.graphics.GL20;\r
26 import com.badlogic.gdx.graphics.GLCommon;\r
27 import com.badlogic.gdx.graphics.Mesh;\r
28 import com.badlogic.gdx.graphics.Mesh.VertexDataType;\r
29 import com.badlogic.gdx.graphics.Texture;\r
30 import com.badlogic.gdx.graphics.VertexAttribute;\r
31 import com.badlogic.gdx.graphics.VertexAttributes.Usage;\r
32 import com.badlogic.gdx.graphics.glutils.ShaderProgram;\r
33 import com.badlogic.gdx.math.MathUtils;\r
34 import com.badlogic.gdx.math.Matrix4;\r
35 import com.badlogic.gdx.utils.NumberUtils;\r
36 \r
37 /** A PolygonSpriteBatch is used to draw 2D polygons that reference a texture (region). The class will batch the drawing commands\r
38  * and optimize them for processing by the GPU.\r
39  * <p>\r
40  * To draw something with a PolygonSpriteBatch one has to first call the {@link PolygonSpriteBatch#begin()} method which will\r
41  * setup appropriate render states. When you are done with drawing you have to call {@link PolygonSpriteBatch#end()} which will\r
42  * actually draw the things you specified.\r
43  * <p>\r
44  * All drawing commands of the PolygonSpriteBatch operate in screen coordinates. The screen coordinate system has an x-axis\r
45  * pointing to the right, an y-axis pointing upwards and the origin is in the lower left corner of the screen. You can also\r
46  * provide your own transformation and projection matrices if you so wish.\r
47  * <p>\r
48  * A PolygonSpriteBatch is managed. In case the OpenGL context is lost all OpenGL resources a PolygonSpriteBatch uses internally\r
49  * get invalidated. A context is lost when a user switches to another application or receives an incoming call on Android. A\r
50  * SpritPolygonSpriteBatcheBatch will be automatically reloaded after the OpenGL context is restored.\r
51  * <p>\r
52  * A PolygonSpriteBatch is a pretty heavy object so you should only ever have one in your program.\r
53  * <p>\r
54  * A PolygonSpriteBatch works with OpenGL ES 1.x and 2.0. In the case of a 2.0 context it will use its own custom shader to draw\r
55  * all provided sprites. You can set your own custom shader via {@link #setShader(ShaderProgram)}.\r
56  * <p>\r
57  * A PolygonSpriteBatch has to be disposed if it is no longer used.\r
58  * @author mzechner\r
59  * @author Stefan Bachmann\r
60  * @author Nathan Sweet */\r
61 public class PolygonSpriteBatch {\r
62         private Mesh mesh;\r
63         private Mesh[] buffers;\r
64         private int bufferIndex;\r
65 \r
66         private final float[] vertices;\r
67         private final short[] triangles;\r
68         private int vertexIndex, triangleIndex;\r
69         private Texture lastTexture;\r
70         private boolean drawing;\r
71 \r
72         private final Matrix4 transformMatrix = new Matrix4();\r
73         private final Matrix4 projectionMatrix = new Matrix4();\r
74         private final Matrix4 combinedMatrix = new Matrix4();\r
75 \r
76         private boolean blendingDisabled;\r
77         private int blendSrcFunc = GL11.GL_SRC_ALPHA;\r
78         private int blendDstFunc = GL11.GL_ONE_MINUS_SRC_ALPHA;\r
79 \r
80         private final ShaderProgram shader;\r
81         private ShaderProgram customShader;\r
82         private boolean ownsShader;\r
83 \r
84         float color = Color.WHITE.toFloatBits();\r
85         private Color tempColor = new Color(1, 1, 1, 1);\r
86 \r
87         /** Number of render calls since the last {@link #begin()}. **/\r
88         public int renderCalls = 0;\r
89 \r
90         /** Number of rendering calls, ever. Will not be reset unless set manually. **/\r
91         public int totalRenderCalls = 0;\r
92 \r
93         /** The maximum number of triangles rendered in one batch so far. **/\r
94         public int maxTrianglesInBatch = 0;\r
95 \r
96         /** Constructs a new PolygonSpriteBatch with a size of 2000, the default shader, and one buffer.\r
97          * @see PolygonSpriteBatch#PolygonSpriteBatch(int, int, ShaderProgram) */\r
98         public PolygonSpriteBatch () {\r
99                 this(2000, null);\r
100         }\r
101 \r
102         /** Constructs a PolygonSpriteBatch with the default shader and one buffer.\r
103          * @see PolygonSpriteBatch#PolygonSpriteBatch(int, int, ShaderProgram) */\r
104         public PolygonSpriteBatch (int size) {\r
105                 this(size, 1, null);\r
106         }\r
107 \r
108         /** Constructs a new PolygonSpriteBatch with one buffer.\r
109          * @see PolygonSpriteBatch#PolygonSpriteBatch(int, int, ShaderProgram) */\r
110         public PolygonSpriteBatch (int size, ShaderProgram defaultShader) {\r
111                 this(size, 1, defaultShader);\r
112         }\r
113 \r
114         /** Constructs a PolygonSpriteBatch with the default shader.\r
115          * @see PolygonSpriteBatch#PolygonSpriteBatch(int, int, ShaderProgram) */\r
116         public PolygonSpriteBatch (int size, int buffers) {\r
117                 this(size, buffers, null);\r
118         }\r
119 \r
120         /** Constructs a new PolygonSpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point upwards,\r
121          * x-axis point to the right and the origin being in the bottom left corner of the screen. The projection will be pixel perfect\r
122          * with respect to the current screen resolution.\r
123          * <p>\r
124          * The defaultShader specifies the shader to use. Note that the names for uniforms for this default shader are different than\r
125          * the ones expect for shaders set with {@link #setShader(ShaderProgram)}. See {@link SpriteBatch#createDefaultShader()}.\r
126          * @param size The max number of vertices and number of triangles in a single batch. Max of 10920.\r
127          * @param buffers The number of meshes to use. This is an expert function. It only makes sense with VBOs (see\r
128          *           {@link Mesh#forceVBO}).\r
129          * @param defaultShader The default shader to use. This is not owned by the PolygonSpriteBatch and must be disposed separately. */\r
130         public PolygonSpriteBatch (int size, int buffers, ShaderProgram defaultShader) {\r
131                 // 32767 is max index, so 32767 / 3 - (32767 / 3 % 3) = 10920.\r
132                 if (size > 10920) throw new IllegalArgumentException("Can't have more than 10920 triangles per batch: " + size);\r
133 \r
134                 this.buffers = new Mesh[buffers];\r
135                 for (int i = 0; i < buffers; i++) {\r
136                         this.buffers[i] = new Mesh(VertexDataType.VertexArray, false, size, size * 3, new VertexAttribute(Usage.Position, 2,\r
137                                 ShaderProgram.POSITION_ATTRIBUTE), new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE),\r
138                                 new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"));\r
139                 }\r
140                 mesh = this.buffers[0];\r
141 \r
142                 vertices = new float[size * VERTEX_SIZE];\r
143                 triangles = new short[size * 3];\r
144 \r
145                 if (Gdx.graphics.isGL20Available() && defaultShader == null) {\r
146                         shader = SpriteBatch.createDefaultShader();\r
147                         ownsShader = true;\r
148                 } else\r
149                         shader = defaultShader;\r
150 \r
151                 projectionMatrix.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());\r
152         }\r
153 \r
154         /** Sets up the PolygonSpriteBatch for drawing. This will disable depth buffer writting. It enables blending and texturing. If\r
155          * you have more texture units enabled than the first one you have to disable them before calling this. Uses a screen\r
156          * coordinate system by default where everything is given in pixels. You can specify your own projection and modelview matrices\r
157          * via {@link #setProjectionMatrix(Matrix4)} and {@link #setTransformMatrix(Matrix4)}. */\r
158         public void begin () {\r
159                 if (drawing) throw new IllegalStateException("PolygonSpriteBatch.end must be called before begin.");\r
160                 renderCalls = 0;\r
161 \r
162                 Gdx.gl.glDepthMask(false);\r
163                 if (Gdx.graphics.isGL20Available()) {\r
164                         if (customShader != null)\r
165                                 customShader.begin();\r
166                         else\r
167                                 shader.begin();\r
168                 } else {\r
169                         Gdx.gl.glEnable(GL10.GL_TEXTURE_2D);\r
170                 }\r
171                 setupMatrices();\r
172 \r
173                 drawing = true;\r
174         }\r
175 \r
176         /** Finishes off rendering. Enables depth writes, disables blending and texturing. Must always be called after a call to\r
177          * {@link #begin()} */\r
178         public void end () {\r
179                 if (!drawing) throw new IllegalStateException("PolygonSpriteBatch.begin must be called before end.");\r
180                 if (vertexIndex > 0) flush();\r
181                 lastTexture = null;\r
182                 drawing = false;\r
183 \r
184                 GLCommon gl = Gdx.gl;\r
185                 gl.glDepthMask(true);\r
186                 if (isBlendingEnabled()) gl.glDisable(GL10.GL_BLEND);\r
187 \r
188                 if (Gdx.graphics.isGL20Available()) {\r
189                         if (customShader != null)\r
190                                 customShader.end();\r
191                         else\r
192                                 shader.end();\r
193                 } else {\r
194                         gl.glDisable(GL10.GL_TEXTURE_2D);\r
195                 }\r
196         }\r
197 \r
198         /** Sets the color used to tint images when they are added to the PolygonSpriteBatch. Default is {@link Color#WHITE}. */\r
199         public void setColor (Color tint) {\r
200                 color = tint.toFloatBits();\r
201         }\r
202 \r
203         /** @see #setColor(Color) */\r
204         public void setColor (float r, float g, float b, float a) {\r
205                 int intBits = (int)(255 * a) << 24 | (int)(255 * b) << 16 | (int)(255 * g) << 8 | (int)(255 * r);\r
206                 color = NumberUtils.intToFloatColor(intBits);\r
207         }\r
208 \r
209         /** @see #setColor(Color)\r
210          * @see Color#toFloatBits() */\r
211         public void setColor (float color) {\r
212                 this.color = color;\r
213         }\r
214 \r
215         /** @return the rendering color of this PolygonSpriteBatch. Manipulating the returned instance has no effect. */\r
216         public Color getColor () {\r
217                 int intBits = NumberUtils.floatToIntColor(color);\r
218                 Color color = this.tempColor;\r
219                 color.r = (intBits & 0xff) / 255f;\r
220                 color.g = ((intBits >>> 8) & 0xff) / 255f;\r
221                 color.b = ((intBits >>> 16) & 0xff) / 255f;\r
222                 color.a = ((intBits >>> 24) & 0xff) / 255f;\r
223                 return color;\r
224         }\r
225 \r
226         /** Draws a polygon region with the bottom left corner at x,y having the width and height of the region. */\r
227         public void draw (PolygonRegion region, float x, float y) {\r
228                 if (!drawing) throw new IllegalStateException("PolygonSpriteBatch.begin must be called before draw.");\r
229 \r
230                 final short[] triangles = this.triangles;\r
231                 final short[] regionTriangles = region.triangles;\r
232                 final int regionTrianglesLength = regionTriangles.length;\r
233                 final float[] regionVertices = region.vertices;\r
234                 final int regionVerticesLength = regionVertices.length;\r
235 \r
236                 final Texture texture = region.region.texture;\r
237                 if (texture != lastTexture)\r
238                         switchTexture(texture);\r
239                 else if (triangleIndex + regionTrianglesLength > triangles.length || vertexIndex + regionVerticesLength > vertices.length)\r
240                         flush();\r
241 \r
242                 int triangleIndex = this.triangleIndex;\r
243                 int vertexIndex = this.vertexIndex;\r
244                 final int startVertex = vertexIndex / VERTEX_SIZE;\r
245 \r
246                 for (int i = 0; i < regionTrianglesLength; i++)\r
247                         triangles[triangleIndex++] = (short)(regionTriangles[i] + startVertex);\r
248                 this.triangleIndex = triangleIndex;\r
249 \r
250                 final float[] vertices = this.vertices;\r
251                 final float color = this.color;\r
252                 final float[] textureCoords = region.textureCoords;\r
253 \r
254                 for (int i = 0; i < regionVerticesLength; i += 2) {\r
255                         vertices[vertexIndex++] = regionVertices[i] + x;\r
256                         vertices[vertexIndex++] = regionVertices[i + 1] + y;\r
257                         vertices[vertexIndex++] = color;\r
258                         vertices[vertexIndex++] = textureCoords[i];\r
259                         vertices[vertexIndex++] = textureCoords[i + 1];\r
260                 }\r
261                 this.vertexIndex = vertexIndex;\r
262         }\r
263 \r
264         /** Draws a polygon region with the bottom left corner at x,y and stretching the region to cover the given width and height. */\r
265         public void draw (PolygonRegion region, float x, float y, float width, float height) {\r
266                 if (!drawing) throw new IllegalStateException("PolygonSpriteBatch.begin must be called before draw.");\r
267 \r
268                 final short[] triangles = this.triangles;\r
269                 final short[] regionTriangles = region.triangles;\r
270                 final int regionTrianglesLength = regionTriangles.length;\r
271                 final float[] regionVertices = region.vertices;\r
272                 final int regionVerticesLength = regionVertices.length;\r
273                 final TextureRegion textureRegion = region.region;\r
274 \r
275                 final Texture texture = textureRegion.texture;\r
276                 if (texture != lastTexture)\r
277                         switchTexture(texture);\r
278                 else if (triangleIndex + regionTrianglesLength > triangles.length || vertexIndex + regionVerticesLength > vertices.length)\r
279                         flush();\r
280 \r
281                 int triangleIndex = this.triangleIndex;\r
282                 int vertexIndex = this.vertexIndex;\r
283                 final int startVertex = vertexIndex / VERTEX_SIZE;\r
284 \r
285                 for (int i = 0, n = regionTriangles.length; i < n; i++)\r
286                         triangles[triangleIndex++] = (short)(regionTriangles[i] + startVertex);\r
287                 this.triangleIndex = triangleIndex;\r
288 \r
289                 final float[] vertices = this.vertices;\r
290                 final float color = this.color;\r
291                 final float[] textureCoords = region.textureCoords;\r
292                 final float sX = width / textureRegion.regionWidth;\r
293                 final float sY = height / textureRegion.regionHeight;\r
294 \r
295                 for (int i = 0; i < regionVerticesLength; i += 2) {\r
296                         vertices[vertexIndex++] = regionVertices[i] * sX + x;\r
297                         vertices[vertexIndex++] = regionVertices[i + 1] * sY + y;\r
298                         vertices[vertexIndex++] = color;\r
299                         vertices[vertexIndex++] = textureCoords[i];\r
300                         vertices[vertexIndex++] = textureCoords[i + 1];\r
301                 }\r
302                 this.vertexIndex = vertexIndex;\r
303         }\r
304 \r
305         /** Draws the polygon region with the bottom left corner at x,y and stretching the region to cover the given width and height.\r
306          * The polygon region is offset by originX, originY relative to the origin. Scale specifies the scaling factor by which the\r
307          * polygon region should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the\r
308          * rectangle around originX, originY. */\r
309         public void draw (PolygonRegion region, float x, float y, float originX, float originY, float width, float height,\r
310                 float scaleX, float scaleY, float rotation) {\r
311                 if (!drawing) throw new IllegalStateException("PolygonSpriteBatch.begin must be called before draw.");\r
312 \r
313                 final short[] triangles = this.triangles;\r
314                 final short[] regionTriangles = region.triangles;\r
315                 final int regionTrianglesLength = regionTriangles.length;\r
316                 final float[] regionVertices = region.vertices;\r
317                 final int regionVerticesLength = regionVertices.length;\r
318                 final TextureRegion textureRegion = region.region;\r
319 \r
320                 Texture texture = textureRegion.texture;\r
321                 if (texture != lastTexture)\r
322                         switchTexture(texture);\r
323                 else if (triangleIndex + regionTrianglesLength > triangles.length || vertexIndex + regionVerticesLength > vertices.length)\r
324                         flush();\r
325 \r
326                 int triangleIndex = this.triangleIndex;\r
327                 int vertexIndex = this.vertexIndex;\r
328                 final int startVertex = vertexIndex / VERTEX_SIZE;\r
329 \r
330                 for (int i = 0; i < regionTrianglesLength; i++)\r
331                         triangles[triangleIndex++] = (short)(regionTriangles[i] + startVertex);\r
332                 this.triangleIndex = triangleIndex;\r
333 \r
334                 final float[] vertices = this.vertices;\r
335                 final float color = this.color;\r
336                 final float[] textureCoords = region.textureCoords;\r
337 \r
338                 final float worldOriginX = x + originX;\r
339                 final float worldOriginY = y + originY;\r
340                 final float sX = width / textureRegion.regionWidth;\r
341                 final float sY = height / textureRegion.regionHeight;\r
342                 final float cos = MathUtils.cosDeg(rotation);\r
343                 final float sin = MathUtils.sinDeg(rotation);\r
344 \r
345                 float fx, fy;\r
346                 for (int i = 0; i < regionVerticesLength; i += 2) {\r
347                         fx = (regionVertices[i] * sX - originX) * scaleX;\r
348                         fy = (regionVertices[i + 1] * sY - originY) * scaleY;\r
349                         vertices[vertexIndex++] = cos * fx - sin * fy + worldOriginX;\r
350                         vertices[vertexIndex++] = sin * fx + cos * fy + worldOriginY;\r
351                         vertices[vertexIndex++] = color;\r
352                         vertices[vertexIndex++] = textureCoords[i];\r
353                         vertices[vertexIndex++] = textureCoords[i + 1];\r
354                 }\r
355                 this.vertexIndex = vertexIndex;\r
356         }\r
357 \r
358         /** Draws the polygon using the given vertices and triangles. Each vertices must be made up of 5 elements in this order: x, y,\r
359          * color, u, v. */\r
360         public void draw (Texture texture, float[] polygonVertices, int verticesOffset, int verticesCount, short[] polygonTriangles,\r
361                 int trianglesOffset, int trianglesCount) {\r
362                 if (!drawing) throw new IllegalStateException("PolygonSpriteBatch.begin must be called before draw.");\r
363 \r
364                 final short[] triangles = this.triangles;\r
365                 final float[] vertices = this.vertices;\r
366 \r
367                 if (texture != lastTexture)\r
368                         switchTexture(texture);\r
369                 else if (triangleIndex + trianglesCount > triangles.length || vertexIndex + verticesCount > vertices.length) //\r
370                         flush();\r
371 \r
372                 int triangleIndex = this.triangleIndex;\r
373                 final int vertexIndex = this.vertexIndex;\r
374                 final int startVertex = vertexIndex / VERTEX_SIZE;\r
375 \r
376                 for (int i = trianglesOffset, n = i + trianglesCount; i < n; i++)\r
377                         triangles[triangleIndex++] = (short)(polygonTriangles[i] + startVertex);\r
378                 this.triangleIndex = triangleIndex;\r
379 \r
380                 System.arraycopy(polygonVertices, verticesOffset, vertices, vertexIndex, verticesCount);\r
381                 this.vertexIndex += verticesCount;\r
382         }\r
383 \r
384         /** Causes any pending sprites to be rendered, without ending the PolygonSpriteBatch. */\r
385         public void flush () {\r
386                 if (vertexIndex == 0) return;\r
387 \r
388                 renderCalls++;\r
389                 totalRenderCalls++;\r
390                 int trianglesInBatch = triangleIndex;\r
391                 if (trianglesInBatch > maxTrianglesInBatch) maxTrianglesInBatch = trianglesInBatch;\r
392 \r
393                 lastTexture.bind();\r
394                 Mesh mesh = this.mesh;\r
395                 mesh.setVertices(vertices, 0, vertexIndex);\r
396                 mesh.setIndices(triangles, 0, triangleIndex);\r
397 \r
398                 if (blendingDisabled) {\r
399                         Gdx.gl.glDisable(GL20.GL_BLEND);\r
400                 } else {\r
401                         Gdx.gl.glEnable(GL20.GL_BLEND);\r
402                         if (blendSrcFunc != -1) Gdx.gl.glBlendFunc(blendSrcFunc, blendDstFunc);\r
403                 }\r
404 \r
405                 if (Gdx.graphics.isGL20Available())\r
406                         mesh.render(customShader != null ? customShader : shader, GL10.GL_TRIANGLES, 0, trianglesInBatch);\r
407                 else\r
408                         mesh.render(GL10.GL_TRIANGLES, 0, trianglesInBatch);\r
409 \r
410                 vertexIndex = 0;\r
411                 triangleIndex = 0;\r
412                 bufferIndex++;\r
413                 if (bufferIndex == buffers.length) bufferIndex = 0;\r
414                 this.mesh = buffers[bufferIndex];\r
415         }\r
416 \r
417         /** Disables blending for drawing sprites. Calling this within {@link #begin()}/{@link #end()} will flush the batch. */\r
418         public void disableBlending () {\r
419                 flush();\r
420                 blendingDisabled = true;\r
421         }\r
422 \r
423         /** Enables blending for sprites. Calling this within {@link #begin()}/{@link #end()} will flush the batch. */\r
424         public void enableBlending () {\r
425                 flush();\r
426                 blendingDisabled = false;\r
427         }\r
428 \r
429         /** Sets the blending function to be used when rendering sprites.\r
430          * @param srcFunc the source function, e.g. GL11.GL_SRC_ALPHA. If set to -1, PolygonSpriteBatch won't change the blending\r
431          *           function.\r
432          * @param dstFunc the destination function, e.g. GL11.GL_ONE_MINUS_SRC_ALPHA */\r
433         public void setBlendFunction (int srcFunc, int dstFunc) {\r
434                 if (blendSrcFunc == srcFunc && blendDstFunc == dstFunc) return;\r
435                 flush();\r
436                 blendSrcFunc = srcFunc;\r
437                 blendDstFunc = dstFunc;\r
438         }\r
439 \r
440         /** Disposes all resources associated with this PolygonSpriteBatch. */\r
441         public void dispose () {\r
442                 for (int i = 0; i < buffers.length; i++)\r
443                         buffers[i].dispose();\r
444                 if (ownsShader && shader != null) shader.dispose();\r
445         }\r
446 \r
447         /** Returns the current projection matrix. Changing this within {@link #begin()}/{@link #end()} results in undefined behaviour. */\r
448         public Matrix4 getProjectionMatrix () {\r
449                 return projectionMatrix;\r
450         }\r
451 \r
452         /** Returns the current transform matrix. Changing this within {@link #begin()}/{@link #end()} results in undefined behaviour. */\r
453         public Matrix4 getTransformMatrix () {\r
454                 return transformMatrix;\r
455         }\r
456 \r
457         /** Sets the projection matrix to be used by this PolygonSpriteBatch. If this is called inside a {@link #begin()}/{@link #end()}\r
458          * block, the current batch is flushed to the gpu. */\r
459         public void setProjectionMatrix (Matrix4 projection) {\r
460                 if (drawing) flush();\r
461                 projectionMatrix.set(projection);\r
462                 if (drawing) setupMatrices();\r
463         }\r
464 \r
465         /** Sets the transform matrix to be used by this PolygonSpriteBatch. If this is called inside a {@link #begin()}/{@link #end()}\r
466          * block, the current batch is flushed to the gpu. */\r
467         public void setTransformMatrix (Matrix4 transform) {\r
468                 if (drawing) flush();\r
469                 transformMatrix.set(transform);\r
470                 if (drawing) setupMatrices();\r
471         }\r
472 \r
473         private void setupMatrices () {\r
474                 if (!Gdx.graphics.isGL20Available()) {\r
475                         GL10 gl = Gdx.gl10;\r
476                         gl.glMatrixMode(GL10.GL_PROJECTION);\r
477                         gl.glLoadMatrixf(projectionMatrix.val, 0);\r
478                         gl.glMatrixMode(GL10.GL_MODELVIEW);\r
479                         gl.glLoadMatrixf(transformMatrix.val, 0);\r
480                 } else {\r
481                         combinedMatrix.set(projectionMatrix).mul(transformMatrix);\r
482                         if (customShader != null) {\r
483                                 customShader.setUniformMatrix("u_proj", projectionMatrix);\r
484                                 customShader.setUniformMatrix("u_trans", transformMatrix);\r
485                                 customShader.setUniformMatrix("u_projTrans", combinedMatrix);\r
486                                 customShader.setUniformi("u_texture", 0);\r
487                         } else {\r
488                                 shader.setUniformMatrix("u_projTrans", combinedMatrix);\r
489                                 shader.setUniformi("u_texture", 0);\r
490                         }\r
491                 }\r
492         }\r
493 \r
494         private void switchTexture (Texture texture) {\r
495                 flush();\r
496                 lastTexture = texture;\r
497         }\r
498 \r
499         /** @see SpriteBatch#setShader(ShaderProgram) */\r
500         public void setShader (ShaderProgram shader) {\r
501                 if (drawing) {\r
502                         flush();\r
503                         if (customShader != null)\r
504                                 customShader.end();\r
505                         else\r
506                                 this.shader.end();\r
507                 }\r
508                 customShader = shader;\r
509                 if (drawing) {\r
510                         if (customShader != null)\r
511                                 customShader.begin();\r
512                         else\r
513                                 this.shader.begin();\r
514                         setupMatrices();\r
515                 }\r
516         }\r
517 \r
518         /** @return whether blending for sprites is enabled */\r
519         public boolean isBlendingEnabled () {\r
520                 return !blendingDisabled;\r
521         }\r
522 }\r