1 module evael.graphics.gui.animations.AnimationSet; 2 3 import std.typecons; 4 5 import evael.graphics.gui.animations.Animation; 6 import evael.graphics.gui.controls.Control; 7 8 import dnogc.DynamicArray; 9 10 /** 11 * AnimationSet. 12 * 13 * Contains multiple animations to be played one by one or all together. 14 */ 15 class AnimationSet 16 { 17 public enum SequenceType : ubyte 18 { 19 AllTogether, 20 OneByOne 21 } 22 23 protected alias OnSequenceEnd = void delegate(); 24 protected OnSequenceEnd m_onSequenceEnd; 25 26 /// Animations 27 private DynamicArray!Animation m_animations; 28 29 /// Current animation 30 private uint m_currentAnimation; 31 32 /// Replay animations ? 33 private bool m_loop; 34 35 /// AnimationSet sequence type (play all animations together or one by one) 36 private SequenceType m_sequenceType; 37 38 /// Animations duration in ms 39 protected float m_duration; 40 41 private Control m_control; 42 43 /** 44 * AnimationSet constructor. 45 * Params: 46 * loop : loop animations 47 * sequenceType : sequence type 48 */ 49 @nogc @safe 50 public this(in Flag!"loop" loop = No.loop, in SequenceType sequenceType = SequenceType.OneByOne) pure nothrow 51 { 52 this.m_currentAnimation = 0; 53 this.m_loop = loop; 54 this.m_sequenceType = sequenceType; 55 this.m_duration = 1000.0f; 56 } 57 58 public void dispose() 59 { 60 this.m_animations.dispose(); 61 } 62 63 public void update(in float deltaTime) 64 { 65 if (this.m_sequenceType == SequenceType.OneByOne) 66 { 67 this.m_animations[this.m_currentAnimation].update(deltaTime); 68 } 69 else 70 { 71 foreach (animation; this.m_animations) 72 { 73 animation.update(deltaTime); 74 } 75 } 76 } 77 78 /** 79 * Adds animation to the set. 80 * Params: 81 * animation : 82 */ 83 @nogc @safe 84 public void add(Animation animation) pure nothrow 85 { 86 animation.id = this.m_animations.length; 87 88 this.m_animations.insert(animation); 89 90 animation.onAnimationEndEvent = &this.onAnimationEndEvent; 91 } 92 93 /** 94 * Event received when an animation ended. 95 */ 96 public void onAnimationEndEvent(Animation endedAnimation) 97 { 98 final switch (this.m_sequenceType) with (SequenceType) 99 { 100 case OneByOne: 101 { 102 if (++this.m_currentAnimation != this.m_animations.length) 103 return; 104 105 if (this.m_loop) 106 { 107 this.m_currentAnimation = 0; 108 109 foreach (animation; this.m_animations) 110 { 111 animation.reset(); 112 } 113 } 114 else 115 { 116 if (this.m_onSequenceEnd !is null) 117 { 118 this.m_onSequenceEnd(); 119 } 120 } 121 break; 122 } 123 case AllTogether: 124 { 125 // We are playing all animations together 126 if (this.m_loop) 127 { 128 endedAnimation.reset(); 129 } 130 else 131 { 132 import std.algorithm : countUntil; 133 134 auto animationIndex = this.m_animations[].countUntil!(a => a == endedAnimation); 135 136 if (animationIndex >= 0) 137 { 138 this.m_animations.remove(animationIndex); 139 } 140 141 if (!this.m_animations.length) 142 { 143 if (this.m_onSequenceEnd !is null) 144 { 145 this.m_onSequenceEnd(); 146 } 147 } 148 } 149 break; 150 } 151 } 152 } 153 154 @nogc @safe 155 @property pure nothrow 156 { 157 public void control(Control value) 158 { 159 this.m_control = value; 160 161 foreach (animation; this.m_animations) 162 { 163 animation.control = value; 164 } 165 } 166 167 public void duration(in float value) 168 { 169 this.m_duration = value; 170 171 foreach (animation; this.m_animations) 172 { 173 animation.duration = value; 174 } 175 } 176 177 public void onSequenceEndEvent(OnSequenceEnd value) 178 { 179 this.m_onSequenceEnd = value; 180 } 181 } 182 }