浏览代码

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

Davide Tantillo 1 年之前
父节点
当前提交
eb80431642

+ 18 - 1
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<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;

+ 85 - 1
spine-haxe/spine-haxe/spine/SkeletonClipping.hx

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

+ 1 - 1
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<Int> = [0, 1, 2, 2, 3, 0];
 
 	private var tempLight:spine.Color = new spine.Color(0, 0, 0);