1 /* 2 Copyright (c) 2019 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.logics.tween; 29 30 import dlib.math.vector; 31 import dlib.math.quaternion; 32 import dlib.math.easing; 33 import dlib.math.interpolation; 34 import dlib.math.utils; 35 import dlib.image.color; 36 import dagon.logics.entity; 37 38 enum TweenDataType 39 { 40 Float, 41 Vector, 42 Color 43 } 44 45 enum TweenType 46 { 47 Unknown = 0, 48 Position, 49 Rotation, 50 Scaling, 51 Color, 52 Alpha, 53 } 54 55 enum Easing 56 { 57 Linear, 58 QuadIn, 59 QuadOut, 60 QuadInOut, 61 BackIn, 62 BackOut, 63 BackInOut, 64 BounceOut 65 } 66 67 struct Tween 68 { 69 TweenDataType dataType; 70 TweenType type = TweenType.Unknown; 71 Easing easing; 72 bool active = false; 73 Entity entity; 74 double duration; 75 double time = 0.0f; 76 uint repeat = 1; 77 uint repeatCounter; 78 bool isPlaying = true; 79 80 union 81 { 82 Color4f fromColor; 83 Vector3f fromVector; 84 float fromFloat; 85 } 86 87 union 88 { 89 Color4f toColor; 90 Vector3f toVector; 91 float toFloat; 92 } 93 94 this(Entity entity, TweenType type, Vector3f start, Vector3f end, double duration, Easing easing = Easing.Linear) 95 { 96 this.dataType = TweenDataType.Vector; 97 this.type = type; 98 this.easing = easing; 99 this.active = true; 100 this.entity = entity; 101 this.duration = duration; 102 this.time = 0.0f; 103 this.fromVector = start; 104 this.toVector = end; 105 this.repeatCounter = 0; 106 this.isPlaying = true; 107 } 108 109 this(Entity entity, TweenType type, Color4f start, Color4f end, double duration, Easing easing = Easing.Linear) 110 { 111 this.dataType = TweenDataType.Color; 112 this.type = type; 113 this.easing = easing; 114 this.active = true; 115 this.entity = entity; 116 this.duration = duration; 117 this.time = 0.0f; 118 this.fromColor = start; 119 this.toColor = end; 120 this.repeatCounter = 0; 121 this.isPlaying = true; 122 } 123 124 this(Entity entity, TweenType type, float start, float end, double duration, Easing easing = Easing.Linear) 125 { 126 this.dataType = TweenDataType.Float; 127 this.type = type; 128 this.easing = easing; 129 this.active = true; 130 this.entity = entity; 131 this.duration = duration; 132 this.time = 0.0f; 133 this.fromFloat = start; 134 this.toFloat = end; 135 this.repeatCounter = 0; 136 this.isPlaying = true; 137 } 138 139 void pause() 140 { 141 isPlaying = false; 142 } 143 144 void play() 145 { 146 isPlaying = true; 147 } 148 149 void kill() 150 { 151 active = false; 152 time = 0.0; 153 repeatCounter = 0; 154 isPlaying = false; 155 } 156 157 void restart() 158 { 159 time = 0.0; 160 } 161 162 void update(double dt) 163 { 164 if (active && entity && isPlaying) 165 { 166 time += dt; 167 float t; 168 169 if (time > duration) 170 { 171 time = 0.0; 172 t = 0.0f; 173 if (repeat >= 0) 174 { 175 repeatCounter++; 176 if (repeatCounter >= repeat) 177 { 178 repeatCounter = 0; 179 active = false; 180 t = 1.0f; 181 } 182 } 183 } 184 else 185 { 186 t = time / duration; 187 } 188 189 applyTween(t); 190 } 191 } 192 193 void applyTween(float t) 194 { 195 if (type == TweenType.Position) 196 entity.position = lerp(fromVector, toVector, ease(t)); 197 else if (type == TweenType.Rotation) 198 entity.angles = lerp(fromVector, toVector, ease(t)); 199 else if (type == TweenType.Scaling) 200 entity.scaling = lerp(fromVector, toVector, ease(t)); 201 } 202 203 float ease(float t) 204 { 205 if (easing == Easing.Linear) return t; 206 else if (easing == Easing.QuadIn) return easeInQuad(t); 207 else if (easing == Easing.QuadOut) return easeOutQuad(t); 208 else if (easing == Easing.QuadInOut) return easeInOutQuad(t); 209 else if (easing == Easing.BackIn) return easeInBack(t); 210 else if (easing == Easing.BackOut) return easeOutBack(t); 211 else if (easing == Easing.BackInOut) return easeInOutBack(t); 212 else if (easing == Easing.BounceOut) return easeOutBounce(t); 213 else return t; 214 } 215 }