Эх сурвалжийг харах

Merge branch '3.8' into 4.0-beta

Harald Csaszar 4 жил өмнө
parent
commit
c9e52024f5

+ 11 - 6
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs

@@ -625,9 +625,12 @@ namespace Spine.Unity.Editor {
 				warnings.Add("Missing Skeleton JSON");
 			} else {
 				var fieldValue = (TextAsset)skeletonJSON.objectReferenceValue;
-
-				if (!AssetUtility.IsSpineData(fieldValue, out compatibilityProblemInfo)) {
-					warnings.Add("Skeleton data file is not a valid Spine JSON or binary file.");
+				string problemDescription = null;
+				if (!AssetUtility.IsSpineData(fieldValue, out compatibilityProblemInfo, ref problemDescription)) {
+					if (problemDescription != null)
+						warnings.Add(problemDescription);
+					else
+						warnings.Add("Skeleton data file is not a valid Spine JSON or binary file.");
 				} else {
 					#if SPINE_TK2D
 					bool searchForSpineAtlasAssets = (compatibilityProblemInfo == null);
@@ -644,11 +647,12 @@ namespace Spine.Unity.Editor {
 						var actualAtlasAssets = targetSkeletonDataAsset.atlasAssets;
 
 						for (int i = 0; i < actualAtlasAssets.Length; i++) {
-							if (targetSkeletonDataAsset.atlasAssets[i] == null) {
+							if (actualAtlasAssets[i] == null) {
 								detectedNullAtlasEntry = true;
 								break;
 							} else {
-								atlasList.Add(actualAtlasAssets[i].GetAtlas());
+								if (actualAtlasAssets[i].MaterialCount > 0)
+									atlasList.Add(actualAtlasAssets[i].GetAtlas());
 							}
 						}
 
@@ -658,8 +662,9 @@ namespace Spine.Unity.Editor {
 							List<string> missingPaths = null;
 							if (atlasAssets.arraySize > 0) {
 								missingPaths = AssetUtility.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue));
-
 								foreach (var atlas in atlasList) {
+									if (atlas == null)
+										continue;
 									for (int i = 0; i < missingPaths.Count; i++) {
 										if (atlas.FindRegion(missingPaths[i]) != null) {
 											missingPaths.RemoveAt(i);

+ 46 - 18
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs

@@ -58,7 +58,18 @@ using System.Reflection;
 using CompatibilityProblemInfo = Spine.Unity.SkeletonDataCompatibility.CompatibilityProblemInfo;
 
 namespace Spine.Unity.Editor {
-	using PathAndProblemInfo = System.Collections.Generic.KeyValuePair<string, CompatibilityProblemInfo>;
+
+	public class PathAndProblemInfo {
+		public string path;
+		public CompatibilityProblemInfo compatibilityProblems;
+		public string otherProblemDescription;
+
+		public PathAndProblemInfo (string path, CompatibilityProblemInfo compatibilityInfo, string otherProblemDescription) {
+			this.path = path;
+			this.compatibilityProblems = compatibilityInfo;
+			this.otherProblemDescription = otherProblemDescription;
+		}
+	}
 
 	public static class AssetUtility {
 
@@ -276,17 +287,26 @@ namespace Spine.Unity.Editor {
 					case ".jpg":
 						imagePaths.Add(str);
 						break;
-					case ".json":
+					case ".json": {
 						var jsonAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(str);
-						if (jsonAsset != null && IsSpineData(jsonAsset, out compatibilityProblemInfo))
-							skeletonPaths.Add(new PathAndProblemInfo(str, compatibilityProblemInfo));
+						string problemDescription = null;
+						if (jsonAsset != null && IsSpineData(jsonAsset, out compatibilityProblemInfo, ref problemDescription))
+							skeletonPaths.Add(new PathAndProblemInfo(str, compatibilityProblemInfo, problemDescription));
+						if (problemDescription != null)
+							Debug.LogError(problemDescription, jsonAsset);
 						break;
-					case ".bytes":
+					}
+					case ".bytes": {
 						if (str.ToLower().EndsWith(".skel.bytes", System.StringComparison.Ordinal)) {
-							if (IsSpineData(AssetDatabase.LoadAssetAtPath<TextAsset>(str), out compatibilityProblemInfo))
-								skeletonPaths.Add(new PathAndProblemInfo(str, compatibilityProblemInfo));
+							var binaryAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(str);
+							string problemDescription = null;
+							if (IsSpineData(binaryAsset, out compatibilityProblemInfo, ref problemDescription))
+								skeletonPaths.Add(new PathAndProblemInfo(str, compatibilityProblemInfo, problemDescription));
+							if (problemDescription != null)
+								Debug.LogError(problemDescription, binaryAsset);
 						}
 						break;
+					}
 				}
 			}
 
@@ -304,8 +324,9 @@ namespace Spine.Unity.Editor {
 			// Import skeletons and match them with atlases.
 			bool abortSkeletonImport = false;
 			foreach (var skeletonPathEntry in skeletonPaths) {
-				string skeletonPath = skeletonPathEntry.Key;
-				var compatibilityProblems = skeletonPathEntry.Value;
+				string skeletonPath = skeletonPathEntry.path;
+				var compatibilityProblems = skeletonPathEntry.compatibilityProblems;
+				string otherProblemDescription = skeletonPathEntry.otherProblemDescription;
 				if (skeletonPath.StartsWith("Packages"))
 					continue;
 				if (!reimport && CheckForValidSkeletonData(skeletonPath)) {
@@ -318,6 +339,9 @@ namespace Spine.Unity.Editor {
 					IngestIncompatibleSpineProject(loadedAsset, compatibilityProblems);
 					continue;
 				}
+				if (otherProblemDescription != null) {
+					continue;
+				}
 
 				string dir = Path.GetDirectoryName(skeletonPath).Replace('\\', '/');
 
@@ -378,8 +402,12 @@ namespace Spine.Unity.Editor {
 				if (usedSkeletonPath == null)
 					continue;
 
-				if (skeletonPaths.FindIndex(p => { return p.Key == usedSkeletonPath; } ) < 0) {
-					skeletonPaths.Add(new PathAndProblemInfo(usedSkeletonPath, null));
+				if (skeletonPaths.FindIndex(p => { return p.path == usedSkeletonPath; } ) < 0) {
+					string problemDescription = null;
+					CompatibilityProblemInfo compatibilityProblemInfo = null;
+					TextAsset textAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(usedSkeletonPath);
+					if (textAsset != null && IsSpineData(textAsset, out compatibilityProblemInfo, ref problemDescription))
+						skeletonPaths.Add(new PathAndProblemInfo(usedSkeletonPath, compatibilityProblemInfo, problemDescription));
 				}
 			}
 		}
@@ -427,7 +455,8 @@ namespace Spine.Unity.Editor {
 						}
 
 						SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
-						BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
+						if (skeletonData != null)
+							BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
 
 						string currentHash = skeletonData != null ? skeletonData.Hash : null;
 
@@ -831,11 +860,10 @@ namespace Spine.Unity.Editor {
 		internal static SkeletonDataAsset IngestIncompatibleSpineProject(TextAsset spineJson,
 			CompatibilityProblemInfo compatibilityProblemInfo) {
 
-			string filePath = GetSkeletonDataAssetFilePath(spineJson);
-
 			if (spineJson == null)
 				return null;
 
+			string filePath = GetSkeletonDataAssetFilePath(spineJson);
 			SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
 			if (skeletonDataAsset == null) {
 				skeletonDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
@@ -921,14 +949,14 @@ namespace Spine.Unity.Editor {
 				if (skeletonDataAsset != null && skeletonDataAsset.skeletonJSON == textAsset)
 					return true;
 			}
-
 			return false;
 		}
 
-		public static bool IsSpineData (TextAsset asset, out CompatibilityProblemInfo compatibilityProblemInfo) {
-			SkeletonDataCompatibility.VersionInfo fileVersion = SkeletonDataCompatibility.GetVersionInfo(asset);
+		public static bool IsSpineData (TextAsset asset, out CompatibilityProblemInfo compatibilityProblemInfo, ref string problemDescription) {
+			bool isSpineSkeletonData;
+			SkeletonDataCompatibility.VersionInfo fileVersion = SkeletonDataCompatibility.GetVersionInfo(asset, out isSpineSkeletonData, ref problemDescription);
 			compatibilityProblemInfo = SkeletonDataCompatibility.GetCompatibilityProblemInfo(fileVersion);
-			return fileVersion != null;
+			return isSpineSkeletonData;
 		}
 #endregion
 

+ 11 - 5
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/SkeletonDataAsset.cs

@@ -163,22 +163,29 @@ namespace Spine.Unity {
 			}
 			#endif
 
-			bool isBinary = skeletonJSON.name.ToLower().Contains(".skel");
+			bool hasBinaryExtension = skeletonJSON.name.ToLower().Contains(".skel");
 			SkeletonData loadedSkeletonData = null;
 
 			try {
-				if (isBinary)
+				if (hasBinaryExtension)
 					loadedSkeletonData = SkeletonDataAsset.ReadSkeletonData(skeletonJSON.bytes, attachmentLoader, skeletonDataScale);
 				else
 					loadedSkeletonData = SkeletonDataAsset.ReadSkeletonData(skeletonJSON.text, attachmentLoader, skeletonDataScale);
 			} catch (Exception ex) {
 				if (!quiet)
-					Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
+					Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, skeletonJSON);
 			}
 
 			#if UNITY_EDITOR
 			if (loadedSkeletonData == null && !quiet && skeletonJSON != null) {
-				SkeletonDataCompatibility.VersionInfo fileVersion = SkeletonDataCompatibility.GetVersionInfo(skeletonJSON);
+				string problemDescription = null;
+				bool isSpineSkeletonData;
+				SkeletonDataCompatibility.VersionInfo fileVersion = SkeletonDataCompatibility.GetVersionInfo(skeletonJSON, out isSpineSkeletonData, ref problemDescription);
+				if (problemDescription != null) {
+					if (!quiet)
+						Debug.LogError(problemDescription, skeletonJSON);
+					return null;
+				}
 				CompatibilityProblemInfo compatibilityProblemInfo = SkeletonDataCompatibility.GetCompatibilityProblemInfo(fileVersion);
 				if (compatibilityProblemInfo != null) {
 					SkeletonDataCompatibility.DisplayCompatibilityProblem(compatibilityProblemInfo.DescriptionString(), skeletonJSON);
@@ -250,7 +257,6 @@ namespace Spine.Unity {
 			};
 			return json.ReadSkeletonData(input);
 		}
-
 	}
 
 }

+ 58 - 11
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/SkeletonDataCompatibility.cs

@@ -30,6 +30,7 @@
 using System.Collections.Generic;
 using System.IO;
 using UnityEngine;
+using System;
 #if UNITY_EDITOR
 using System.Globalization;
 using System.Text.RegularExpressions;
@@ -63,8 +64,12 @@ namespace Spine.Unity {
 		public class CompatibilityProblemInfo {
 			public VersionInfo actualVersion;
 			public int[][] compatibleVersions;
+			public string explicitProblemDescription = null;
 
 			public string DescriptionString () {
+				if (!string.IsNullOrEmpty(explicitProblemDescription))
+					return explicitProblemDescription;
+
 				string compatibleVersionString = "";
 				string optionalOr = null;
 				foreach (int[] version in compatibleVersions) {
@@ -77,12 +82,28 @@ namespace Spine.Unity {
 		}
 
 	#if UNITY_EDITOR
-		public static VersionInfo GetVersionInfo (TextAsset asset) {
+		public static VersionInfo GetVersionInfo (TextAsset asset, out bool isSpineSkeletonData, ref string problemDescription) {
+			isSpineSkeletonData = false;
 			if (asset == null)
 				return null;
 
 			VersionInfo fileVersion = new VersionInfo();
-			fileVersion.sourceType = asset.name.Contains(".skel") ? SourceType.Binary : SourceType.Json;
+			bool hasBinaryExtension = asset.name.Contains(".skel");
+			fileVersion.sourceType = hasBinaryExtension ? SourceType.Binary : SourceType.Json;
+
+			bool isJsonFileByContent = IsJsonFile(asset);
+			if (hasBinaryExtension == isJsonFileByContent) {
+				if (hasBinaryExtension) {
+					problemDescription = string.Format("Failed to read '{0}'. Extension is '.skel.bytes' but content looks like a '.json' file.\n"
+						+ "Did you choose the wrong extension upon export?\n", asset.name);
+				}
+				else {
+					problemDescription = string.Format("Failed to read '{0}'. Extension is '.json' but content looks like binary 'skel.bytes' file.\n"
+						+ "Did you choose the wrong extension upon export?\n", asset.name);
+				}
+				isSpineSkeletonData = false;
+				return null;
+			}
 
 			if (fileVersion.sourceType == SourceType.Binary) {
 				try {
@@ -91,8 +112,8 @@ namespace Spine.Unity {
 					}
 				}
 				catch (System.Exception e) {
-					Debug.LogError(string.Format("Failed to read '{0}'. It is likely not a binary Spine SkeletonData file.\n{1}",
-						asset.name, e), asset);
+					problemDescription = string.Format("Failed to read '{0}'. It is likely not a binary Spine SkeletonData file.\n{1}", asset.name, e);
+					isSpineSkeletonData = false;
 					return null;
 				}
 			}
@@ -104,13 +125,15 @@ namespace Spine.Unity {
 				else {
 					object obj = Json.Deserialize(new StringReader(asset.text));
 					if (obj == null) {
-						Debug.LogError(string.Format("'{0}' is not valid JSON.", asset.name), asset);
+						problemDescription = string.Format("'{0}' is not valid JSON.", asset.name);
+						isSpineSkeletonData = false;
 						return null;
 					}
 
 					var root = obj as Dictionary<string, object>;
 					if (root == null) {
-						Debug.LogError(string.Format("'{0}' is not compatible JSON. Parser returned an incorrect type while parsing version info.", asset.name), asset);
+						problemDescription = string.Format("'{0}' is not compatible JSON. Parser returned an incorrect type while parsing version info.", asset.name);
+						isSpineSkeletonData = false;
 						return null;
 					}
 
@@ -124,7 +147,8 @@ namespace Spine.Unity {
 			}
 
 			if (string.IsNullOrEmpty(fileVersion.rawVersion)) {
-				// very likely not a Spine skeleton json file at all.
+				// very likely not a Spine skeleton json file at all. Could be another valid json file, don't report errors.
+				isSpineSkeletonData = false;
 				return null;
 			}
 
@@ -134,16 +158,39 @@ namespace Spine.Unity {
 									int.Parse(versionSplit[1], CultureInfo.InvariantCulture) };
 			}
 			catch (System.Exception e) {
-				Debug.LogError(string.Format("Failed to read version info at skeleton '{0}'. It is likely not a valid Spine SkeletonData file.\n{1}",
-					asset.name, e), asset);
+				problemDescription = string.Format("Failed to read version info at skeleton '{0}'. It is likely not a valid Spine SkeletonData file.\n{1}", asset.name, e);
+				isSpineSkeletonData = false;
 				return null;
 			}
+			isSpineSkeletonData = true;
 			return fileVersion;
 		}
 
+		public static bool IsJsonFile (TextAsset file) {
+			string fileText = file.text;
+			const int maxCharsToCheck = 256;
+			int numCharsToCheck = Math.Min(fileText.Length, maxCharsToCheck);
+			if (fileText.IndexOf("\"skeleton\"", 0, numCharsToCheck) != -1 ||
+				fileText.IndexOf("\"hash\"", 0, numCharsToCheck) != -1 ||
+				fileText.IndexOf("\"spine\"", 0, numCharsToCheck) != -1)
+				return true;
+
+			int jsonCharCount = 0;
+			const string jsonChars = "{}:\",";
+			for (int i = 0; i < numCharsToCheck; ++i) {
+				char c = fileText[i];
+				if (jsonChars.IndexOf(c) != -1 || char.IsWhiteSpace(c))
+					++jsonCharCount;
+			}
+			if (jsonCharCount > numCharsToCheck / 10)
+				return true;
+			return false;
+		}
+
 		public static CompatibilityProblemInfo GetCompatibilityProblemInfo (VersionInfo fileVersion) {
-			if (fileVersion == null)
-				return null;
+			if (fileVersion == null) {
+				return null; // it's most likely not a Spine skeleton file, e.g. another json file. don't report problems.
+			}
 
 			CompatibilityProblemInfo info = new CompatibilityProblemInfo();
 			info.actualVersion = fileVersion;

+ 8 - 5
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs

@@ -142,6 +142,9 @@ namespace Spine.Unity {
 
 		[System.Serializable]
 		public class MecanimTranslator {
+
+			const float WeightEpsilon = 0.0001f;
+
 			#region Inspector
 			public bool autoReset = true;
 			public bool useCustomMixMode = true;
@@ -220,7 +223,7 @@ namespace Spine.Unity {
 			private bool ApplyAnimation (Skeleton skeleton, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
 										int layerIndex, float layerWeight, MixBlend layerBlendMode, bool useClipWeight1 = false) {
 				float weight = info.weight * layerWeight;
-				if (weight == 0)
+				if (weight < WeightEpsilon)
 					return false;
 
 				var clip = GetAnimation(info.clip);
@@ -244,7 +247,7 @@ namespace Spine.Unity {
 
 				float clipWeight = interpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
 				float weight = clipWeight * layerWeight;
-				if (weight == 0)
+				if (weight < WeightEpsilon)
 					return false;
 
 				var clip = GetAnimation(info.clip);
@@ -320,7 +323,7 @@ namespace Spine.Unity {
 
 						for (int c = 0; c < clipInfoCount; c++) {
 							var info = clipInfo[c];
-							float weight = info.weight * layerWeight; if (weight == 0) continue;
+							float weight = info.weight * layerWeight; if (weight < WeightEpsilon) continue;
 							var clip = GetAnimation(info.clip);
 							if (clip != null)
 								previousAnimations.Add(clip);
@@ -329,7 +332,7 @@ namespace Spine.Unity {
 						if (hasNext) {
 							for (int c = 0; c < nextClipInfoCount; c++) {
 								var info = nextClipInfo[c];
-								float weight = info.weight * layerWeight; if (weight == 0) continue;
+								float weight = info.weight * layerWeight; if (weight < WeightEpsilon) continue;
 								var clip = GetAnimation(info.clip);
 								if (clip != null)
 									previousAnimations.Add(clip);
@@ -341,7 +344,7 @@ namespace Spine.Unity {
 							{
 								var info = interruptingClipInfo[c];
 								float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
-								float weight = clipWeight * layerWeight; if (weight == 0) continue;
+								float weight = clipWeight * layerWeight; if (weight < WeightEpsilon) continue;
 								var clip = GetAnimation(info.clip);
 								if (clip != null)
 									previousAnimations.Add(clip);

+ 1 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs

@@ -363,7 +363,7 @@ namespace Spine.Unity {
 			#if UNITY_EDITOR
 			if (!Application.isPlaying) {
 				string errorMessage = null;
-				if (quiet || MaterialChecks.IsMaterialSetupProblematic(this, ref errorMessage))
+				if (!quiet && MaterialChecks.IsMaterialSetupProblematic(this, ref errorMessage))
 					Debug.LogWarningFormat(this, "Problematic material setup at {0}: {1}", this.name, errorMessage);
 			}
 			#endif