summaryrefslogtreecommitdiff
path: root/src/ui/util.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-10-23 14:53:28 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-10-23 14:53:28 +0300
commit0c9806529bc33f02431570ba0cc2d48039b8afe1 (patch)
treec8915ed3b93aa7b9b5c67bea100e800f0cda0598 /src/ui/util.c
parent97fd3c886ee1aa069784da881dc206741d282b3c (diff)
Improved smooth scrolling
Use proper easing curves for a smoother animation. Ensure that mouse hover on links is disabled when scrolling.
Diffstat (limited to 'src/ui/util.c')
-rw-r--r--src/ui/util.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/src/ui/util.c b/src/ui/util.c
index bef839dc..38124b22 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -135,8 +135,9 @@ iBool isFinished_Anim(const iAnim *d) {
135} 135}
136 136
137void init_Anim(iAnim *d, float value) { 137void init_Anim(iAnim *d, float value) {
138 d->due = d->when = frameTime_Window(get_Window()); 138 d->due = d->when = SDL_GetTicks(); // frameTime_Window(get_Window());
139 d->from = d->to = value; 139 d->from = d->to = value;
140 d->flags = 0;
140} 141}
141 142
142void setValue_Anim(iAnim *d, float to, uint32_t span) { 143void setValue_Anim(iAnim *d, float to, uint32_t span) {
@@ -149,6 +150,54 @@ void setValue_Anim(iAnim *d, float to, uint32_t span) {
149 } 150 }
150} 151}
151 152
153iLocalDef float pos_Anim_(const iAnim *d, uint32_t now) {
154 return (float) (now - d->when) / (float) (d->due - d->when);
155}
156
157void setValueEased_Anim(iAnim *d, float to, uint32_t span) {
158 if (fabsf(to - d->to) <= 0.00001f) {
159 d->to = to; /* Pretty much unchanged. */
160 return;
161 }
162 const uint32_t now = SDL_GetTicks();
163 if (isFinished_Anim(d)) {
164 d->from = d->to;
165 d->when = now;
166 d->flags = easeBoth_AnimFlag;
167 }
168 else {
169 d->from = value_Anim(d);
170 d->when = frameTime_Window(get_Window()); /* to match the timing of value_Anim */
171 d->flags = easeOut_AnimFlag;
172 }
173 d->to = to;
174 d->due = now + span;
175}
176
177void setFlags_Anim(iAnim *d, int flags, iBool set) {
178 iChangeFlags(d->flags, flags, set);
179}
180
181void stop_Anim(iAnim *d) {
182 d->from = d->to = value_Anim(d);
183 d->when = d->due = SDL_GetTicks();
184}
185
186iLocalDef float easeIn_(float t) {
187 return t * t;
188}
189
190iLocalDef float easeOut_(float t) {
191 return t * (2.0f - t);
192}
193
194iLocalDef float easeBoth_(float t) {
195 if (t < 0.5f) {
196 return easeIn_(t * 2.0f) * 0.5f;
197 }
198 return 0.5f + easeOut_((t - 0.5f) * 2.0f) * 0.5f;
199}
200
152float value_Anim(const iAnim *d) { 201float value_Anim(const iAnim *d) {
153 const uint32_t now = frameTime_Window(get_Window()); 202 const uint32_t now = frameTime_Window(get_Window());
154 if (now >= d->due) { 203 if (now >= d->due) {
@@ -157,8 +206,17 @@ float value_Anim(const iAnim *d) {
157 if (now <= d->when) { 206 if (now <= d->when) {
158 return d->from; 207 return d->from;
159 } 208 }
160 const float pos = (float) (now - d->when) / (float) (d->due - d->when); 209 float t = pos_Anim_(d, now);
161 return d->from * (1.0f - pos) + d->to * pos; 210 if ((d->flags & easeBoth_AnimFlag) == easeBoth_AnimFlag) {
211 t = easeBoth_(t);
212 }
213 else if (d->flags & easeIn_AnimFlag) {
214 t = easeIn_(t);
215 }
216 else if (d->flags & easeOut_AnimFlag) {
217 t = easeOut_(t);
218 }
219 return d->from * (1.0f - t) + d->to * t;
162} 220}
163 221
164/*-----------------------------------------------------------------------------------------------*/ 222/*-----------------------------------------------------------------------------------------------*/