1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-26 14:38:34 +01:00

improved SpriteAnimationGroup performance

This commit is contained in:
Ell 2021-12-21 21:17:45 +01:00
parent c31e196071
commit b5bee0facb

View file

@ -11,23 +11,15 @@ namespace MLEM.Animations {
/// </summary> /// </summary>
public class SpriteAnimationGroup : GenericDataHolder { public class SpriteAnimationGroup : GenericDataHolder {
private readonly List<ConditionedAnimation> animations = new List<ConditionedAnimation>();
private ConditionedAnimation currAnimation;
private ConditionedAnimation CurrAnimation {
get {
if (this.isDirty) {
this.isDirty = false;
this.animations.Sort((a1, a2) => a2.Priority.CompareTo(a1.Priority));
this.FindAnimationToPlay();
}
return this.currAnimation;
}
set => this.currAnimation = value;
}
/// <summary> /// <summary>
/// Returns the animation that is currently playing. /// Returns the animation that is currently playing.
/// </summary> /// </summary>
public SpriteAnimation CurrentAnimation => this.CurrAnimation?.Animation; public SpriteAnimation CurrentAnimation {
get {
this.SortAnimationsIfDirty(true);
return this.currentAnimation?.Animation;
}
}
/// <summary> /// <summary>
/// Returns the frame that <see cref="CurrentAnimation"/> is displaying. /// Returns the frame that <see cref="CurrentAnimation"/> is displaying.
/// </summary> /// </summary>
@ -40,11 +32,6 @@ namespace MLEM.Animations {
/// Returns the <see cref="CurrentAnimation"/>'s <see cref="SpriteAnimation.CurrentRegions"/>. /// Returns the <see cref="CurrentAnimation"/>'s <see cref="SpriteAnimation.CurrentRegions"/>.
/// </summary> /// </summary>
public IList<TextureRegion> CurrentRegions => this.CurrentAnimation?.CurrentRegions; public IList<TextureRegion> CurrentRegions => this.CurrentAnimation?.CurrentRegions;
/// <summary>
/// A callback for when the currently displaying animation has changed due to a condition with a higher priority being met.
/// </summary>
public event AnimationChanged OnAnimationChanged;
private bool isDirty;
/// <inheritdoc cref="SpriteAnimation.SpeedMultiplier"/> /// <inheritdoc cref="SpriteAnimation.SpeedMultiplier"/>
public float SpeedMultiplier { public float SpeedMultiplier {
set { set {
@ -53,6 +40,15 @@ namespace MLEM.Animations {
} }
} }
/// <summary>
/// A callback for when the currently displaying animation has changed due to a condition with a higher priority being met.
/// </summary>
public event AnimationChanged OnAnimationChanged;
private readonly List<ConditionedAnimation> animations = new List<ConditionedAnimation>();
private ConditionedAnimation currentAnimation;
private bool animationsDirty;
/// <summary> /// <summary>
/// Adds a <see cref="SpriteAnimation"/> to this group. /// Adds a <see cref="SpriteAnimation"/> to this group.
/// </summary> /// </summary>
@ -62,7 +58,7 @@ namespace MLEM.Animations {
/// <returns>This group, for chaining</returns> /// <returns>This group, for chaining</returns>
public SpriteAnimationGroup Add(SpriteAnimation anim, Func<bool> condition, int priority = 0) { public SpriteAnimationGroup Add(SpriteAnimation anim, Func<bool> condition, int priority = 0) {
this.animations.Add(new ConditionedAnimation(anim, condition, priority)); this.animations.Add(new ConditionedAnimation(anim, condition, priority));
this.isDirty = true; this.animationsDirty = true;
return this; return this;
} }
@ -74,8 +70,8 @@ namespace MLEM.Animations {
/// <inheritdoc cref="SpriteAnimation.Update(TimeSpan)"/> /// <inheritdoc cref="SpriteAnimation.Update(TimeSpan)"/>
public void Update(TimeSpan elapsed) { public void Update(TimeSpan elapsed) {
this.FindAnimationToPlay(); this.FindAnimationToPlay();
if (this.CurrAnimation != null) if (this.CurrentAnimation != null)
this.CurrAnimation.Animation.Update(elapsed); this.CurrentAnimation.Update(elapsed);
} }
/// <summary> /// <summary>
@ -88,25 +84,37 @@ namespace MLEM.Animations {
} }
private void FindAnimationToPlay() { private void FindAnimationToPlay() {
this.SortAnimationsIfDirty(false);
ConditionedAnimation animToPlay = null; ConditionedAnimation animToPlay = null;
if (this.CurrAnimation != null && this.CurrAnimation.ShouldPlay()) if (this.currentAnimation != null && this.currentAnimation.ShouldPlay())
animToPlay = this.CurrAnimation; animToPlay = this.currentAnimation;
foreach (var anim in this.animations) { foreach (var anim in this.animations) {
// if we find an animation with a lower priority then it means we can break // if we find an animation with a lower priority then it means we can break since the list is sorted by priority
// because the list is sorted by priority if (animToPlay != null && anim.Priority <= animToPlay.Priority)
if (animToPlay != null && anim.Priority < animToPlay.Priority)
break; break;
if (anim.ShouldPlay()) if (anim.ShouldPlay())
animToPlay = anim; animToPlay = anim;
} }
if (animToPlay != this.CurrAnimation) {
this.OnAnimationChanged?.Invoke(this.CurrAnimation?.Animation, animToPlay?.Animation); if (animToPlay != this.currentAnimation) {
this.CurrAnimation = animToPlay; this.OnAnimationChanged?.Invoke(this.currentAnimation?.Animation, animToPlay?.Animation);
this.currentAnimation = animToPlay;
if (animToPlay != null) if (animToPlay != null)
animToPlay.Animation.Restart(); animToPlay.Animation.Restart();
} }
} }
private void SortAnimationsIfDirty(bool findAnimationToPlay) {
if (this.animationsDirty) {
this.animationsDirty = false;
this.animations.Sort((a1, a2) => a2.Priority.CompareTo(a1.Priority));
if (findAnimationToPlay)
this.FindAnimationToPlay();
}
}
/// <summary> /// <summary>
/// A callback delegate for when a <see cref="SpriteAnimationGroup"/>'s current animation changed. /// A callback delegate for when a <see cref="SpriteAnimationGroup"/>'s current animation changed.
/// </summary> /// </summary>