diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java index 19a9de0dbf..59159f4e8c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java @@ -70,12 +70,12 @@ public class SkeletonRenderer { * previous blend function is not restored, since that could result in unnecessary flushes, depending on what is rendered * next. */ public void draw (Batch batch, Skeleton skeleton) { - if (batch instanceof PolygonSpriteBatch) { - draw((PolygonSpriteBatch)batch, skeleton); - return; - } else if (batch instanceof TwoColorPolygonBatch) { + if (batch instanceof TwoColorPolygonBatch) { draw((TwoColorPolygonBatch)batch, skeleton); return; + } else if (batch instanceof PolygonSpriteBatch) { + draw((PolygonSpriteBatch)batch, skeleton); + return; } VertexEffect vertexEffect = this.vertexEffect; @@ -357,7 +357,7 @@ public void draw (TwoColorPolygonBatch batch, Skeleton skeleton) { FloatArray clippedVertices = clipper.getClippedVertices(); ShortArray clippedTriangles = clipper.getClippedTriangles(); if (vertexEffect != null) applyVertexEffect(clippedVertices.items, clippedVertices.size, 6, light, dark); - batch.draw(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0, + batch.drawTwoColor(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0, clippedTriangles.size); } else { if (vertexEffect != null) { @@ -386,7 +386,7 @@ public void draw (TwoColorPolygonBatch batch, Skeleton skeleton) { vertices[v + 3] = uvs[u + 1]; } } - batch.draw(texture, vertices, 0, verticesLength, triangles, 0, triangles.length); + batch.drawTwoColor(texture, vertices, 0, verticesLength, triangles, 0, triangles.length); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/TwoColorPolygonBatch.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/TwoColorPolygonBatch.java index c1d8cf652c..dd0de951ce 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/TwoColorPolygonBatch.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/TwoColorPolygonBatch.java @@ -31,10 +31,15 @@ package com.esotericsoftware.spine.utils; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.*; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.Mesh; import com.badlogic.gdx.graphics.Mesh.VertexDataType; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.VertexAttribute; import com.badlogic.gdx.graphics.VertexAttributes.Usage; import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.PolygonBatch; import com.badlogic.gdx.graphics.g2d.PolygonRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.ShaderProgram; @@ -43,13 +48,18 @@ import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.utils.NumberUtils; -public class TwoColorPolygonBatch implements Batch { +/** A batch that renders polygons and performs tinting using a light and dark color. + *
+ * Because an additional vertex attribute is used, the {@link Batch} and {@link PolygonBatch} methods that accept float[] vertex + * data do not perform two color tinting. {@link #drawTwoColor(Texture, float[], int, int)} and + * {@link #drawTwoColor(Texture, float[], int, int, short[], int, int)} are provided to accept float[] vertex data that contains + * two colors per vertex. */ +public class TwoColorPolygonBatch implements PolygonBatch { static final int VERTEX_SIZE = 2 + 1 + 1 + 2; static final int SPRITE_SIZE = 4 * VERTEX_SIZE; private final Mesh mesh; private final float[] vertices; - private final float[] tempSpriteVertices = new float[SPRITE_SIZE]; private final short[] triangles; private final Matrix4 transformMatrix = new Matrix4(); private final Matrix4 projectionMatrix = new Matrix4(); @@ -313,30 +323,6 @@ else if (triangleIndex + regionTrianglesLength > triangles.length this.vertexIndex = vertexIndex; } - public void draw (Texture texture, float[] polygonVertices, int verticesOffset, int verticesCount, short[] polygonTriangles, - int trianglesOffset, int trianglesCount) { - if (!drawing) throw new IllegalStateException("begin must be called before draw."); - - final short[] triangles = this.triangles; - final float[] vertices = this.vertices; - - if (texture != lastTexture) { - switchTexture(texture); - } else if (triangleIndex + trianglesCount > triangles.length || vertexIndex + verticesCount > vertices.length) // - flush(); - - int triangleIndex = this.triangleIndex; - final int vertexIndex = this.vertexIndex; - final int startVertex = vertexIndex / 6; - - for (int i = trianglesOffset, n = i + trianglesCount; i < n; i++) - triangles[triangleIndex++] = (short)(polygonTriangles[i] + startVertex); - this.triangleIndex = triangleIndex; - - System.arraycopy(polygonVertices, verticesOffset, vertices, vertexIndex, verticesCount); - this.vertexIndex += verticesCount; - } - @Override public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) { @@ -746,28 +732,74 @@ else if (triangleIndex + 6 > triangles.length || vertexIndex + SPRITE_SIZE > ver this.vertexIndex = idx; } - /** Draws a rectangle using the given vertices. There must be 4 vertices, each made up of 6 elements in this order: x, y, - * lightColor, darkColor, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not + /** Draws polygons using the given vertices and triangles. There must be 4 vertices, each made up of 6 elements in this order: + * x, y, lightColor, darkColor, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not * applied. */ - @Override - public void draw (Texture texture, float[] spriteVertices, int offset, int count) { + public void drawTwoColor (Texture texture, float[] polygonVertices, int verticesOffset, int verticesCount, + short[] polygonTriangles, int trianglesOffset, int trianglesCount) { + if (!drawing) throw new IllegalStateException("begin must be called before draw."); + + final short[] triangles = this.triangles; + final float[] vertices = this.vertices; + + if (texture != lastTexture) { + switchTexture(texture); + } else if (triangleIndex + trianglesCount > triangles.length || vertexIndex + verticesCount > vertices.length) // + flush(); + + int triangleIndex = this.triangleIndex; + final int vertexIndex = this.vertexIndex; + final int startVertex = vertexIndex / 6; + + for (int i = trianglesOffset, n = i + trianglesCount; i < n; i++) + triangles[triangleIndex++] = (short)(polygonTriangles[i] + startVertex); + this.triangleIndex = triangleIndex; + + System.arraycopy(polygonVertices, verticesOffset, vertices, vertexIndex, verticesCount); + this.vertexIndex += verticesCount; + } + + /** Draws polygons using the given vertices and triangles in the {@link PolygonBatch} format. There must be 4 vertices, each + * made up of 5 elements in this order: x, y, color, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the + * TwoColorPolygonBatch is not applied. */ + public void draw (Texture texture, float[] polygonVertices, int verticesOffset, int verticesCount, short[] polygonTriangles, + int trianglesOffset, int trianglesCount) { if (!drawing) throw new IllegalStateException("begin must be called before draw."); - // odds are this is a sprite, we meed to convert it - if (spriteVertices.length == 20 && offset == 0 && count == 20) { - final float[] vertices = tempSpriteVertices; - int idx = 0; - for (int i = 0; i < 20; i += 5) { - vertices[idx++] = spriteVertices[i]; - vertices[idx++] = spriteVertices[i + 1]; - vertices[idx++] = spriteVertices[i + 2]; - vertices[idx++] = 0; // dark - vertices[idx++] = spriteVertices[i + 3]; - vertices[idx++] = spriteVertices[i + 4]; - } - spriteVertices = vertices; - count = SPRITE_SIZE; + final short[] triangles = this.triangles; + final float[] vertices = this.vertices; + + if (texture != lastTexture) { + switchTexture(texture); + } else if (triangleIndex + trianglesCount > triangles.length || vertexIndex + verticesCount / 5 * 6 > vertices.length) // + flush(); + + int triangleIndex = this.triangleIndex; + final int vertexIndex = this.vertexIndex; + final int startVertex = vertexIndex / 6; + + for (int i = trianglesOffset, n = i + trianglesCount; i < n; i++) + triangles[triangleIndex++] = (short)(polygonTriangles[i] + startVertex); + this.triangleIndex = triangleIndex; + + int idx = this.vertexIndex; + for (int i = verticesOffset, n = verticesOffset + verticesCount; i < n; i += 5) { + vertices[idx++] = polygonVertices[i]; + vertices[idx++] = polygonVertices[i + 1]; + vertices[idx++] = polygonVertices[i + 2]; + vertices[idx++] = 0; // dark + vertices[idx++] = polygonVertices[i + 3]; + vertices[idx++] = polygonVertices[i + 4]; } + this.vertexIndex = idx; + } + + /** Draws rectangles using the given vertices. There must be 4 vertices, each made up of 6 elements in this order: x, y, + * lightColor, darkColor, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not + * applied. */ + public void drawTwoColor (Texture texture, float[] spriteVertices, int offset, int count) { + if (!drawing) throw new IllegalStateException("begin must be called before draw."); + final short[] triangles = this.triangles; final float[] vertices = this.vertices; @@ -794,6 +826,47 @@ else if (triangleIndex + triangleCount > triangles.length || vertexIndex + count this.vertexIndex += count; } + /** Draws rectangles using the given vertices in the {@link Batch} format. There must be 4 vertices, each made up of 5 elements + * in this order: x, y, color, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not + * applied. */ + @Override + public void draw (Texture texture, float[] spriteVertices, int offset, int count) { + if (!drawing) throw new IllegalStateException("begin must be called before draw."); + + final short[] triangles = this.triangles; + final float[] vertices = this.vertices; + + final int triangleCount = count / 20 * 6; + if (texture != lastTexture) + switchTexture(texture); + else if (triangleIndex + triangleCount > triangles.length || vertexIndex + count / 5 * 6 > vertices.length) // + flush(); + + final int vertexIndex = this.vertexIndex; + int triangleIndex = this.triangleIndex; + short vertex = (short)(vertexIndex / VERTEX_SIZE); + for (int n = triangleIndex + triangleCount; triangleIndex < n; triangleIndex += 6, vertex += 4) { + triangles[triangleIndex] = vertex; + triangles[triangleIndex + 1] = (short)(vertex + 1); + triangles[triangleIndex + 2] = (short)(vertex + 2); + triangles[triangleIndex + 3] = (short)(vertex + 2); + triangles[triangleIndex + 4] = (short)(vertex + 3); + triangles[triangleIndex + 5] = vertex; + } + this.triangleIndex = triangleIndex; + + int idx = this.vertexIndex; + for (int i = offset, n = offset + count; i < n; i += 5) { + vertices[idx++] = spriteVertices[i]; + vertices[idx++] = spriteVertices[i + 1]; + vertices[idx++] = spriteVertices[i + 2]; + vertices[idx++] = 0; // dark + vertices[idx++] = spriteVertices[i + 3]; + vertices[idx++] = spriteVertices[i + 4]; + } + this.vertexIndex = idx; + } + @Override public void draw (TextureRegion region, float x, float y) { draw(region, x, y, region.getRegionWidth(), region.getRegionHeight());