1 // Aseprite
2 // Copyright (C) 2001-2016  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifndef APP_UI_ANIMATED_WIDGET_H_INCLUDED
8 #define APP_UI_ANIMATED_WIDGET_H_INCLUDED
9 #pragma once
10 
11 #include "obs/connection.h"
12 #include "ui/timer.h"
13 
14 #include <cmath>
15 
16 namespace app {
17 
18   class AnimatedWidget {
19   public:
AnimatedWidget()20     AnimatedWidget()
21       : m_timer(1000/60)
22       , m_animation(0)
23     {
24       m_scopedConn = m_timer.Tick.connect(&AnimatedWidget::onTick, this);
25     }
26 
~AnimatedWidget()27     ~AnimatedWidget() {
28       m_timer.stop();
29     }
30 
31     // For each animation frame
onAnimationStart()32     virtual void onAnimationStart() { }
onAnimationStop(int animation)33     virtual void onAnimationStop(int animation) { }
onAnimationFrame()34     virtual void onAnimationFrame() { }
35 
36   protected:
startAnimation(int animation,int lifespan)37     void startAnimation(int animation, int lifespan) {
38       // Stop previous animation
39       if (m_animation)
40         stopAnimation();
41 
42       m_animation = animation;
43       m_animationTime = 0;
44       m_animationLifespan = lifespan;
45       m_timer.start();
46 
47       onAnimationStart();
48     }
49 
stopAnimation()50     void stopAnimation() {
51       int animation = m_animation;
52       m_animation = 0;
53       m_timer.stop();
54 
55       onAnimationStop(animation);
56     }
57 
animation()58     int animation() const {
59       return m_animation;
60     }
61 
animationTime()62     double animationTime() const {
63       return double(m_animationTime) / double(m_animationLifespan);
64     }
65 
ease(double t)66     double ease(double t) {
67       return (1.0 - std::pow(1.0 - t, 2));
68     }
69 
inbetween(double x0,double x1,double t)70     double inbetween(double x0, double x1, double t) {
71       return x0 + (x1-x0)*ease(t);
72     }
73 
74   private:
onTick()75     void onTick() {
76       if (m_animation) {
77         if (m_animationTime == m_animationLifespan)
78           stopAnimation();
79         else
80           ++m_animationTime;
81 
82         onAnimationFrame();
83       }
84     }
85 
86     ui::Timer m_timer;
87     int m_animation;
88     int m_animationTime;
89     int m_animationLifespan;
90     obs::scoped_connection m_scopedConn;
91   };
92 
93 } // namespace app
94 
95 #endif
96