From eb8043164244aa266d0841f4a7a9f1b908c9a60a Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Sat, 4 May 2024 12:01:20 +0200 Subject: [PATCH] [haxe] Skeleton.getBounds() applies clipping, see #2515. Port of commits b043e5c, 637321a and 2049bed. --- spine-haxe/spine-haxe/spine/Skeleton.hx | 19 +++- .../spine-haxe/spine/SkeletonClipping.hx | 86 ++++++++++++++++++- .../spine/starling/SkeletonSprite.hx | 2 +- 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/spine-haxe/spine-haxe/spine/Skeleton.hx b/spine-haxe/spine-haxe/spine/Skeleton.hx index 89651e826..c4ca11604 100644 --- a/spine-haxe/spine-haxe/spine/Skeleton.hx +++ b/spine-haxe/spine-haxe/spine/Skeleton.hx @@ -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 = [0, 1, 2, 2, 3, 0]; private var _data:SkeletonData; public var bones:Array; @@ -611,7 +613,7 @@ class Skeleton { private var _tempVertices = new Array(); 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 = null; + var triangles:Array = 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; diff --git a/spine-haxe/spine-haxe/spine/SkeletonClipping.hx b/spine-haxe/spine-haxe/spine/SkeletonClipping.hx index 6289220ef..d6edcea2e 100644 --- a/spine-haxe/spine-haxe/spine/SkeletonClipping.hx +++ b/spine-haxe/spine-haxe/spine/SkeletonClipping.hx @@ -84,7 +84,91 @@ class SkeletonClipping { return clipAttachment != null; } - public function clipTriangles(vertices:Array, triangles:Array, trianglesLength:Float, uvs:Array):Void { + private function clipTrianglesNoRender(vertices:Array, triangles:Array, 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; + var clippedTrianglesItems:Array; + 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 = 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, triangles:Array, trianglesLength:Float, uvs:Array = null):Void { + if (uvs == null) { + clipTrianglesNoRender(vertices, triangles, trianglesLength); + return; + } + var polygonsCount:Int = clippingPolygons.length; var index:Int = 0; clippedVertices.resize(0); diff --git a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx index b424b3e52..f8a673072 100644 --- a/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx +++ b/spine-haxe/spine-haxe/spine/starling/SkeletonSprite.hx @@ -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 = [0, 1, 2, 2, 3, 0]; private var tempLight:spine.Color = new spine.Color(0, 0, 0);