|
@@ -36,7 +36,7 @@ using System.Collections.Generic;
|
|
namespace Spine.Unity {
|
|
namespace Spine.Unity {
|
|
[RequireComponent(typeof(Animator))]
|
|
[RequireComponent(typeof(Animator))]
|
|
public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
|
|
public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
|
|
-
|
|
|
|
|
|
+
|
|
[SerializeField] protected MecanimTranslator translator;
|
|
[SerializeField] protected MecanimTranslator translator;
|
|
public MecanimTranslator Translator { get { return translator; } }
|
|
public MecanimTranslator Translator { get { return translator; } }
|
|
|
|
|
|
@@ -108,9 +108,13 @@ namespace Spine.Unity {
|
|
|
|
|
|
public enum MixMode { AlwaysMix, MixNext, SpineStyle }
|
|
public enum MixMode { AlwaysMix, MixNext, SpineStyle }
|
|
|
|
|
|
- readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
|
|
|
|
- readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
|
|
|
|
|
|
+ readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>(IntEqualityComparer.Instance);
|
|
|
|
+ readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>(AnimationClipEqualityComparer.Instance);
|
|
readonly List<Animation> previousAnimations = new List<Animation>();
|
|
readonly List<Animation> previousAnimations = new List<Animation>();
|
|
|
|
+ #if UNITY_2017_1_OR_NEWER
|
|
|
|
+ readonly List<AnimatorClipInfo> clipInfoCache = new List<AnimatorClipInfo>();
|
|
|
|
+ readonly List<AnimatorClipInfo> nextClipInfoCache = new List<AnimatorClipInfo>();
|
|
|
|
+ #endif
|
|
Animator animator;
|
|
Animator animator;
|
|
|
|
|
|
public Animator Animator { get { return this.animator; } }
|
|
public Animator Animator { get { return this.animator; } }
|
|
@@ -144,16 +148,19 @@ namespace Spine.Unity {
|
|
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
|
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
|
|
|
|
|
bool hasNext = nextStateInfo.fullPathHash != 0;
|
|
bool hasNext = nextStateInfo.fullPathHash != 0;
|
|
- AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
|
|
|
|
- AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
|
|
|
|
|
|
|
|
- for (int c = 0; c < clipInfo.Length; c++) {
|
|
|
|
|
|
+ int clipInfoCount, nextClipInfoCount;
|
|
|
|
+ IList<AnimatorClipInfo> clipInfo, nextClipInfo;
|
|
|
|
+ GetAnimatorClipInfos(layer, out clipInfoCount, out nextClipInfoCount, out clipInfo, out nextClipInfo);
|
|
|
|
+
|
|
|
|
+ for (int c = 0; c < clipInfoCount; c++) {
|
|
var info = clipInfo[c];
|
|
var info = clipInfo[c];
|
|
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
|
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
|
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
|
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
|
}
|
|
}
|
|
|
|
+
|
|
if (hasNext) {
|
|
if (hasNext) {
|
|
- for (int c = 0; c < nextClipInfo.Length; c++) {
|
|
|
|
|
|
+ for (int c = 0; c < nextClipInfoCount; c++) {
|
|
var info = nextClipInfo[c];
|
|
var info = nextClipInfo[c];
|
|
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
|
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
|
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
|
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
|
@@ -169,22 +176,20 @@ namespace Spine.Unity {
|
|
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
|
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
|
|
|
|
|
bool hasNext = nextStateInfo.fullPathHash != 0;
|
|
bool hasNext = nextStateInfo.fullPathHash != 0;
|
|
- AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
|
|
|
|
- AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
|
|
|
|
- //UNITY 4
|
|
|
|
- //bool hasNext = nextStateInfo.nameHash != 0;
|
|
|
|
- //var clipInfo = animator.GetCurrentAnimationClipState(i);
|
|
|
|
- //var nextClipInfo = animator.GetNextAnimationClipState(i);
|
|
|
|
|
|
+
|
|
|
|
+ int clipInfoCount, nextClipInfoCount;
|
|
|
|
+ IList<AnimatorClipInfo> clipInfo, nextClipInfo;
|
|
|
|
+ GetAnimatorClipInfos(layer, out clipInfoCount, out nextClipInfoCount, out clipInfo, out nextClipInfo);
|
|
|
|
|
|
MixMode mode = layerMixModes[layer];
|
|
MixMode mode = layerMixModes[layer];
|
|
if (mode == MixMode.AlwaysMix) {
|
|
if (mode == MixMode.AlwaysMix) {
|
|
// 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 < clipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
}
|
|
}
|
|
if (hasNext) {
|
|
if (hasNext) {
|
|
- for (int c = 0; c < nextClipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
}
|
|
}
|
|
@@ -192,13 +197,13 @@ namespace Spine.Unity {
|
|
} else { // case MixNext || SpineStyle
|
|
} else { // case MixNext || SpineStyle
|
|
// Apply first non-zero weighted clip
|
|
// Apply first non-zero weighted clip
|
|
int c = 0;
|
|
int c = 0;
|
|
- for (; c < clipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
// Mix the rest
|
|
// Mix the rest
|
|
- for (; c < clipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
}
|
|
}
|
|
@@ -207,14 +212,14 @@ namespace Spine.Unity {
|
|
if (hasNext) {
|
|
if (hasNext) {
|
|
// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
|
|
// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
|
|
if (mode == MixMode.SpineStyle) {
|
|
if (mode == MixMode.SpineStyle) {
|
|
- for (; c < nextClipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Mix the rest
|
|
// Mix the rest
|
|
- for (; c < nextClipInfo.Length; 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, MixPose.Current, MixDirection.In);
|
|
}
|
|
}
|
|
@@ -239,6 +244,31 @@ namespace Spine.Unity {
|
|
return normalizedTime * clipLength;
|
|
return normalizedTime * clipLength;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ void GetAnimatorClipInfos (
|
|
|
|
+ int layer,
|
|
|
|
+ out int clipInfoCount,
|
|
|
|
+ out int nextClipInfoCount,
|
|
|
|
+ out IList<AnimatorClipInfo> clipInfo,
|
|
|
|
+ out IList<AnimatorClipInfo> nextClipInfo) {
|
|
|
|
+ #if UNITY_2017_1_OR_NEWER
|
|
|
|
+ clipInfoCount = animator.GetCurrentAnimatorClipInfoCount(layer);
|
|
|
|
+ nextClipInfoCount = animator.GetNextAnimatorClipInfoCount(layer);
|
|
|
|
+ if (clipInfoCache.Capacity < clipInfoCount) clipInfoCache.Capacity = clipInfoCount;
|
|
|
|
+ if (nextClipInfoCache.Capacity < nextClipInfoCount) nextClipInfoCache.Capacity = nextClipInfoCount;
|
|
|
|
+ animator.GetCurrentAnimatorClipInfo(layer, clipInfoCache);
|
|
|
|
+ animator.GetNextAnimatorClipInfo(layer, nextClipInfoCache);
|
|
|
|
+
|
|
|
|
+ clipInfo = clipInfoCache;
|
|
|
|
+ nextClipInfo = nextClipInfoCache;
|
|
|
|
+ #else
|
|
|
|
+ clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
|
|
|
|
+ nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
|
|
|
|
+
|
|
|
|
+ clipInfoCount = clipInfo.Count;
|
|
|
|
+ nextClipInfoCount = nextClipInfo.Count;
|
|
|
|
+ #endif
|
|
|
|
+ }
|
|
|
|
+
|
|
int NameHashCode (AnimationClip clip) {
|
|
int NameHashCode (AnimationClip clip) {
|
|
int clipNameHashCode;
|
|
int clipNameHashCode;
|
|
if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
|
|
if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
|
|
@@ -247,6 +277,24 @@ namespace Spine.Unity {
|
|
}
|
|
}
|
|
return clipNameHashCode;
|
|
return clipNameHashCode;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ class AnimationClipEqualityComparer : IEqualityComparer<AnimationClip> {
|
|
|
|
+ internal static readonly IEqualityComparer<AnimationClip> Instance = new AnimationClipEqualityComparer();
|
|
|
|
+
|
|
|
|
+ public bool Equals (AnimationClip x, AnimationClip y) {
|
|
|
|
+ return x.GetInstanceID() == y.GetInstanceID();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public int GetHashCode (AnimationClip o) {
|
|
|
|
+ return o.GetInstanceID();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ class IntEqualityComparer : IEqualityComparer<int> {
|
|
|
|
+ internal static readonly IEqualityComparer<int> Instance = new IntEqualityComparer();
|
|
|
|
+ public bool Equals (int x, int y) { return x == y; }
|
|
|
|
+ public int GetHashCode(int o) { return o; }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|