Quellcode durchsuchen

[unity] Update API use and compatibility notes to 3.7.

pharan vor 7 Jahren
Ursprung
Commit
2fad707529

+ 6 - 6
spine-unity/Assets/spine-unity/Components/SkeletonAnimator.cs

@@ -201,12 +201,12 @@ namespace Spine.Unity {
 						// Always use Mix instead of Applying the first non-zero weighted clip.
 						// Always use Mix instead of Applying the first non-zero weighted clip.
 						for (int c = 0; c < clipInfoCount; c++) {
 						for (int c = 0; c < clipInfoCount; c++) {
 							var info = clipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
 							var info = clipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
-							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
 						}
 						}
 						if (hasNext) {
 						if (hasNext) {
 							for (int c = 0; c < nextClipInfoCount; c++) {
 							for (int c = 0; c < nextClipInfoCount; c++) {
 								var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
 								var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
 							}
 							}
 						}
 						}
 					} else { // case MixNext || SpineStyle
 					} else { // case MixNext || SpineStyle
@@ -214,13 +214,13 @@ namespace Spine.Unity {
 						int c = 0;
 						int c = 0;
 						for (; c < clipInfoCount; c++) {
 						for (; c < clipInfoCount; c++) {
 							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
 							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, 1f, MixBlend.Replace, MixDirection.In);
 							break;
 							break;
 						}
 						}
 						// Mix the rest
 						// Mix the rest
 						for (; c < clipInfoCount; c++) {
 						for (; c < clipInfoCount; c++) {
 							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
 							var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+							animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
 						}
 						}
 
 
 						c = 0;
 						c = 0;
@@ -229,14 +229,14 @@ namespace Spine.Unity {
 							if (mode == MixMode.SpineStyle) {
 							if (mode == MixMode.SpineStyle) {
 								for (; c < nextClipInfoCount; c++) {
 								for (; c < nextClipInfoCount; c++) {
 									var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
 									var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
-									animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
+									animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, MixBlend.Replace, MixDirection.In);
 									break;
 									break;
 								}
 								}
 							}
 							}
 							// Mix the rest
 							// Mix the rest
 							for (; c < nextClipInfoCount; c++) {
 							for (; c < nextClipInfoCount; c++) {
 								var info = nextClipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
 								var info = nextClipInfo[c];	float weight = info.weight * layerWeight; if (weight == 0) continue;
-								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
+								animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
 							}
 							}
 						}
 						}
 					}
 					}

+ 1 - 0
spine-unity/Assets/spine-unity/Components/SkeletonRenderer.cs

@@ -317,6 +317,7 @@ namespace Spine.Unity {
 				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
 				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
 			}
 			}
 
 
+			meshGenerator.FillLateVertexData(currentMesh);
 
 
 			// STEP 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. ===========
 			// STEP 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. ===========
 			meshFilter.sharedMesh = currentMesh;
 			meshFilter.sharedMesh = currentMesh;

+ 10 - 10
spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs

@@ -1053,7 +1053,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1080,7 +1080,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1099,7 +1099,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 						if (i == steps)
 							currentTime = time;
 							currentTime = time;
 
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 						px = xKeys[listIndex - 1];
 						px = xKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
@@ -1196,7 +1196,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1223,7 +1223,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1241,7 +1241,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 						if (i == steps)
 							currentTime = time;
 							currentTime = time;
 
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 						px = xKeys[listIndex - 1];
 						px = xKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
 						py = yKeys[listIndex - 1];
