[haxe] Skeleton.getBounds() applies clipping, see #2515. Port of commits b043e5c, 637321a and 2049bed.

This commit is contained in:
Davide Tantillo 2024-05-04 12:01:20 +02:00
parent ad82b56425
commit eb80431642
3 changed files with 104 additions and 3 deletions

View File

@ -32,11 +32,13 @@ package spine;
import lime.math.Rectangle;
import haxe.ds.StringMap;
import spine.attachments.Attachment;
import spine.attachments.ClippingAttachment;
import spine.attachments.MeshAttachment;
import spine.attachments.PathAttachment;
import spine.attachments.RegionAttachment;
class Skeleton {
private static var quadTriangles:Array<Int> = [0, 1, 2, 2, 3, 0];
private var _data:SkeletonData;
public var bones:Array<Bone>;
@ -611,7 +613,7 @@ class Skeleton {
private var _tempVertices = new Array<Float>();
private var _bounds = new Rectangle();
public function getBounds():Rectangle {
public function getBounds(clipper: SkeletonClipping = null):Rectangle {
var minX:Float = Math.POSITIVE_INFINITY;
var minY:Float = Math.POSITIVE_INFINITY;
var maxX:Float = Math.NEGATIVE_INFINITY;
@ -619,20 +621,33 @@ class Skeleton {
for (slot in drawOrder) {
var verticesLength:Int = 0;
var vertices:Array<Float> = null;
var triangles:Array<Int> = null;
var attachment:Attachment = slot.attachment;
if (Std.isOfType(attachment, RegionAttachment)) {
verticesLength = 8;
_tempVertices.resize(verticesLength);
vertices = _tempVertices;
cast(attachment, RegionAttachment).computeWorldVertices(slot, vertices, 0, 2);
triangles = Skeleton.quadTriangles;
} else if (Std.isOfType(attachment, MeshAttachment)) {
var mesh:MeshAttachment = cast(attachment, MeshAttachment);
verticesLength = mesh.worldVerticesLength;
_tempVertices.resize(verticesLength);
vertices = _tempVertices;
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
triangles = mesh.triangles;
} else if (Std.isOfType(attachment, ClippingAttachment) && clipper != null) {
clipper.clipStart(slot, cast(attachment, ClippingAttachment));
continue;
}
if (vertices != null) {
if (clipper != null && clipper.isClipping()) {
clipper.clipTriangles(vertices, triangles, triangles.length);
vertices = clipper.clippedVertices;
verticesLength = clipper.clippedVertices.length;
}
var ii:Int = 0;
var nn:Int = vertices.length;
while (ii < nn) {
@ -644,7 +659,9 @@ class Skeleton {
ii += 2;
}
}
if (clipper != null) clipper.clipEndWithSlot(slot);
}
if (clipper != null) clipper.clipEnd();
_bounds.x = minX;
_bounds.y = minY;
_bounds.width = maxX - minX;

View File

@ -84,7 +84,91 @@ class SkeletonClipping {
return clipAttachment != null;
}
public function clipTriangles(vertices:Array<Float>, triangles:Array<Int>, trianglesLength:Float, uvs:Array<Float>):Void {
private function clipTrianglesNoRender(vertices:Array<Float>, triangles:Array<Int>, trianglesLength:Float):Void {
var polygonsCount:Int = clippingPolygons.length;
var index:Int = 0;
clippedVertices.resize(0);
clippedUvs.resize(0);
clippedTriangles.resize(0);
var i:Int = 0;
while (i < trianglesLength) {
var vertexOffset:Int = triangles[i] << 1;
var x1:Float = vertices[vertexOffset],
y1:Float = vertices[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
var x2:Float = vertices[vertexOffset],
y2:Float = vertices[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
var x3:Float = vertices[vertexOffset],
y3:Float = vertices[vertexOffset + 1];
for (p in 0...polygonsCount) {
var s:Int = clippedVertices.length;
var clippedVerticesItems:Array<Float>;
var clippedTrianglesItems:Array<Int>;
if (this.clip(x1, y1, x2, y2, x3, y3, clippingPolygons[p], clipOutput)) {
var clipOutputLength:Int = clipOutput.length;
if (clipOutputLength == 0)
continue;
var clipOutputCount:Int = clipOutputLength >> 1;
var clipOutputItems:Array<Float> = clipOutput;
clippedVerticesItems = clippedVertices;
clippedVerticesItems.resize(s + clipOutputLength);
var ii:Int = 0;
while (ii < clipOutputLength) {
var x:Float = clipOutputItems[ii],
y:Float = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
s += 2;
ii += 2;
}
s = clippedTriangles.length;
clippedTrianglesItems = clippedTriangles;
clippedTrianglesItems.resize(s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (ii in 1...clipOutputCount) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + ii);
clippedTrianglesItems[s + 2] = (index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
} else {
clippedVerticesItems = clippedVertices;
clippedVerticesItems.resize(s + 3 * 2);
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.length;
clippedTrianglesItems = clippedTriangles;
clippedTrianglesItems.resize(s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (index + 1);
clippedTrianglesItems[s + 2] = (index + 2);
index += 3;
break;
}
}
i += 3;
}
}
public function clipTriangles(vertices:Array<Float>, triangles:Array<Int>, trianglesLength:Float, uvs:Array<Float> = null):Void {
if (uvs == null) {
clipTrianglesNoRender(vertices, triangles, trianglesLength);
return;
}
var polygonsCount:Int = clippingPolygons.length;
var index:Int = 0;
clippedVertices.resize(0);

View File

@ -66,7 +66,7 @@ class SkeletonSprite extends DisplayObject implements IAnimatable {
private var _smoothing:String = "bilinear";
private static var clipper:SkeletonClipping = new SkeletonClipping();
public static var clipper(default, never):SkeletonClipping = new SkeletonClipping();
private static var QUAD_INDICES:Array<Int> = [0, 1, 2, 2, 3, 0];
private var tempLight:spine.Color = new spine.Color(0, 0, 0);