mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[unity] Update calls to Timeline/Animation.Apply. And other cleanup.
This commit is contained in:
parent
44a44aa6c6
commit
7481a05931
@ -65,7 +65,7 @@ namespace Spine.Unity.Examples {
|
||||
if (fillAnimation == null) return;
|
||||
}
|
||||
|
||||
fillAnimation.Apply(skeleton, 0, percent, false, null, 1f, true, false);
|
||||
fillAnimation.Apply(skeleton, 0, percent, false, null, 1f, MixPose.Setup, MixDirection.In);
|
||||
|
||||
skeleton.Update(Time.deltaTime);
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
@ -115,8 +115,8 @@ namespace Spine.Unity.Editor {
|
||||
Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue);
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (animationToUse != null) animationToUse.Apply(skeletonAnimation.skeleton, 0f, 0f, false, null, 1f, true, false);
|
||||
skeletonAnimation.Update();
|
||||
if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f);
|
||||
skeletonAnimation.Update(0);
|
||||
skeletonAnimation.LateUpdate();
|
||||
requireRepaint = true;
|
||||
} else {
|
||||
|
||||
@ -931,7 +931,7 @@ namespace Spine.Unity.Editor {
|
||||
Skeleton skeleton = bone.Skeleton;
|
||||
bool inheritRotation = bone.Data.TransformMode.InheritsRotation();
|
||||
|
||||
animation.Apply(skeleton, 0, 0, true, null, 1f, true, false);
|
||||
animation.PoseSkeleton(skeleton, 0);
|
||||
skeleton.UpdateWorldTransform();
|
||||
float duration = animation.Duration;
|
||||
|
||||
@ -952,7 +952,6 @@ namespace Spine.Unity.Editor {
|
||||
int steps = Mathf.CeilToInt(duration / bakeIncrement);
|
||||
|
||||
float currentTime = 0;
|
||||
float lastTime = 0;
|
||||
float angle = rotation;
|
||||
|
||||
for (int i = 1; i <= steps; i++) {
|
||||
@ -960,7 +959,7 @@ namespace Spine.Unity.Editor {
|
||||
if (i == steps)
|
||||
currentTime = duration;
|
||||
|
||||
animation.Apply(skeleton, lastTime, currentTime, true, null, 1f, true, false);
|
||||
animation.PoseSkeleton(skeleton, currentTime, true);
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
int pIndex = listIndex - 1;
|
||||
@ -969,11 +968,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
pk = keys[pIndex];
|
||||
|
||||
if (inheritRotation)
|
||||
rotation = bone.AppliedRotation;
|
||||
else {
|
||||
rotation = GetUninheritedRotation(bone);
|
||||
}
|
||||
rotation = inheritRotation ? bone.AppliedRotation : GetUninheritedRotation(bone);
|
||||
|
||||
angle += Mathf.DeltaAngle(angle, rotation);
|
||||
|
||||
@ -988,7 +983,6 @@ namespace Spine.Unity.Editor {
|
||||
keys[pIndex] = pk;
|
||||
|
||||
listIndex++;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
|
||||
@ -1058,7 +1052,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1085,7 +1079,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1104,7 +1098,7 @@ namespace Spine.Unity.Editor {
|
||||
if (i == steps)
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
px = xKeys[listIndex - 1];
|
||||
py = yKeys[listIndex - 1];
|
||||
@ -1201,7 +1195,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1228,7 +1222,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1246,7 +1240,7 @@ namespace Spine.Unity.Editor {
|
||||
if (i == steps)
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
px = xKeys[listIndex - 1];
|
||||
py = yKeys[listIndex - 1];
|
||||
@ -1330,7 +1324,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1355,7 +1349,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
|
||||
lastTime = time;
|
||||
listIndex++;
|
||||
@ -1365,7 +1359,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
float time = frames[f];
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
rotation = frames[f + 1] + boneData.Rotation;
|
||||
@ -1379,7 +1373,7 @@ namespace Spine.Unity.Editor {
|
||||
if (i == steps)
|
||||
currentTime = time;
|
||||
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, false, false);
|
||||
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixPose.Setup, MixDirection.In);
|
||||
skeleton.UpdateWorldTransform();
|
||||
pk = keys[listIndex - 1];
|
||||
|
||||
@ -1407,7 +1401,7 @@ namespace Spine.Unity.Editor {
|
||||
curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
|
||||
|
||||
string path = GetPath(boneData);
|
||||
string propertyName = "localEulerAnglesBaked";
|
||||
const string propertyName = "localEulerAnglesBaked";
|
||||
|
||||
EditorCurveBinding xBind = EditorCurveBinding.FloatCurve(path, typeof(Transform), propertyName + ".x");
|
||||
AnimationUtility.SetEditorCurve(clip, xBind, new AnimationCurve());
|
||||
|
||||
@ -242,7 +242,7 @@ namespace Spine.Unity {
|
||||
// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
|
||||
var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation);
|
||||
if (animationObject != null)
|
||||
animationObject.Apply(skeleton, 0f, 0f, false, null, 1f, true, false);
|
||||
animationObject.PoseSkeleton(skeleton, 0);
|
||||
}
|
||||
Update(0);
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ namespace Spine.Unity {
|
||||
// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
|
||||
var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
|
||||
if (animationObject != null)
|
||||
animationObject.Apply(skeleton, 0f, 0f, false, null, 1f, true, false);
|
||||
animationObject.PoseSkeleton(skeleton, 0f);
|
||||
}
|
||||
Update(0);
|
||||
}
|
||||
@ -162,10 +162,11 @@ namespace Spine.Unity {
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Update () {
|
||||
void Update () {
|
||||
Update(Time.deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>Progresses the AnimationState according to the given deltaTime, and applies it to the Skeleton. Use Time.deltaTime to update manually. Use deltaTime 0 to update without progressing the time.</summary>
|
||||
public void Update (float deltaTime) {
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
@ -40,9 +40,6 @@ namespace Spine.Unity {
|
||||
public enum MixMode { AlwaysMix, MixNext, SpineStyle }
|
||||
public MixMode[] layerMixModes = new MixMode[0];
|
||||
|
||||
public bool autoReset = true;
|
||||
List<Animation> previousAnimations = new List<Animation>();
|
||||
|
||||
#region Bone Callbacks (ISkeletonAnimation)
|
||||
protected event UpdateBonesDelegate _UpdateLocal;
|
||||
protected event UpdateBonesDelegate _UpdateWorld;
|
||||
@ -66,122 +63,164 @@ namespace Spine.Unity {
|
||||
public event UpdateBonesDelegate UpdateComplete { add { _UpdateComplete += value; } remove { _UpdateComplete -= value; } }
|
||||
#endregion
|
||||
|
||||
readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
|
||||
readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
|
||||
Animator animator;
|
||||
public class SpineMecanimTranslator {
|
||||
readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
|
||||
readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
|
||||
Animator animator;
|
||||
|
||||
List<Animation> previousAnimations = new List<Animation>();
|
||||
public bool autoReset = true;
|
||||
|
||||
public void Initialize (Animator animator, SkeletonDataAsset skeletonDataAsset) {
|
||||
this.animator = animator;
|
||||
animationTable.Clear();
|
||||
clipNameHashCodeTable.Clear();
|
||||
var data = skeletonDataAsset.GetSkeletonData(true);
|
||||
foreach (var a in data.Animations)
|
||||
animationTable.Add(a.Name.GetHashCode(), a);
|
||||
}
|
||||
|
||||
public void Apply (Skeleton skeleton, ref MixMode[] layerMixModes) {
|
||||
|
||||
if (layerMixModes.Length < animator.layerCount)
|
||||
System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
|
||||
|
||||
//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.5).
|
||||
|
||||
// Clear Previous
|
||||
if (autoReset) {
|
||||
var previousAnimations = this.previousAnimations;
|
||||
for (int i = 0, n = previousAnimations.Count; i < n; i++)
|
||||
previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
|
||||
|
||||
previousAnimations.Clear();
|
||||
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
|
||||
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
|
||||
if (layerWeight <= 0) continue;
|
||||
|
||||
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
||||
|
||||
bool hasNext = nextStateInfo.fullPathHash != 0;
|
||||
AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
|
||||
AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
|
||||
|
||||
for (int c = 0; c < clipInfo.Length; c++) {
|
||||
var info = clipInfo[c];
|
||||
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
||||
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
||||
}
|
||||
if (hasNext) {
|
||||
for (int c = 0; c < nextClipInfo.Length; c++) {
|
||||
var info = nextClipInfo[c];
|
||||
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
||||
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply
|
||||
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
|
||||
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
|
||||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(layer);
|
||||
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
||||
|
||||
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);
|
||||
|
||||
MixMode mode = layerMixModes[layer];
|
||||
if (mode == MixMode.AlwaysMix) {
|
||||
// Always use Mix instead of Applying the first non-zero weighted clip.
|
||||
for (int c = 0; c < clipInfo.Length; c++) {
|
||||
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);
|
||||
}
|
||||
if (hasNext) {
|
||||
for (int c = 0; c < nextClipInfo.Length; c++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else { // case MixNext || SpineStyle
|
||||
// Apply first non-zero weighted clip
|
||||
int c = 0;
|
||||
for (; c < clipInfo.Length; c++) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
// Mix the rest
|
||||
for (; c < clipInfo.Length; c++) {
|
||||
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);
|
||||
}
|
||||
|
||||
c = 0;
|
||||
if (hasNext) {
|
||||
// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
|
||||
if (mode == MixMode.SpineStyle) {
|
||||
for (; c < nextClipInfo.Length; c++) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Mix the rest
|
||||
for (; c < nextClipInfo.Length; c++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float AnimationTime (float normalizedTime, float clipLength, bool loop, bool reversed) {
|
||||
if (reversed)
|
||||
normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
|
||||
float time = normalizedTime * clipLength;
|
||||
if (loop) return time;
|
||||
const float EndSnapEpsilon = 1f/30f; // Workaround for end-duration keys not being applied.
|
||||
return (clipLength - time < EndSnapEpsilon) ? clipLength : time; // return a time snapped to clipLength;
|
||||
}
|
||||
|
||||
static float AnimationTime (float normalizedTime, float clipLength, bool reversed) {
|
||||
if (reversed)
|
||||
normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
|
||||
|
||||
return normalizedTime * clipLength;
|
||||
}
|
||||
|
||||
int NameHashCode (AnimationClip clip) {
|
||||
int clipNameHashCode;
|
||||
if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
|
||||
clipNameHashCode = clip.name.GetHashCode();
|
||||
clipNameHashCodeTable.Add(clip, clipNameHashCode);
|
||||
}
|
||||
return clipNameHashCode;
|
||||
}
|
||||
}
|
||||
|
||||
public SpineMecanimTranslator translator;
|
||||
|
||||
public override void Initialize (bool overwrite) {
|
||||
if (valid && !overwrite) return;
|
||||
base.Initialize(overwrite);
|
||||
if (!valid) return;
|
||||
|
||||
animationTable.Clear();
|
||||
clipNameHashCodeTable.Clear();
|
||||
animator = GetComponent<Animator>();
|
||||
var data = skeletonDataAsset.GetSkeletonData(true);
|
||||
foreach (var a in data.Animations)
|
||||
animationTable.Add(a.Name.GetHashCode(), a);
|
||||
translator = new SpineMecanimTranslator();
|
||||
translator.Initialize(GetComponent<Animator>(), this.skeletonDataAsset);
|
||||
}
|
||||
|
||||
public void Update () {
|
||||
if (!valid) return;
|
||||
|
||||
if (layerMixModes.Length < animator.layerCount)
|
||||
System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
|
||||
|
||||
//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.5).
|
||||
|
||||
// Clear Previous
|
||||
if (autoReset) {
|
||||
var previousAnimations = this.previousAnimations;
|
||||
for (int i = 0, n = previousAnimations.Count; i < n; i++)
|
||||
previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
|
||||
|
||||
previousAnimations.Clear();
|
||||
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
|
||||
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
|
||||
if (layerWeight <= 0) continue;
|
||||
|
||||
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
||||
|
||||
bool hasNext = nextStateInfo.fullPathHash != 0;
|
||||
AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
|
||||
AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
|
||||
|
||||
for (int c = 0; c < clipInfo.Length; c++) {
|
||||
var info = clipInfo[c];
|
||||
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
||||
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
||||
}
|
||||
if (hasNext) {
|
||||
for (int c = 0; c < nextClipInfo.Length; c++) {
|
||||
var info = nextClipInfo[c];
|
||||
float weight = info.weight * layerWeight; if (weight == 0) continue;
|
||||
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply
|
||||
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
|
||||
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
|
||||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(layer);
|
||||
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
|
||||
|
||||
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);
|
||||
|
||||
MixMode mode = layerMixModes[layer];
|
||||
if (mode == MixMode.AlwaysMix) {
|
||||
// Always use Mix instead of Applying the first non-zero weighted clip.
|
||||
for (int c = 0; c < clipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
}
|
||||
if (hasNext) {
|
||||
for (int c = 0; c < nextClipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
}
|
||||
}
|
||||
} else { // case MixNext || SpineStyle
|
||||
// Apply first non-zero weighted clip
|
||||
int c = 0;
|
||||
for (; c < clipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
break;
|
||||
}
|
||||
// Mix the rest
|
||||
for (; c < clipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
}
|
||||
|
||||
c = 0;
|
||||
if (hasNext) {
|
||||
// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
|
||||
if (mode == MixMode.SpineStyle) {
|
||||
for (; c < nextClipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Mix the rest
|
||||
for (; c < nextClipInfo.Length; c++) {
|
||||
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, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
translator.Apply(skeleton, ref layerMixModes);
|
||||
|
||||
// UpdateWorldTransform and Bone Callbacks
|
||||
{
|
||||
@ -199,30 +238,5 @@ namespace Spine.Unity {
|
||||
_UpdateComplete(this);
|
||||
}
|
||||
}
|
||||
|
||||
static float AnimationTime (float normalizedTime, float clipLength, bool loop, bool reversed) {
|
||||
if (reversed)
|
||||
normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
|
||||
float time = normalizedTime * clipLength;
|
||||
if (loop) return time;
|
||||
const float EndSnapEpsilon = 1f/30f; // Workaround for end-duration keys not being applied.
|
||||
return (clipLength - time < EndSnapEpsilon) ? clipLength : time; // return a time snapped to clipLength;
|
||||
}
|
||||
|
||||
static float AnimationTime (float normalizedTime, float clipLength, bool reversed) {
|
||||
if (reversed)
|
||||
normalizedTime = (1-normalizedTime + (int)normalizedTime) + (int)normalizedTime;
|
||||
|
||||
return normalizedTime * clipLength;
|
||||
}
|
||||
|
||||
int NameHashCode (AnimationClip clip) {
|
||||
int clipNameHashCode;
|
||||
if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
|
||||
clipNameHashCode = clip.name.GetHashCode();
|
||||
clipNameHashCodeTable.Add(clip, clipNameHashCode);
|
||||
}
|
||||
return clipNameHashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,11 +283,6 @@ namespace Spine {
|
||||
#endregion
|
||||
|
||||
#region Posing
|
||||
[System.Obsolete("Old Animation.Apply method signature. Please use the 8 parameter signature. See summary to learn about the extra arguments.")]
|
||||
public static void Apply (this Spine.Animation animation, Skeleton skeleton, float lastTime, float time, bool loop, ExposedList<Event> events) {
|
||||
animation.Apply(skeleton, lastTime, time, loop, events, 1f, false, false);
|
||||
}
|
||||
|
||||
internal static void SetPropertyToSetupPose (this Skeleton skeleton, int propertyID) {
|
||||
int tt = propertyID >> 24;
|
||||
var timelineType = (TimelineType)tt;
|
||||
@ -326,6 +321,9 @@ namespace Spine {
|
||||
case TimelineType.Color:
|
||||
skeleton.slots.Items[i].SetColorToSetupPose();
|
||||
break;
|
||||
case TimelineType.TwoColor:
|
||||
skeleton.slots.Items[i].SetColorToSetupPose();
|
||||
break;
|
||||
case TimelineType.Deform:
|
||||
skeleton.slots.Items[i].attachmentVertices.Clear();
|
||||
break;
|
||||
@ -341,6 +339,8 @@ namespace Spine {
|
||||
ikc.mix = ikc.data.mix;
|
||||
ikc.bendDirection = ikc.data.bendDirection;
|
||||
break;
|
||||
|
||||
// TransformConstraint
|
||||
case TimelineType.TransformConstraint:
|
||||
var tc = skeleton.transformConstraints.Items[i];
|
||||
var tcData = tc.data;
|
||||
@ -384,6 +384,9 @@ namespace Spine {
|
||||
slot.g = slot.data.g;
|
||||
slot.b = slot.data.b;
|
||||
slot.a = slot.data.a;
|
||||
slot.r2 = slot.data.r2;
|
||||
slot.g2 = slot.data.g2;
|
||||
slot.b2 = slot.data.b2;
|
||||
}
|
||||
|
||||
/// <summary>Sets a slot's attachment to setup pose. If you have the slotIndex, Skeleton.SetSlotAttachmentToSetupPose is faster.</summary>
|
||||
@ -411,17 +414,24 @@ namespace Spine {
|
||||
/// <param name="animationName">The name of the animation to use.</param>
|
||||
/// <param name = "time">The time of the pose within the animation.</param>
|
||||
/// <param name = "loop">Wraps the time around if it is longer than the duration of the animation.</param>
|
||||
public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
|
||||
public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop = false) {
|
||||
// Fail loud when skeleton.data is null.
|
||||
Spine.Animation animation = skeleton.data.FindAnimation(animationName);
|
||||
if (animation == null) return;
|
||||
animation.Apply(skeleton, 0, time, loop, null, 1f, false, false);
|
||||
animation.Apply(skeleton, 0, time, loop, null, 1f, MixPose.Setup, MixDirection.In);
|
||||
}
|
||||
|
||||
/// <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) {
|
||||
animation.Apply(skeleton, 0, time, loop, null, 1f, MixPose.Setup, MixDirection.In);
|
||||
}
|
||||
|
||||
/// <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) {
|
||||
animation.Apply(skeleton, 0, 0, false, null, 0, true, true);
|
||||
animation.Apply(skeleton, 0, 0, false, null, 0, MixPose.Setup, MixDirection.Out);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skins
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user