@@ -1325,7 +1325,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1350,7 +1350,7 @@ namespace Spine.Unity.Editor {
 
 
 					currentTime = time;
 					currentTime = time;
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 
 
 					lastTime = time;
 					lastTime = time;
 					listIndex++;
 					listIndex++;
@@ -1360,7 +1360,7 @@ namespace Spine.Unity.Editor {
 
 
 					float time = frames[f];
 					float time = frames[f];
 
 
-					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+					timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 					skeleton.UpdateWorldTransform();
 					skeleton.UpdateWorldTransform();
 
 
 					rotation = frames[f + 1] + boneData.Rotation;
 					rotation = frames[f + 1] + boneData.Rotation;
@@ -1374,7 +1374,7 @@ namespace Spine.Unity.Editor {
 						if (i == steps)
 						if (i == steps)
 							currentTime = time;
 							currentTime = time;
 
 
-						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
+						timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
 						skeleton.UpdateWorldTransform();
 						skeleton.UpdateWorldTransform();
 						pk = keys[listIndex - 1];
 						pk = keys[listIndex - 1];
 
 

+ 6 - 5
spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs

@@ -370,9 +370,9 @@ namespace Spine.Unity.Editor {
 			}
 			}
 
 
 			EditorGUILayout.LabelField("Name", "      Duration");
 			EditorGUILayout.LabelField("Name", "      Duration");
-			bool nonessential = targetSkeletonData.ImagesPath != null; // Currently the only way to determine if skeleton data has nonessential data. (Spine 3.6)
-			float fps = targetSkeletonData.Fps;
-			if (nonessential && fps == 0) fps = 30;
+			//bool nonessential = targetSkeletonData.ImagesPath != null; // Currently the only way to determine if skeleton data has nonessential data. (Spine 3.6)
+			//float fps = targetSkeletonData.Fps;
+			//if (nonessential && fps == 0) fps = 30;
 
 
 			var activeTrack = preview.ActiveTrack;
 			var activeTrack = preview.ActiveTrack;
 			foreach (Animation animation in targetSkeletonData.Animations) {
 			foreach (Animation animation in targetSkeletonData.Animations) {
@@ -387,8 +387,9 @@ namespace Spine.Unity.Editor {
 					} else {
 					} else {
 						GUILayout.Label("-", GUILayout.Width(24));
 						GUILayout.Label("-", GUILayout.Width(24));
 					}
 					}
-					string frameCountString = (fps > 0) ? ("(" + (Mathf.RoundToInt(animation.Duration * fps)) + ")").PadLeft(12, ' ') : string.Empty;
-					EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s" + frameCountString));
+					//string frameCountString = (fps > 0) ? ("(" + (Mathf.RoundToInt(animation.Duration * fps)) + ")").PadLeft(12, ' ') : string.Empty;
+					//EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s" + frameCountString));
+					EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s"));
 				}
 				}
 			}
 			}
 		}
 		}

+ 1 - 1
spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs

