diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index fca5f239f..2fadf1cd6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -38,16 +38,16 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Skin.SkinEntry; -import com.esotericsoftware.spine.attachments.Attachment; -import com.esotericsoftware.spine.attachments.MeshAttachment; -import com.esotericsoftware.spine.attachments.PathAttachment; -import com.esotericsoftware.spine.attachments.RegionAttachment; +import com.esotericsoftware.spine.attachments.*; +import com.esotericsoftware.spine.utils.SkeletonClipping; /** Stores the current pose for a skeleton. *

* See Instance objects in the Spine * Runtimes Guide. */ public class Skeleton { + static private final SkeletonClipping clipper = new SkeletonClipping(); + static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0}; final SkeletonData data; final Array bones; final Array slots; @@ -699,19 +699,31 @@ public class Skeleton { if (!slot.bone.active) continue; int verticesLength = 0; float[] vertices = null; + short[] triangles = null; Attachment attachment = slot.attachment; if (attachment instanceof RegionAttachment) { RegionAttachment region = (RegionAttachment)attachment; verticesLength = 8; vertices = temp.setSize(8); region.computeWorldVertices(slot, vertices, 0, 2); + triangles = quadTriangles; } else if (attachment instanceof MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; verticesLength = mesh.getWorldVerticesLength(); vertices = temp.setSize(verticesLength); mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + triangles = mesh.getTriangles(); + } else if (attachment instanceof ClippingAttachment) { + ClippingAttachment clip = (ClippingAttachment)attachment; + clipper.clipStart(slot, clip); + continue; } if (vertices != null) { + if (clipper.isClipping()) { + clipper.clipTriangles(vertices, verticesLength, triangles, triangles.length); + vertices = clipper.getClippedVertices().items; + verticesLength = clipper.getClippedVertices().size; + } for (int ii = 0; ii < verticesLength; ii += 2) { float x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); @@ -720,7 +732,9 @@ public class Skeleton { maxY = Math.max(maxY, y); } } + clipper.clipEnd(slot); } + clipper.clipEnd(); offset.set(minX, minY); size.set(maxX - minX, maxY - minY); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java index 2c9ad1afb..77bcfab56 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java @@ -82,6 +82,78 @@ public class SkeletonClipping { return clipAttachment != null; } + public void clipTriangles (float[] vertices, int verticesLength, short[] triangles, int trianglesLength) { + + FloatArray clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + ShortArray clippedTriangles = this.clippedTriangles; + Object[] polygons = clippingPolygons.items; + int polygonsCount = clippingPolygons.size; + int vertexSize = 2; + + short index = 0; + clippedVertices.clear(); + clippedTriangles.clear(); + outer: + for (int i = 0; i < trianglesLength; i += 3) { + int vertexOffset = triangles[i] << 1; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] << 1; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] << 1; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + + for (int p = 0; p < polygonsCount; p++) { + int s = clippedVertices.size; + if (clip(x1, y1, x2, y2, x3, y3, (FloatArray)polygons[p], clipOutput)) { + int clipOutputLength = clipOutput.size; + if (clipOutputLength == 0) continue; + + int clipOutputCount = clipOutputLength >> 1; + float[] clipOutputItems = clipOutput.items; + float[] clippedVerticesItems = clippedVertices.setSize(s + clipOutputCount * vertexSize); + for (int ii = 0; ii < clipOutputLength; ii += 2) { + float x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + s += 2; + } + + s = clippedTriangles.size; + short[] clippedTrianglesItems = clippedTriangles.setSize(s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (int ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (short)(index + ii); + clippedTrianglesItems[s + 2] = (short)(index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + + } else { + float[] clippedVerticesItems = clippedVertices.setSize(s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + + s = clippedTriangles.size; + short[] clippedTrianglesItems = clippedTriangles.setSize(s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (short)(index + 1); + clippedTrianglesItems[s + 2] = (short)(index + 2); + index += 3; + continue outer; + } + } + } + } + public void clipTriangles (float[] vertices, int verticesLength, short[] triangles, int trianglesLength, float[] uvs, float light, float dark, boolean twoColor) {