[libgdx] Skeleton.getBounds() applies clipping, see #2515

This commit is contained in:
Mario Zechner 2024-05-02 16:55:22 +02:00
parent a228adf684
commit b043e5c978
2 changed files with 90 additions and 4 deletions

View File

@ -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.
* <p>
* See <a href="http://esotericsoftware.com/spine-runtime-architecture#Instance-objects">Instance objects</a> 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<Bone> bones;
final Array<Slot> 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);
}

View File

@ -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) {