@@ -374,7 +374,7 @@ namespace Spine.Unity.Editor {
 
 
 										EditorGUI.BeginChangeCheck();
 										EditorGUI.BeginChangeCheck();
 										c.Mix = EditorGUILayout.Slider("Mix", c.Mix, MixMin, MixMax);
 										c.Mix = EditorGUILayout.Slider("Mix", c.Mix, MixMin, MixMax);
-										c.BendDirection = EditorGUILayout.Toggle("Bend Direction +", c.BendDirection > 0) ? 1 : -1;
+										c.BendDirection = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bend Clockwise", tooltip: "IkConstraint.BendDirection == 1 if clockwise; -1 if counterclockwise."), c.BendDirection > 0) ? 1 : -1;
 										if (EditorGUI.EndChangeCheck())	requireRepaint = true;
 										if (EditorGUI.EndChangeCheck())	requireRepaint = true;
 
 
 										EditorGUILayout.Space();
 										EditorGUILayout.Space();

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

@@ -1240,8 +1240,8 @@ namespace Spine.Unity.Editor {
 		#endregion
 		#endregion
 
 
 		#region Checking Methods
 		#region Checking Methods
-		static int[][] compatibleBinaryVersions = { new[] {3, 6, 0}, new[] {3, 5, 0} };
-		static int[][] compatibleJsonVersions = { new[] { 3, 6, 0 }, new[] { 3, 7, 0 }, new[] { 3, 5, 0 } };
+		static int[][] compatibleBinaryVersions = { new[] {3, 7, 0} };
+		static int[][] compatibleJsonVersions = { new[] { 3, 7, 0 }, new[] { 3, 6, 0 }, new[] { 3, 5, 0 } };
 		//static bool isFixVersionRequired = false;
 		//static bool isFixVersionRequired = false;
 
 
 		static bool CheckForValidSkeletonData (string skeletonJSONPath) {
 		static bool CheckForValidSkeletonData (string skeletonJSONPath) {

+ 52 - 46
spine-unity/Assets/spine-unity/Mesh Generation/SpineMesh.cs

@@ -50,13 +50,13 @@ namespace Spine.Unity {
 		}
 		}
 	}
 	}
 
 
-	/// <summary>Instructions for how to generate a mesh or submesh out of a range of slots in a given skeleton.</summary>
+	/// <summary>Instructions for how to generate a mesh or submesh: "Render this skeleton's slots: start slot, up to but not including endSlot, using this material."</summary>
 	public struct SubmeshInstruction {
 	public struct SubmeshInstruction {
 		public Skeleton skeleton;
 		public Skeleton skeleton;
 		public int startSlot;
 		public int startSlot;
 		public int endSlot;
 		public int endSlot;
-
 		public Material material;
 		public Material material;
+
 		public bool forceSeparate;
 		public bool forceSeparate;
 		public int preActiveClippingSlotSource;
 		public int preActiveClippingSlotSource;
 
 
@@ -206,35 +206,35 @@ namespace Spine.Unity {
 			bool skeletonHasClipping = false;
 			bool skeletonHasClipping = false;
 			var drawOrderItems = drawOrder.Items;
 			var drawOrderItems = drawOrder.Items;
 			for (int i = 0; i < drawOrderCount; i++) {
 			for (int i = 0; i < drawOrderCount; i++) {
-			Slot slot = drawOrderItems[i];
-			Attachment attachment = slot.attachment;
-
-			workingAttachmentsItems[i] = attachment;
-			int attachmentTriangleCount;
-			int attachmentVertexCount;
-
-			var regionAttachment = attachment as RegionAttachment;
-			if (regionAttachment != null) {
-			attachmentVertexCount = 4;
-			attachmentTriangleCount = 6;
-			} else {
-			var meshAttachment = attachment as MeshAttachment;
-			if (meshAttachment != null) {
-			attachmentVertexCount = meshAttachment.worldVerticesLength >> 1;
-			attachmentTriangleCount = meshAttachment.triangles.Length;						
-			} else {
-			var clippingAttachment = attachment as ClippingAttachment;
-			if (clippingAttachment != null) {
-			current.hasClipping = true;
-			skeletonHasClipping = true;
-			}
-			attachmentVertexCount = 0;
-			attachmentTriangleCount = 0;
-			}
-			}
-			current.rawTriangleCount += attachmentTriangleCount;
-			current.rawVertexCount += attachmentVertexCount;
-			totalRawVertexCount += attachmentVertexCount;
+				Slot slot = drawOrderItems[i];
+				Attachment attachment = slot.attachment;
+
+				workingAttachmentsItems[i] = attachment;
+				int attachmentTriangleCount;
+				int attachmentVertexCount;
+
+				var regionAttachment = attachment as RegionAttachment;
+				if (regionAttachment != null) {
+					attachmentVertexCount = 4;
+					attachmentTriangleCount = 6;
+				} else {
+					var meshAttachment = attachment as MeshAttachment;
+					if (meshAttachment != null) {
+						attachmentVertexCount = meshAttachment.worldVerticesLength >> 1;
+						attachmentTriangleCount = meshAttachment.triangles.Length;
+					} else {
+						var clippingAttachment = attachment as ClippingAttachment;
+						if (clippingAttachment != null) {
+							current.hasClipping = true;
+							skeletonHasClipping = true;
+						}
+						attachmentVertexCount = 0;
+						attachmentTriangleCount = 0;
+					}
+				}
+				current.rawTriangleCount += attachmentTriangleCount;
+				current.rawVertexCount += attachmentVertexCount;
+				totalRawVertexCount += attachmentVertexCount;
 
 
 			}
 			}
 
 
@@ -448,9 +448,9 @@ namespace Spine.Unity {
 				meshBoundsThickness = 0f;
 				meshBoundsThickness = 0f;
 			}
 			}
 
 
-			submeshes.Count = 1;
-			submeshes.Items[0].Clear(false);
 			submeshIndex = 0;
 			submeshIndex = 0;
+			submeshes.Count = 1;
+			//submeshes.Items[0].Clear(false);
 		}
 		}
 
 
 		public void AddSubmesh (SubmeshInstruction instruction, bool updateTriangles = true) {
 		public void AddSubmesh (SubmeshInstruction instruction, bool updateTriangles = true) {
@@ -500,7 +500,7 @@ namespace Spine.Unity {
 				int attachmentIndexCount;
 				int attachmentIndexCount;
 
 
 				Color c = default(Color);
 				Color c = default(Color);
-
+				
 				// Identify and prepare values.
 				// Identify and prepare values.
 				var region = attachment as RegionAttachment;
 				var region = attachment as RegionAttachment;
 				if (region != null) {
 				if (region != null) {
@@ -969,8 +969,6 @@ namespace Spine.Unity {
 			var vbi = vertexBuffer.Items;
 			var vbi = vertexBuffer.Items;
 			var ubi = uvBuffer.Items;
 			var ubi = uvBuffer.Items;
 			var cbi = colorBuffer.Items;
 			var cbi = colorBuffer.Items;
-			var sbi = submeshes.Items;
-			int submeshCount = submeshes.Count;
 
 
 			// Zero the extra.
 			// Zero the extra.
 			{
 			{
@@ -1020,18 +1018,26 @@ namespace Spine.Unity {
 				if (settings.tintBlack) {
 				if (settings.tintBlack) {
 					mesh.uv2 = this.uv2.Items;
 					mesh.uv2 = this.uv2.Items;
 					mesh.uv3 = this.uv3.Items;
 					mesh.uv3 = this.uv3.Items;
-				}
+				}				
+			}
+		}
 
 
-				if (settings.calculateTangents) {
-					MeshGenerator.SolveTangents2DEnsureSize(ref this.tangents, ref this.tempTanBuffer, vertexCount);
-					for (int i = 0; i < submeshCount; i++) {
-						var submesh = sbi[i].Items;
-						int triangleCount = sbi[i].Count;
-						MeshGenerator.SolveTangents2DTriangles(this.tempTanBuffer, submesh, triangleCount, vbi, ubi, vertexCount);
-					}
-					MeshGenerator.SolveTangents2DBuffer(this.tangents, this.tempTanBuffer, vertexCount);
-					mesh.tangents = this.tangents;
+		public void FillLateVertexData (Mesh mesh) {
+			if (settings.calculateTangents) {
+				int vertexCount = this.vertexBuffer.Count;
+				var sbi = submeshes.Items;
+				int submeshCount = submeshes.Count;
+				var vbi = vertexBuffer.Items;
+				var ubi = uvBuffer.Items;
+
+				MeshGenerator.SolveTangents2DEnsureSize(ref this.tangents, ref this.tempTanBuffer, vertexCount);
+				for (int i = 0; i < submeshCount; i++) {
+					var submesh = sbi[i].Items;
+					int triangleCount = sbi[i].Count;
+					MeshGenerator.SolveTangents2DTriangles(this.tempTanBuffer, submesh, triangleCount, vbi, ubi, vertexCount);
 				}
 				}
+				MeshGenerator.SolveTangents2DBuffer(this.tangents, this.tempTanBuffer, vertexCount);
+				mesh.tangents = this.tangents;
 			}
 			}
 		}
 		}
 
 

+ 3 - 3
spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs

@@ -792,16 +792,16 @@ namespace Spine.Unity.Modules.AttachmentTools {
 
 
 		/// <summary>Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced.</summary>
 		/// <summary>Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced.</summary>
 		public static void SetAttachment (this Skin skin, string slotName, string keyName, Attachment attachment, Skeleton skeleton) {
 		public static void SetAttachment (this Skin skin, string slotName, string keyName, Attachment attachment, Skeleton skeleton) {
-			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			int slotIndex = skeleton.FindSlotIndex(slotName);
 			int slotIndex = skeleton.FindSlotIndex(slotName);
+			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			skin.AddAttachment(slotIndex, keyName, attachment);
 			skin.AddAttachment(slotIndex, keyName, attachment);
 		}
 		}
 
 
 		/// <summary>Gets an attachment from the skin for the specified slot index and name.</summary>
 		/// <summary>Gets an attachment from the skin for the specified slot index and name.</summary>
 		public static Attachment GetAttachment (this Skin skin, string slotName, string keyName, Skeleton skeleton) {
 		public static Attachment GetAttachment (this Skin skin, string slotName, string keyName, Skeleton skeleton) {
-			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			int slotIndex = skeleton.FindSlotIndex(slotName);
 			int slotIndex = skeleton.FindSlotIndex(slotName);
+			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			return skin.GetAttachment(slotIndex, keyName);
 			return skin.GetAttachment(slotIndex, keyName);
 		}
 		}
@@ -813,8 +813,8 @@ namespace Spine.Unity.Modules.AttachmentTools {
 
 
 		/// <summary>Removes the attachment. Returns true if the element is successfully found and removed; otherwise, false.</summary>
 		/// <summary>Removes the attachment. Returns true if the element is successfully found and removed; otherwise, false.</summary>
 		public static bool RemoveAttachment (this Skin skin, string slotName, string keyName, Skeleton skeleton) {
 		public static bool RemoveAttachment (this Skin skin, string slotName, string keyName, Skeleton skeleton) {
-			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			int slotIndex = skeleton.FindSlotIndex(slotName);
 			int slotIndex = skeleton.FindSlotIndex(slotName);
+			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
 			return skin.RemoveAttachment(slotIndex, keyName);
 			return skin.RemoveAttachment(slotIndex, keyName);
 		}
 		}

+ 1 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs

@@ -287,6 +287,7 @@ namespace Spine.Unity {
 			var mesh = smartMesh.mesh;
 			var mesh = smartMesh.mesh;
 			meshGenerator.FillVertexData(mesh);
 			meshGenerator.FillVertexData(mesh);
 			if (updateTriangles) meshGenerator.FillTrianglesSingle(mesh);
 			if (updateTriangles) meshGenerator.FillTrianglesSingle(mesh);
+			meshGenerator.FillLateVertexData(mesh);
 
 
 			canvasRenderer.SetMesh(mesh);
 			canvasRenderer.SetMesh(mesh);
 			smartMesh.instructionUsed.Set(currentInstructions);
 			smartMesh.instructionUsed.Set(currentInstructions);

+ 1 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs

@@ -117,6 +117,7 @@ namespace Spine.Unity.Modules {
 					meshRenderer.sharedMaterials = buffers.GetUpdatedSharedMaterialsArray();
 					meshRenderer.sharedMaterials = buffers.GetUpdatedSharedMaterialsArray();
 				}
 				}
 			}
 			}
+			meshGenerator.FillLateVertexData(mesh);
 
 
 			meshFilter.sharedMesh = mesh;
 			meshFilter.sharedMesh = mesh;
 			smartMesh.instructionUsed.Set(currentInstructions);
 			smartMesh.instructionUsed.Set(currentInstructions);

+ 18 - 5
spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs

@@ -41,6 +41,7 @@ namespace Spine.Unity.Modules {
 		public bool detachedShadow = false;
 		public bool detachedShadow = false;
 		public Transform parent;
 		public Transform parent;
 		public bool hideShadow = true;
 		public bool hideShadow = true;
+		public PhysicsSystem physicsSystem = PhysicsSystem.Physics3D;
 		#endregion
 		#endregion
 
 
 		GameObject shadowRoot;
 		GameObject shadowRoot;
@@ -49,6 +50,11 @@ namespace Spine.Unity.Modules {
 			public Transform dest, src;
 			public Transform dest, src;
 		}
 		}
 
 
+		public enum PhysicsSystem {
+			Physics2D,
+			Physics3D
+		};
+
 		void Start () {
 		void Start () {
 			// Duplicate this gameObject as the "shadow" with a different parent.
 			// Duplicate this gameObject as the "shadow" with a different parent.
 			shadowRoot = Instantiate<GameObject>(this.gameObject);
 			shadowRoot = Instantiate<GameObject>(this.gameObject);
@@ -84,9 +90,10 @@ namespace Spine.Unity.Modules {
 			foreach (var b in bones) {
 			foreach (var b in bones) {
 				if (b.gameObject == this.gameObject)
 				if (b.gameObject == this.gameObject)
 					continue;
 					continue;
-				
+
+				System.Type checkType = (physicsSystem == PhysicsSystem.Physics2D) ? typeof(Rigidbody2D) : typeof(Rigidbody);
 				foreach (var sb in shadowBones) {
 				foreach (var sb in shadowBones) {
-					if (sb.GetComponent<Rigidbody>() != null && sb.boneName == b.boneName) {
+					if (sb.GetComponent(checkType) != null && sb.boneName == b.boneName) {
 						shadowTable.Add(new TransformPair {
 						shadowTable.Add(new TransformPair {
 							dest = b.transform,
 							dest = b.transform,
 							src = sb.transform
 							src = sb.transform
@@ -111,9 +118,15 @@ namespace Spine.Unity.Modules {
 		}
 		}
 
 
 		void FixedUpdate () {
 		void FixedUpdate () {
-			var shadowRootRigidbody = shadowRoot.GetComponent<Rigidbody>();
-			shadowRootRigidbody.MovePosition(transform.position);
-			shadowRootRigidbody.MoveRotation(transform.rotation);
+			if (physicsSystem == PhysicsSystem.Physics2D) {
+				var shadowRootRigidbody = shadowRoot.GetComponent<Rigidbody2D>();
+				shadowRootRigidbody.MovePosition(transform.position);
+				shadowRootRigidbody.MoveRotation(transform.rotation.eulerAngles.z);
+			} else {
+				var shadowRootRigidbody = shadowRoot.GetComponent<Rigidbody>();
+				shadowRootRigidbody.MovePosition(transform.position);
+				shadowRootRigidbody.MoveRotation(transform.rotation);
+			}
 
 
 			for (int i = 0, n = shadowTable.Count; i < n; i++) {
 			for (int i = 0, n = shadowTable.Count; i < n; i++) {
 				var pair = shadowTable[i];
 				var pair = shadowTable[i];

+ 3 - 3
spine-unity/Assets/spine-unity/SkeletonExtensions.cs

@@ -445,17 +445,17 @@ namespace Spine {
 			// Fail loud when skeleton.data is null.
 			// Fail loud when skeleton.data is null.
 			Spine.Animation animation = skeleton.data.FindAnimation(animationName);
 			Spine.Animation animation = skeleton.data.FindAnimation(animationName);
 			if (animation == null) return;
 			if (animation == null) return;
-			animation.Apply(skeleton, 0, time, loop, null, 1f, MixPose.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.</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, MixPose.Setup, MixDirection.In);
+			animation.Apply(skeleton, 0, time, loop, null, 1f, MixBlend.Setup, MixDirection.In);
 		}
 		}
 
 
 		/// <summary>Resets Skeleton parts to Setup Pose according to a Spine.Animation's keyed items.</summary>
 		/// <summary>Resets Skeleton parts to Setup Pose according to a Spine.Animation's keyed items.</summary>
 		public static void SetKeyedItemsToSetupPose (this Animation animation, Skeleton skeleton) {
 		public static void SetKeyedItemsToSetupPose (this Animation animation, Skeleton skeleton) {
-			animation.Apply(skeleton, 0, 0, false, null, 0, MixPose.Setup, MixDirection.Out);
+			animation.Apply(skeleton, 0, 0, false, null, 0, MixBlend.Setup, MixDirection.Out);
 		}
 		}
 
 
 
 

+ 1 - 1
spine-unity/Assets/spine-unity/version.txt

@@ -1 +1 @@
-This Spine-Unity runtime works with data exported from Spine Editor version: 3.6.xx
+This Spine-Unity runtime works with data exported from Spine Editor version: 3.7.xx