Tween.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using System;
  2. using Microsoft.Xna.Framework;
  3. namespace MonoGame.Extended.Tweening
  4. {
  5. public abstract class Tween<T> : Tween
  6. where T : struct
  7. {
  8. internal Tween(object target, float duration, float delay, TweenMember<T> member, T endValue)
  9. : base(target, duration, delay)
  10. {
  11. Member = member;
  12. _endValue = endValue;
  13. }
  14. public TweenMember<T> Member { get; }
  15. public override string MemberName => Member.Name;
  16. protected T _startValue;
  17. protected T _endValue;
  18. protected override void Initialize()
  19. {
  20. _startValue = Member.Value;
  21. }
  22. protected override void Swap()
  23. {
  24. _endValue = _startValue;
  25. Initialize();
  26. }
  27. }
  28. public abstract class Tween
  29. {
  30. internal Tween(object target, float duration, float delay)
  31. {
  32. Target = target;
  33. Duration = duration;
  34. Delay = delay;
  35. IsAlive = true;
  36. _remainingDelay = delay;
  37. }
  38. public object Target { get; }
  39. public abstract string MemberName { get; }
  40. public float Duration { get; }
  41. public float Delay { get; }
  42. public bool IsPaused { get; set; }
  43. public bool IsRepeating => _remainingRepeats != 0;
  44. public bool IsRepeatingForever => _remainingRepeats < 0;
  45. public bool IsAutoReverse { get; private set; }
  46. public bool IsAlive { get; private set; }
  47. public bool IsComplete { get; private set; }
  48. public float TimeRemaining => Duration - _elapsedDuration;
  49. public float Completion => MathHelper.Clamp(_completion, 0, 1);
  50. private Func<float, float> _easingFunction;
  51. private bool _isInitialized;
  52. private float _completion;
  53. private float _elapsedDuration;
  54. private float _remainingDelay;
  55. private float _repeatDelay;
  56. private int _remainingRepeats;
  57. private Action<Tween> _onBegin;
  58. private Action<Tween> _onEnd;
  59. public Tween Easing(Func<float, float> easingFunction) { _easingFunction = easingFunction; return this; }
  60. public Tween OnBegin(Action<Tween> action) { _onBegin = action; return this; }
  61. public Tween OnEnd(Action<Tween> action) { _onEnd = action; return this; }
  62. public Tween Pause() { IsPaused = true; return this; }
  63. public Tween Resume() { IsPaused = false; return this; }
  64. public Tween Repeat(int count, float repeatDelay = 0f)
  65. {
  66. _remainingRepeats = count;
  67. _repeatDelay = repeatDelay;
  68. return this;
  69. }
  70. public Tween RepeatForever(float repeatDelay = 0f)
  71. {
  72. _remainingRepeats = -1;
  73. _repeatDelay = repeatDelay;
  74. return this;
  75. }
  76. public Tween AutoReverse()
  77. {
  78. if (_remainingRepeats == 0)
  79. _remainingRepeats = 1;
  80. IsAutoReverse = true;
  81. return this;
  82. }
  83. protected abstract void Initialize();
  84. protected abstract void Interpolate(float n);
  85. protected abstract void Swap();
  86. public void Cancel()
  87. {
  88. _remainingRepeats = 0;
  89. IsAlive = false;
  90. }
  91. public void CancelAndComplete()
  92. {
  93. if (IsAlive)
  94. {
  95. _completion = 1;
  96. Interpolate(1);
  97. IsComplete = true;
  98. _onEnd?.Invoke(this);
  99. }
  100. Cancel();
  101. }
  102. public void Update(float elapsedSeconds)
  103. {
  104. if(IsPaused || !IsAlive)
  105. return;
  106. if (_remainingDelay > 0)
  107. {
  108. _remainingDelay -= elapsedSeconds;
  109. if (_remainingDelay > 0)
  110. return;
  111. }
  112. if (!_isInitialized)
  113. {
  114. _isInitialized = true;
  115. Initialize();
  116. _onBegin?.Invoke(this);
  117. }
  118. if (IsComplete)
  119. {
  120. IsComplete = false;
  121. _elapsedDuration = 0;
  122. _onBegin?.Invoke(this);
  123. if (IsAutoReverse)
  124. Swap();
  125. }
  126. _elapsedDuration += elapsedSeconds;
  127. var n = _completion = _elapsedDuration / Duration;
  128. if (_easingFunction != null)
  129. n = _easingFunction(n);
  130. if (_elapsedDuration >= Duration)
  131. {
  132. if (_remainingRepeats != 0)
  133. {
  134. if(_remainingRepeats > 0)
  135. _remainingRepeats--;
  136. _remainingDelay = _repeatDelay;
  137. }
  138. else if (_remainingRepeats == 0)
  139. {
  140. IsAlive = false;
  141. }
  142. n = _completion = 1;
  143. IsComplete = true;
  144. }
  145. Interpolate(n);
  146. if (IsComplete)
  147. _onEnd?.Invoke(this);
  148. }
  149. }
  150. }