瀏覽代碼

Merge branch '3.7-beta' into 3.7-beta-cpp

badlogic 7 年之前
父節點
當前提交
8f95417ac3

+ 67 - 68
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/TwoColorPolygonBatch.java

@@ -67,9 +67,13 @@ public class TwoColorPolygonBatch implements Batch {
 	private int blendDstFuncAlpha = GL20.GL_ONE_MINUS_SRC_ALPHA;
 	private int blendDstFuncAlpha = GL20.GL_ONE_MINUS_SRC_ALPHA;
 	private boolean premultipliedAlpha;
 	private boolean premultipliedAlpha;
 
 
-	private float light = Color.WHITE.toFloatBits();
-	private float dark = Color.BLACK.toFloatBits();
-	private Color tempColor = new Color(1, 1, 1, 1);
+	private final Color light = new Color(1, 1, 1, 1);
+	private final Color dark = new Color(0, 0, 0, 1);
+	private float lightPacked = Color.WHITE.toFloatBits();
+	private float darkPacked = Color.BLACK.toFloatBits();
+
+	/** Number of rendering calls, ever. Will not be reset unless set manually. **/
+	public int totalRenderCalls = 0;
 
 
 	public TwoColorPolygonBatch () {
 	public TwoColorPolygonBatch () {
 		this(2000);
 		this(2000);
@@ -122,61 +126,53 @@ public class TwoColorPolygonBatch implements Batch {
 
 
 	@Override
 	@Override
 	public void setColor (Color tint) {
 	public void setColor (Color tint) {
-		light = tint.toFloatBits();
+		light.set(tint);
+		lightPacked = tint.toFloatBits();
 	}
 	}
 
 
 	@Override
 	@Override
 	public void setColor (float r, float g, float b, float a) {
 	public void setColor (float r, float g, float b, float a) {
-		int intBits = (int)(255 * a) << 24 | (int)(255 * b) << 16 | (int)(255 * g) << 8 | (int)(255 * r);
-		light = NumberUtils.intToFloatColor(intBits);
+		light.set(r, g, b, a);
+		lightPacked = light.toFloatBits();
 	}
 	}
 
 
 	@Override
 	@Override
-	public void setColor (float color) {
-		this.light = color;
+	public void setPackedColor (float packedColor) {
+		Color.rgba8888ToColor(light, NumberUtils.floatToIntColor(packedColor));
+		lightPacked = packedColor;
 	}
 	}
 
 
 	@Override
 	@Override
 	public Color getColor () {
 	public Color getColor () {
-		int intBits = NumberUtils.floatToIntColor(light);
-		Color color = this.tempColor;
-		color.r = (intBits & 0xff) / 255f;
-		color.g = ((intBits >>> 8) & 0xff) / 255f;
-		color.b = ((intBits >>> 16) & 0xff) / 255f;
-		color.a = ((intBits >>> 24) & 0xff) / 255f;
-		return color;
+		return light;
 	}
 	}
 
 
 	@Override
 	@Override
 	public float getPackedColor () {
 	public float getPackedColor () {
-		return light;
+		return lightPacked;
 	}
 	}
 
 
 	public void setDarkColor (Color tint) {
 	public void setDarkColor (Color tint) {
-		dark = tint.toFloatBits();
+		dark.set(tint);
+		darkPacked = tint.toFloatBits();
 	}
 	}
 
 
 	public void setDarkColor (float r, float g, float b, float a) {
 	public void setDarkColor (float r, float g, float b, float a) {
-		int intBits = (int)(255 * a) << 24 | (int)(255 * b) << 16 | (int)(255 * g) << 8 | (int)(255 * r);
-		dark = NumberUtils.intToFloatColor(intBits);
+		dark.set(r, g, b, a);
+		darkPacked = dark.toFloatBits();
 	}
 	}
 
 
-	public void setDarkColor (float color) {
-		this.dark = color;
+	public void setPackedDarkColor (float packedColor) {
+		Color.rgba8888ToColor(dark, NumberUtils.floatToIntColor(packedColor));
+		this.darkPacked = packedColor;
 	}
 	}
 
 
 	public Color getDarkColor () {
 	public Color getDarkColor () {
-		int intBits = NumberUtils.floatToIntColor(dark);
-		Color color = this.tempColor;
-		color.r = (intBits & 0xff) / 255f;
-		color.g = ((intBits >>> 8) & 0xff) / 255f;
-		color.b = ((intBits >>> 16) & 0xff) / 255f;
-		color.a = ((intBits >>> 24) & 0xff) / 255f;
-		return color;
+		return dark;
 	}
 	}
 
 
 	public float getPackedDarkColor () {
 	public float getPackedDarkColor () {
-		return dark;
+		return darkPacked;
 	}
 	}
 
 
 	/** Draws a polygon region with the bottom left corner at x,y having the width and height of the region. */
 	/** Draws a polygon region with the bottom left corner at x,y having the width and height of the region. */
@@ -193,7 +189,7 @@ public class TwoColorPolygonBatch implements Batch {
 		if (texture != lastTexture)
 		if (texture != lastTexture)
 			switchTexture(texture);
 			switchTexture(texture);
 		else if (triangleIndex + regionTrianglesLength > triangles.length
 		else if (triangleIndex + regionTrianglesLength > triangles.length
-				|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
+			|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
 
 
 		int triangleIndex = this.triangleIndex;
 		int triangleIndex = this.triangleIndex;
 		int vertexIndex = this.vertexIndex;
 		int vertexIndex = this.vertexIndex;
@@ -204,8 +200,8 @@ public class TwoColorPolygonBatch implements Batch {
 		this.triangleIndex = triangleIndex;
 		this.triangleIndex = triangleIndex;
 
 
 		final float[] vertices = this.vertices;
 		final float[] vertices = this.vertices;
-		final float light = this.light;
-		final float dark = this.dark;
+		final float light = this.lightPacked;
+		final float dark = this.darkPacked;
 		final float[] textureCoords = region.getTextureCoords();
 		final float[] textureCoords = region.getTextureCoords();
 
 
 		for (int i = 0; i < regionVerticesLength; i += 2) {
 		for (int i = 0; i < regionVerticesLength; i += 2) {
@@ -234,7 +230,7 @@ public class TwoColorPolygonBatch implements Batch {
 		if (texture != lastTexture)
 		if (texture != lastTexture)
 			switchTexture(texture);
 			switchTexture(texture);
 		else if (triangleIndex + regionTrianglesLength > triangles.length
 		else if (triangleIndex + regionTrianglesLength > triangles.length
-				|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
+			|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
 
 
 		int triangleIndex = this.triangleIndex;
 		int triangleIndex = this.triangleIndex;
 		int vertexIndex = this.vertexIndex;
 		int vertexIndex = this.vertexIndex;
@@ -245,8 +241,8 @@ public class TwoColorPolygonBatch implements Batch {
 		this.triangleIndex = triangleIndex;
 		this.triangleIndex = triangleIndex;
 
 
 		final float[] vertices = this.vertices;
 		final float[] vertices = this.vertices;
-		final float light = this.light;
-		final float dark = this.dark;
+		final float light = this.lightPacked;
+		final float dark = this.darkPacked;
 		final float[] textureCoords = region.getTextureCoords();
 		final float[] textureCoords = region.getTextureCoords();
 		final float sX = width / textureRegion.getRegionWidth();
 		final float sX = width / textureRegion.getRegionWidth();
 		final float sY = height / textureRegion.getRegionHeight();
 		final float sY = height / textureRegion.getRegionHeight();
@@ -267,7 +263,7 @@ public class TwoColorPolygonBatch implements Batch {
 	 * polygon region should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the
 	 * polygon region should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the
 	 * rectangle around originX, originY. */
 	 * rectangle around originX, originY. */
 	public void draw (PolygonRegion region, float x, float y, float originX, float originY, float width, float height,
 	public void draw (PolygonRegion region, float x, float y, float originX, float originY, float width, float height,
-					  float scaleX, float scaleY, float rotation) {
+		float scaleX, float scaleY, float rotation) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 
 
 		final short[] triangles = this.triangles;
 		final short[] triangles = this.triangles;
@@ -281,7 +277,7 @@ public class TwoColorPolygonBatch implements Batch {
 		if (texture != lastTexture)
 		if (texture != lastTexture)
 			switchTexture(texture);
 			switchTexture(texture);
 		else if (triangleIndex + regionTrianglesLength > triangles.length
 		else if (triangleIndex + regionTrianglesLength > triangles.length
-				|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
+			|| vertexIndex + regionVerticesLength * VERTEX_SIZE / 2 > vertices.length) flush();
 
 
 		int triangleIndex = this.triangleIndex;
 		int triangleIndex = this.triangleIndex;
 		int vertexIndex = this.vertexIndex;
 		int vertexIndex = this.vertexIndex;
@@ -292,8 +288,8 @@ public class TwoColorPolygonBatch implements Batch {
 		this.triangleIndex = triangleIndex;
 		this.triangleIndex = triangleIndex;
 
 
 		final float[] vertices = this.vertices;
 		final float[] vertices = this.vertices;
-		final float light = this.light;
-		final float dark = this.dark;
+		final float light = this.lightPacked;
+		final float dark = this.darkPacked;
 		final float[] textureCoords = region.getTextureCoords();
 		final float[] textureCoords = region.getTextureCoords();
 
 
 		final float worldOriginX = x + originX;
 		final float worldOriginX = x + originX;
@@ -343,7 +339,7 @@ public class TwoColorPolygonBatch implements Batch {
 
 
 	@Override
 	@Override
 	public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX,
 	public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX,
-					  float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) {
+		float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 
 
 		final short[] triangles = this.triangles;
 		final short[] triangles = this.triangles;
@@ -455,8 +451,8 @@ public class TwoColorPolygonBatch implements Batch {
 			v2 = tmp;
 			v2 = tmp;
 		}
 		}
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x1;
 		vertices[idx++] = x1;
 		vertices[idx++] = y1;
 		vertices[idx++] = y1;
@@ -490,7 +486,7 @@ public class TwoColorPolygonBatch implements Batch {
 
 
 	@Override
 	@Override
 	public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth,
 	public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth,
-					  int srcHeight, boolean flipX, boolean flipY) {
+		int srcHeight, boolean flipX, boolean flipY) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 
 
 		final short[] triangles = this.triangles;
 		final short[] triangles = this.triangles;
@@ -530,8 +526,8 @@ public class TwoColorPolygonBatch implements Batch {
 			v2 = tmp;
 			v2 = tmp;
 		}
 		}
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x;
 		vertices[idx++] = x;
 		vertices[idx++] = y;
 		vertices[idx++] = y;
@@ -592,8 +588,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float fx2 = x + srcWidth;
 		final float fx2 = x + srcWidth;
 		final float fy2 = y + srcHeight;
 		final float fy2 = y + srcHeight;
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x;
 		vertices[idx++] = x;
 		vertices[idx++] = y;
 		vertices[idx++] = y;
@@ -650,8 +646,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float fx2 = x + width;
 		final float fx2 = x + width;
 		final float fy2 = y + height;
 		final float fy2 = y + height;
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x;
 		vertices[idx++] = x;
 		vertices[idx++] = y;
 		vertices[idx++] = y;
@@ -717,8 +713,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float u2 = 1;
 		final float u2 = 1;
 		final float v2 = 0;
 		final float v2 = 0;
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x;
 		vertices[idx++] = x;
 		vertices[idx++] = y;
 		vertices[idx++] = y;
@@ -750,8 +746,9 @@ public class TwoColorPolygonBatch implements Batch {
 		this.vertexIndex = idx;
 		this.vertexIndex = idx;
 	}
 	}
 
 
-	/** Draws a rectangle using the given vertices. There must be 4 vertices, each made up of 6 elements in this order: x, y, lightColor, darkColor,
-	 * u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not applied. */
+	/** Draws a rectangle using the given vertices. There must be 4 vertices, each made up of 6 elements in this order: x, y,
+	 * lightColor, darkColor, u, v. The {@link #getColor()} and {@link #getDarkColor()} from the TwoColorPolygonBatch is not
+	 * applied. */
 	@Override
 	@Override
 	public void draw (Texture texture, float[] spriteVertices, int offset, int count) {
 	public void draw (Texture texture, float[] spriteVertices, int offset, int count) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
@@ -832,8 +829,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float u2 = region.getU2();
 		final float u2 = region.getU2();
 		final float v2 = region.getV();
 		final float v2 = region.getV();
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x;
 		vertices[idx++] = x;
 		vertices[idx++] = y;
 		vertices[idx++] = y;
@@ -867,7 +864,7 @@ public class TwoColorPolygonBatch implements Batch {
 
 
 	@Override
 	@Override
 	public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
 	public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
-					  float scaleX, float scaleY, float rotation) {
+		float scaleX, float scaleY, float rotation) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 
 
 		final short[] triangles = this.triangles;
 		final short[] triangles = this.triangles;
@@ -968,8 +965,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float u2 = region.getU2();
 		final float u2 = region.getU2();
 		final float v2 = region.getV();
 		final float v2 = region.getV();
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x1;
 		vertices[idx++] = x1;
 		vertices[idx++] = y1;
 		vertices[idx++] = y1;
@@ -1003,7 +1000,7 @@ public class TwoColorPolygonBatch implements Batch {
 
 
 	@Override
 	@Override
 	public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
 	public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
-					  float scaleX, float scaleY, float rotation, boolean clockwise) {
+		float scaleX, float scaleY, float rotation, boolean clockwise) {
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 		if (!drawing) throw new IllegalStateException("begin must be called before draw.");
 
 
 		final short[] triangles = this.triangles;
 		final short[] triangles = this.triangles;
@@ -1120,8 +1117,8 @@ public class TwoColorPolygonBatch implements Batch {
 			v4 = region.getV2();
 			v4 = region.getV2();
 		}
 		}
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = this.vertexIndex;
 		int idx = this.vertexIndex;
 		vertices[idx++] = x1;
 		vertices[idx++] = x1;
 		vertices[idx++] = y1;
 		vertices[idx++] = y1;
@@ -1191,8 +1188,8 @@ public class TwoColorPolygonBatch implements Batch {
 		final float u2 = region.getU2();
 		final float u2 = region.getU2();
 		final float v2 = region.getV();
 		final float v2 = region.getV();
 
 
-		float light = this.light;
-		float dark = this.dark;
+		float light = this.lightPacked;
+		float dark = this.darkPacked;
 		int idx = vertexIndex;
 		int idx = vertexIndex;
 		vertices[idx++] = x1;
 		vertices[idx++] = x1;
 		vertices[idx++] = y1;
 		vertices[idx++] = y1;
@@ -1228,6 +1225,8 @@ public class TwoColorPolygonBatch implements Batch {
 	public void flush () {
 	public void flush () {
 		if (vertexIndex == 0) return;
 		if (vertexIndex == 0) return;
 
 
+		totalRenderCalls++;
+
 		lastTexture.bind();
 		lastTexture.bind();
 		Mesh mesh = this.mesh;
 		Mesh mesh = this.mesh;
 		mesh.setVertices(vertices, 0, vertexIndex);
 		mesh.setVertices(vertices, 0, vertexIndex);
@@ -1241,13 +1240,13 @@ public class TwoColorPolygonBatch implements Batch {
 	}
 	}
 
 
 	@Override
 	@Override
-	public void disableBlending() {
+	public void disableBlending () {
 		flush();
 		flush();
 		blendingDisabled = true;
 		blendingDisabled = true;
 	}
 	}
 
 
 	@Override
 	@Override
-	public void enableBlending() {
+	public void enableBlending () {
 		flush();
 		flush();
 		blendingDisabled = false;
 		blendingDisabled = false;
 	}
 	}
@@ -1323,7 +1322,7 @@ public class TwoColorPolygonBatch implements Batch {
 	}
 	}
 
 
 	@Override
 	@Override
-	public ShaderProgram getShader() {
+	public ShaderProgram getShader () {
 		return shader;
 		return shader;
 	}
 	}
 
 
@@ -1366,12 +1365,12 @@ public class TwoColorPolygonBatch implements Batch {
 	}
 	}
 
 
 	@Override
 	@Override
-	public int getBlendSrcFuncAlpha() {
+	public int getBlendSrcFuncAlpha () {
 		return blendSrcFuncAlpha;
 		return blendSrcFuncAlpha;
 	}
 	}
 
 
 	@Override
 	@Override
-	public int getBlendDstFuncAlpha() {
+	public int getBlendDstFuncAlpha () {
 		return blendDstFuncAlpha;
 		return blendDstFuncAlpha;
 	}
 	}
 
 

+ 2 - 13
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Menus.cs

@@ -37,23 +37,12 @@ namespace Spine.Unity.Editor {
 	public static class Menus {
 	public static class Menus {
 		[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
 		[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
 		static public void CreateSkeletonRendererGameObject () {
 		static public void CreateSkeletonRendererGameObject () {
-			CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
+			SpineEditorUtilities.EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
 		}
 		}
 
 
 		[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
 		[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
 		static public void CreateSkeletonAnimationGameObject () {
 		static public void CreateSkeletonAnimationGameObject () {
-			CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
-		}
-
-		static void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
-			var parentGameObject = Selection.activeObject as GameObject;
-			var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
-
-			var gameObject = new GameObject(name, typeof(T));
-			gameObject.transform.SetParent(parentTransform, false);
-			EditorUtility.FocusProjectWindow();
-			Selection.activeObject = gameObject;
-			EditorGUIUtility.PingObject(Selection.activeObject);
+			SpineEditorUtilities.EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
 		}
 		}
 	}
 	}
 }
 }

+ 20 - 28
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs

@@ -1165,13 +1165,13 @@ namespace Spine.Unity.Editor {
 			var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex];
 			var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex];
 			var bone = skeleton.Bones.Items[timeline.BoneIndex];
 			var bone = skeleton.Bones.Items[timeline.BoneIndex];
 
 
-			AnimationCurve curve = new AnimationCurve();
+			var curve = new AnimationCurve();
 
 
 			float endTime = timeline.Frames[(timeline.FrameCount * 2) - 2];
 			float endTime = timeline.Frames[(timeline.FrameCount * 2) - 2];
 
 
 			float currentTime = timeline.Frames[0];
 			float currentTime = timeline.Frames[0];
 
 
-			List<Keyframe> keys = new List<Keyframe>();
+			var keys = new List<Keyframe>();
 
 
 			float rotation = timeline.Frames[1] + boneData.Rotation;
 			float rotation = timeline.Frames[1] + boneData.Rotation;
 
 
@@ -1296,35 +1296,27 @@ namespace Spine.Unity.Editor {
 		}
 		}
 
 
 		static void ParseEventTimeline (EventTimeline timeline, AnimationClip clip, SendMessageOptions eventOptions) {
 		static void ParseEventTimeline (EventTimeline timeline, AnimationClip clip, SendMessageOptions eventOptions) {
-
 			float[] frames = timeline.Frames;
 			float[] frames = timeline.Frames;
 			var events = timeline.Events;
 			var events = timeline.Events;
 
 
-			List<AnimationEvent> animEvents = new List<AnimationEvent>();
-			for (int i = 0; i < frames.Length; i++) {
-				var ev = events[i];
-
-				AnimationEvent ae = new AnimationEvent();
-				//MITCH: left todo:  Deal with Mecanim's zero-time missed event
-				ae.time = frames[i];
-				ae.functionName = ev.Data.Name;
-				ae.messageOptions = eventOptions;
-
-				if (!string.IsNullOrEmpty(ev.String)) {
-					ae.stringParameter = ev.String;
-				} else {
-					if (ev.Int == 0 && ev.Float == 0) {
-						//do nothing, raw function
-					} else {
-						if (ev.Int != 0)
-							ae.floatParameter = (float)ev.Int;
-						else
-							ae.floatParameter = ev.Float;
-					}
-
-				}
-
-				animEvents.Add(ae);
+			var animEvents = new List<AnimationEvent>();
+			for (int i = 0, n = frames.Length; i < n; i++) {
+				var spineEvent = events[i];
+				var unityAnimationEvent = new AnimationEvent {
+					time = frames[i],
+					functionName = spineEvent.Data.Name,
+					messageOptions = eventOptions
+				};
+
+				if (!string.IsNullOrEmpty(spineEvent.String)) {
+					unityAnimationEvent.stringParameter = spineEvent.String;
+				} else if (spineEvent.Int != 0) {
+					unityAnimationEvent.intParameter = spineEvent.Int;
+				} else if (spineEvent.Float != 0) {
+					unityAnimationEvent.floatParameter = spineEvent.Float;
+				} // else, paramless function/Action.
+
+				animEvents.Add(unityAnimationEvent);
 			}
 			}
 
 
 			AnimationUtility.SetAnimationEvents(clip, animEvents.ToArray());
 			AnimationUtility.SetAnimationEvents(clip, animEvents.ToArray());

+ 13 - 2
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs

@@ -84,7 +84,6 @@ namespace Spine.Unity.Editor {
 			public static Texture2D skeletonDataAssetIcon;
 			public static Texture2D skeletonDataAssetIcon;
 			public static Texture2D info;
 			public static Texture2D info;
 			public static Texture2D unity;
 			public static Texture2D unity;
-//			public static Texture2D controllerIcon;
 
 
 			static Texture2D LoadIcon (string filename) {
 			static Texture2D LoadIcon (string filename) {
 				return (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/" + filename);
 				return (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/" + filename);
@@ -131,7 +130,6 @@ namespace Spine.Unity.Editor {
 
 
 				info = EditorGUIUtility.FindTexture("console.infoicon.sml");
 				info = EditorGUIUtility.FindTexture("console.infoicon.sml");
 				unity = EditorGUIUtility.FindTexture("SceneAsset Icon");
 				unity = EditorGUIUtility.FindTexture("SceneAsset Icon");
-//				controllerIcon = EditorGUIUtility.FindTexture("AnimatorController Icon");
 			}
 			}
 
 
 			public static Texture2D GetAttachmentIcon (Attachment attachment) {
 			public static Texture2D GetAttachmentIcon (Attachment attachment) {
@@ -381,6 +379,8 @@ namespace Spine.Unity.Editor {
 
 
 				foreach (var sr in activeSkeletonRenderers) {
 				foreach (var sr in activeSkeletonRenderers) {
 					sr.Initialize(true);
 					sr.Initialize(true);
+					//Debug.Log(sr.name);
+					//Debug.Log(sr.valid);
 				}
 				}
 
 
 				foreach (var sg in activeSkeletonGraphics) {
 				foreach (var sg in activeSkeletonGraphics) {
@@ -1227,6 +1227,17 @@ namespace Spine.Unity.Editor {
 				return newSkeletonAnimation;
 				return newSkeletonAnimation;
 			}
 			}
 
 
+			public static void InstantiateEmptySpineGameObject<T> (string name) where T : MonoBehaviour {
+				var parentGameObject = Selection.activeObject as GameObject;
+				var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
+
+				var gameObject = new GameObject(name, typeof(T));
+				gameObject.transform.SetParent(parentTransform, false);
+				EditorUtility.FocusProjectWindow();
+				Selection.activeObject = gameObject;
+				EditorGUIUtility.PingObject(Selection.activeObject);
+			}
+
 			#region SkeletonMecanim
 			#region SkeletonMecanim
 			#if SPINE_SKELETONMECANIM
 			#if SPINE_SKELETONMECANIM
 			public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, string skinName) {
 			public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, string skinName) {

+ 10 - 7
spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs

@@ -38,17 +38,20 @@ namespace Spine.Unity.Modules {
 		SpineInspectorUtility.SerializedSortingProperties sortingProperties;
 		SpineInspectorUtility.SerializedSortingProperties sortingProperties;
 
 
 		void OnEnable () {			
 		void OnEnable () {			
-			sortingProperties = new SpineInspectorUtility.SerializedSortingProperties((target as Component).GetComponent<MeshRenderer>());
+			sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(SpineInspectorUtility.GetRenderersSerializedObject(serializedObject));
 		}
 		}
 
 
 		public override void OnInspectorGUI () {
 		public override void OnInspectorGUI () {
 			SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
 			SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
-			EditorGUILayout.Space();
-			if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Select SkeletonRenderer", SpineEditorUtilities.Icons.spine))) {
-				var thisSkeletonPartsRenderer = target as SkeletonPartsRenderer;
-				var srs = thisSkeletonPartsRenderer.GetComponentInParent<SkeletonRenderSeparator>();
-				if (srs != null && srs.partsRenderers.Contains(thisSkeletonPartsRenderer) && srs.SkeletonRenderer != null)
-					Selection.activeGameObject = srs.SkeletonRenderer.gameObject;
+
+			if (!serializedObject.isEditingMultipleObjects) {
+				EditorGUILayout.Space();
+				if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Select SkeletonRenderer", SpineEditorUtilities.Icons.spine))) {
+					var thisSkeletonPartsRenderer = target as SkeletonPartsRenderer;
+					var srs = thisSkeletonPartsRenderer.GetComponentInParent<SkeletonRenderSeparator>();
+					if (srs != null && srs.partsRenderers.Contains(thisSkeletonPartsRenderer) && srs.SkeletonRenderer != null)
+						Selection.activeGameObject = srs.SkeletonRenderer.gameObject;
+				}
 			}
 			}
 		}
 		}
 	}
 	}

+ 1 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/SkeletonDataAsset.cs

@@ -100,6 +100,7 @@ namespace Spine.Unity {
 			stateData = null;
 			stateData = null;
 		}
 		}
 
 
+		/// <summary>Loads, caches and returns the SkeletonData from the skeleton data file. Returns the cached SkeletonData after the first time it is called. Pass false to prevent direct errors from being logged.</summary>
 		public SkeletonData GetSkeletonData (bool quiet) {
 		public SkeletonData GetSkeletonData (bool quiet) {
 			if (skeletonJSON == null) {
 			if (skeletonJSON == null) {
 				if (!quiet)
 				if (!quiet)

+ 0 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AnimationMatchModifier/AnimationMatchModifierAsset.cs

@@ -206,7 +206,6 @@ namespace Spine.Unity.Modules {
 				var t = new DeformTimeline(1);
 				var t = new DeformTimeline(1);
 				t.slotIndex = timeline.slotIndex;
 				t.slotIndex = timeline.slotIndex;
 				t.attachment = timeline.attachment;
 				t.attachment = timeline.attachment;
-				var slotData = skeletonData.slots.Items[t.slotIndex];
 
 
 				if (t.attachment.IsWeighted()) {
 				if (t.attachment.IsWeighted()) {
 					t.SetFrame(0, 0, new float[t.attachment.vertices.Length]);
 					t.SetFrame(0, 0, new float[t.attachment.vertices.Length]);

+ 14 - 6
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs

@@ -952,7 +952,7 @@ namespace Spine.Unity.Modules.AttachmentTools {
 		}
 		}
 
 
 		public static MeshAttachment GetLinkedClone (this MeshAttachment o, bool inheritDeform = true) {
 		public static MeshAttachment GetLinkedClone (this MeshAttachment o, bool inheritDeform = true) {
-			return o.GetLinkedMesh(o.Name, o.RendererObject as AtlasRegion, inheritDeform);
+			return o.GetLinkedMesh(o.Name, o.RendererObject as AtlasRegion, inheritDeform, copyOriginalProperties: true);
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -1026,7 +1026,7 @@ namespace Spine.Unity.Modules.AttachmentTools {
 		#region Runtime Linked MeshAttachments
 		#region Runtime Linked MeshAttachments
 		/// <summary>
 		/// <summary>
 		/// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to the AtlasRegion provided.</summary>
 		/// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to the AtlasRegion provided.</summary>
-		public static MeshAttachment GetLinkedMesh (this MeshAttachment o, string newLinkedMeshName, AtlasRegion region, bool inheritDeform = true) {
+		public static MeshAttachment GetLinkedMesh (this MeshAttachment o, string newLinkedMeshName, AtlasRegion region, bool inheritDeform = true, bool copyOriginalProperties = false) {
 			//if (string.IsNullOrEmpty(attachmentName)) throw new System.ArgumentException("attachmentName cannot be null or empty", "attachmentName");
 			//if (string.IsNullOrEmpty(attachmentName)) throw new System.ArgumentException("attachmentName cannot be null or empty", "attachmentName");
 			if (region == null) throw new System.ArgumentNullException("region");
 			if (region == null) throw new System.ArgumentNullException("region");
 
 
@@ -1040,10 +1040,18 @@ namespace Spine.Unity.Modules.AttachmentTools {
 
 
 			// 2. (SkeletonJson.cs::ReadAttachment. case: LinkedMesh)
 			// 2. (SkeletonJson.cs::ReadAttachment. case: LinkedMesh)
 			mesh.Path = newLinkedMeshName;
 			mesh.Path = newLinkedMeshName;
-			mesh.r = 1f;
-			mesh.g = 1f;
-			mesh.b = 1f;
-			mesh.a = 1f;
+			if (copyOriginalProperties) {
+				mesh.r = o.r;
+				mesh.g = o.g;
+				mesh.b = o.b;
+				mesh.a = o.a;
+			} else {
+				mesh.r = 1f;
+				mesh.g = 1f;
+				mesh.b = 1f;
+				mesh.a = 1f;
+			}
+			
 			//mesh.ParentMesh property call below sets mesh.Width and mesh.Height
 			//mesh.ParentMesh property call below sets mesh.Width and mesh.Height
 
 
 			// 3. Link mesh with parent. (SkeletonJson.cs)
 			// 3. Link mesh with parent. (SkeletonJson.cs)

+ 1 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs

@@ -145,6 +145,7 @@ namespace Spine.Unity {
 				if (boundingBoxAttachment != null) {
 				if (boundingBoxAttachment != null) {
 					if (!colliderTable.ContainsKey(boundingBoxAttachment)) {
 					if (!colliderTable.ContainsKey(boundingBoxAttachment)) {
 						var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(boundingBoxAttachment, slot, gameObject, isTrigger);
 						var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(boundingBoxAttachment, slot, gameObject, isTrigger);
+
 						bbCollider.enabled = false;
 						bbCollider.enabled = false;
 						bbCollider.hideFlags = HideFlags.NotEditable;
 						bbCollider.hideFlags = HideFlags.NotEditable;
 						bbCollider.isTrigger = IsTrigger;
 						bbCollider.isTrigger = IsTrigger;

+ 10 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs

@@ -362,19 +362,25 @@ namespace Spine.Unity.Modules {
 			var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
 			var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
 
 
 			var attachments = new List<Attachment>();
 			var attachments = new List<Attachment>();
-			foreach (Slot s in skeleton.Slots) {
-				if (s.bone == b) {
-					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+			foreach (Slot slot in skeleton.Slots) {
+				if (slot.bone == b) {
+					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(slot), attachments);
+
+					bool bbAttachmentAdded = false;
 					foreach (var a in attachments) {
 					foreach (var a in attachments) {
 						var bbAttachment = a as BoundingBoxAttachment;
 						var bbAttachment = a as BoundingBoxAttachment;
 						if (bbAttachment != null) {
 						if (bbAttachment != null) {
 							if (!a.Name.ToLower().Contains(AttachmentNameMarker))
 							if (!a.Name.ToLower().Contains(AttachmentNameMarker))
 								continue;
 								continue;
 
 
-							var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, s, go, isTrigger: false, isKinematic: false, gravityScale: gravityScale);
+							bbAttachmentAdded = true;
+							var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, slot, go, isTrigger: false);
 							colliders.Add(bbCollider);
 							colliders.Add(bbCollider);
 						}
 						}
 					}
 					}
+
+					if (bbAttachmentAdded)
+						SkeletonUtility.AddBoneRigidbody2D(go, isKinematic: false, gravityScale: gravityScale);
 				}
 				}
 			}
 			}
 
 

+ 4 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs

@@ -614,7 +614,7 @@ namespace Spine {
 			animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In);
 			animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In);
 		}
 		}
 
 
-		/// <summary>Pose a skeleton according to a given time in an animation.</summary>
+		/// <summary>Pose a skeleton according to a given time in an animation. This is the simplified version of Animation.Apply(skeleton).</summary>
 		public static void PoseSkeleton (this Animation animation, Skeleton skeleton, float time, bool loop = false) {
 		public static void PoseSkeleton (this Animation animation, Skeleton skeleton, float time, bool loop = false) {
 			animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In);
 			animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In);
 		}
 		}
@@ -624,6 +624,9 @@ namespace Spine {
 			animation.Apply(skeleton, 0, 0, false, null, 0, MixBlend.Setup, MixDirection.Out);
 			animation.Apply(skeleton, 0, 0, false, null, 0, MixBlend.Setup, MixDirection.Out);
 		}
 		}
 
 
+		public static void AllowImmediateQueue (this TrackEntry trackEntry) {
+			if (trackEntry.nextTrackLast < 0) trackEntry.nextTrackLast = 0;
+		}
 
 
 		#endregion
 		#endregion
 
 

+ 11 - 11
spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtility.cs

@@ -73,18 +73,8 @@ namespace Spine.Unity {
 			return AddBoundingBoxAsComponent(box, slot, go, isTrigger);
 			return AddBoundingBoxAsComponent(box, slot, go, isTrigger);
 		}
 		}
 
 
-		public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true, bool isKinematic = true, float gravityScale = 0f) {
+		public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true) {
 			if (box == null) return null;
 			if (box == null) return null;
-
-			if (slot.bone != slot.Skeleton.RootBone) {
-				var rb = gameObject.GetComponent<Rigidbody2D>();
-				if (rb == null) {
-					rb = gameObject.AddComponent<Rigidbody2D>();
-					rb.isKinematic = isKinematic;
-					rb.gravityScale = gravityScale;
-				}
-			}
-
 			var collider = gameObject.AddComponent<PolygonCollider2D>();
 			var collider = gameObject.AddComponent<PolygonCollider2D>();
 			collider.isTrigger = isTrigger;
 			collider.isTrigger = isTrigger;
 			SetColliderPointsLocal(collider, slot, box);
 			SetColliderPointsLocal(collider, slot, box);
@@ -114,6 +104,16 @@ namespace Spine.Unity {
 
 
 			return bounds;
 			return bounds;
 		}
 		}
+
+		public static Rigidbody2D AddBoneRigidbody2D (GameObject gameObject, bool isKinematic = true, float gravityScale = 0f) {
+			var rb = gameObject.GetComponent<Rigidbody2D>();
+			if (rb == null) {
+				rb = gameObject.AddComponent<Rigidbody2D>();
+				rb.isKinematic = isKinematic;
+				rb.gravityScale = gravityScale;
+			}
+			return rb;
+		}
 		#endregion
 		#endregion
 
 
 		public delegate void SkeletonUtilityDelegate ();
 		public delegate void SkeletonUtilityDelegate ();

+ 1 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs

@@ -222,6 +222,7 @@ namespace Spine.Unity {
 		}
 		}
 
 
 		public void AddBoundingBox (string skinName, string slotName, string attachmentName) {
 		public void AddBoundingBox (string skinName, string slotName, string attachmentName) {
+			SkeletonUtility.AddBoneRigidbody2D(transform.gameObject);
 			SkeletonUtility.AddBoundingBoxGameObject(bone.skeleton, skinName, slotName, attachmentName, transform);
 			SkeletonUtility.AddBoundingBoxGameObject(bone.skeleton, skinName, slotName, attachmentName, transform);
 		}
 		}