Merge branch '3.8' into 4.0-beta

This commit is contained in:
Harald Csaszar 2021-03-19 16:15:39 +01:00
commit c9e52024f5
6 changed files with 135 additions and 46 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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