[csharp] Remove mixing from limit, dispose track entries ASAP. a69f9d579f

https://github.com/EsotericSoftware/spine-runtimes/issues/899
This commit is contained in:
John 2017-05-24 14:57:55 +08:00 committed by GitHub
parent 5ae5a2af76
commit aa3969f147

View File

@ -34,7 +34,7 @@ using System.Collections.Generic;
namespace Spine {
public class AnimationState {
static readonly Animation EmptyAnimation = new Animation("<empty>", new ExposedList<Timeline>(), 0);
internal const int SUBSEQUENT = 0, FIRST = 1, DIP = 2;
internal const int SUBSEQUENT = 0, FIRST = 1, DIP = 2, DIP_MIX = 3;
private AnimationStateData data;
private readonly ExposedList<TrackEntry> tracks = new ExposedList<TrackEntry>();
@ -115,7 +115,7 @@ namespace Spine {
DisposeNext(current);
continue;
}
if (current.mixingFrom != null && UpdateMixingFrom(current, delta, 2)) {
if (current.mixingFrom != null && UpdateMixingFrom(current, delta)) {
// End mixing from entries once all have completed.
var from = current.mixingFrom;
current.mixingFrom = null;
@ -132,21 +132,18 @@ namespace Spine {
}
/// <summary>Returns true when all mixing from entries are complete.</summary>
private bool UpdateMixingFrom (TrackEntry entry, float delta, int animationCount) {
TrackEntry from = entry.mixingFrom;
private bool UpdateMixingFrom (TrackEntry to, float delta) {
TrackEntry from = to.mixingFrom;
if (from == null) return true;
bool finished = UpdateMixingFrom(from, delta, animationCount + 1);
bool finished = UpdateMixingFrom(from, delta);
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
if (entry.mixTime > 0 && (entry.mixTime >= entry.mixDuration || entry.timeScale == 0)) {
if (animationCount > 5 && from.mixingFrom == null) {
// Limit linked list by speeding up and removing old entries.
entry.interruptAlpha = Math.Max(0, entry.interruptAlpha - delta * 0.66f);
if (entry.interruptAlpha <= 0) {
entry.mixingFrom = null;
queue.End(from);
}
if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) {
if (from.totalAlpha == 0) {
to.mixingFrom = from.mixingFrom;
to.interruptAlpha = from.interruptAlpha;
queue.End(from);
}
return finished;
}
@ -154,7 +151,7 @@ namespace Spine {
from.animationLast = from.nextAnimationLast;
from.trackLast = from.nextTrackLast;
from.trackTime += delta * from.timeScale;
entry.mixTime += delta * entry.timeScale;
to.mixTime += delta * to.timeScale;
return false;
}
@ -199,10 +196,10 @@ namespace Spine {
Timeline timeline = timelinesItems[ii];
var rotateTimeline = timeline as RotateTimeline;
if (rotateTimeline != null) {
ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, timelineData[ii] > 0, timelinesRotation, ii << 1,
firstFrame);
ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, timelineData[ii] >= FIRST, timelinesRotation,
ii << 1, firstFrame);
} else {
timeline.Apply(skeleton, animationLast, animationTime, events, mix, timelineData[ii] > 0, false);
timeline.Apply(skeleton, animationLast, animationTime, events, mix, timelineData[ii] > FIRST, false);
}
}
}
@ -242,6 +239,7 @@ namespace Spine {
bool first;
float alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha;
from.totalAlpha = 0;
for (int i = 0; i < timelineCount; i++) {
Timeline timeline = timelinesItems[i];
switch (timelineData[i]) {
@ -253,14 +251,18 @@ namespace Spine {
first = true;
alpha = alphaMix;
break;
case DIP:
first = true;
alpha = alphaDip;
break;
default:
first = true;
alpha = alphaDip;
var dipMix = timelineDipMix[i];
if (dipMix != null) alpha *= Math.Max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
alpha *= Math.Max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
break;
}
from.totalAlpha += alpha;
var rotateTimeline = timeline as RotateTimeline;
if (rotateTimeline != null) {
ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, first, timelinesRotation, i << 1, firstFrame);
@ -659,7 +661,7 @@ namespace Spine {
internal float eventThreshold, attachmentThreshold, drawOrderThreshold;
internal float animationStart, animationEnd, animationLast, nextAnimationLast;
internal float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale = 1f;
internal float alpha, mixTime, mixDuration, interruptAlpha;
internal float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha;
internal readonly ExposedList<int> timelineData = new ExposedList<int>();
internal readonly ExposedList<TrackEntry> timelineDipMix = new ExposedList<TrackEntry>();
internal readonly ExposedList<float> timelinesRotation = new ExposedList<float>();
@ -691,8 +693,9 @@ namespace Spine {
int mixingToLast = mixingToArray.Count - 1;
var timelines = animation.timelines.Items;
int timelinesCount = animation.timelines.Count;
var timelineDataItems = this.timelineData.Resize(timelinesCount).Items; // timelineData.setSize(timelinesCount);
var timelineDipMixItems = this.timelineDipMix.Resize(timelinesCount).Items; //timelineDipMix.setSize(timelinesCount);
var timelineDataItems = timelineData.Resize(timelinesCount).Items; // timelineData.setSize(timelinesCount);
timelineDipMix.Clear();
var timelineDipMixItems = timelineDipMix.Resize(timelinesCount).Items; //timelineDipMix.setSize(timelinesCount);
// outer:
for (int i = 0; i < timelinesCount; i++) {
@ -702,15 +705,17 @@ namespace Spine {
} else if (to == null || !to.HasTimeline(id)) {
timelineDataItems[i] = AnimationState.FIRST;
} else {
timelineDataItems[i] = AnimationState.DIP;
for (int ii = mixingToLast; ii >= 0; ii--) {
var entry = mixingTo[ii];
if (!entry.HasTimeline(id)) {
if (entry.mixDuration > 0) timelineDipMixItems[i] = entry;
goto outer; // continue outer;
if (entry.mixDuration > 0) {
timelineData[i] = AnimationState.DIP_MIX;
timelineDipMix[i] = entry;
goto outer; // continue outer;
}
}
}
timelineDipMixItems[i] = null;
timelineData[i] = AnimationState.DIP;
}
outer: {}
}