]> git.localhorst.tv Git - l2e.git/blob - src/app/Timer.h
added repetition awareness in timers
[l2e.git] / src / app / Timer.h
1 /*
2  * Timer.h
3  *
4  *  Created on: Aug 10, 2012
5  *      Author: holy
6  */
7
8 #ifndef APP_TIMER_H_
9 #define APP_TIMER_H_
10
11 #include <algorithm>
12 #include <list>
13 #include <cmath>
14
15 namespace app {
16
17 template<class Time>
18 struct TimerData {
19
20         TimerData() : time(0), target(0), refCount(0), justHit(false), repeat(false) { }
21         TimerData(Time target, bool repeat) : time(0), target(target), refCount(0), justHit(false), repeat(repeat) { }
22
23         Time time;
24         Time target;
25         int refCount;
26         bool justHit;
27         bool repeat;
28
29 };
30
31
32 template<class Time>
33 class Timer {
34
35 public:
36         Timer() : data(0) { }
37         ~Timer() { if (data) --data->refCount; }
38         Timer(TimerData<Time> *data) : data(data) { ++data->refCount; }
39         Timer(const Timer<Time> &other)
40         : data(other.data) { if (data) ++(data->refCount); }
41         Timer<Time> &operator =(const Timer<Time> &other) {
42                 Timer<Time> temp(other);
43                 Swap(temp);
44                 return *this;
45         }
46         void Swap(Timer<Time> &other) {
47                 std::swap(data, other.data);
48         }
49
50 public:
51         bool Finished() const {
52                 return data && data->target != Time() && !data->repeat && data->time >= data->target;
53         }
54         bool Running() const {
55                 return data && !Finished();
56         }
57         Time Elapsed() const {
58                 return data ? data->time : Time();
59         }
60         Time Remaining() const {
61                 return data ? (data->target - data->time) : Time();
62         }
63         int Iteration() const {
64                 return (data && data->target > Time()) ? std::floor(data->time / data->target) : Time();
65         }
66         bool JustHit() const {
67                 return data && data->justHit;
68         }
69
70         void Clear() {
71                 if (data) {
72                         --data->refCount;
73                         data = 0;
74                 }
75         }
76         void Reset() {
77                 if (data) data->time = Time();
78         }
79         void Restart() {
80                 if (data) {
81                         if (data->target > Time() && data->justHit) {
82                                 data->time -= data->target;
83                         } else {
84                                 data->time = Time();
85                         }
86                 }
87         }
88
89 private:
90         TimerData<Time> *data;
91
92 };
93
94
95 template<class Time>
96 class Timers {
97
98 public:
99         Timers() { }
100
101 public:
102         void Update(Time delta) {
103                 for (typename std::list<TimerData<Time> >::iterator i(data.begin()), end(data.end()); i != end;) {
104                         if (i->target > 0) {
105                                 Time intervalTime(i->time);
106                                 if (i->repeat) while (intervalTime > i->target) intervalTime -= i->target;
107                                 i->justHit = intervalTime < i->target && intervalTime + delta >= i->target;
108                         }
109                         i->time += delta;
110                         if (i->refCount <= 0) {
111                                 i = data.erase(i);
112                         } else {
113                                 ++i;
114                         }
115                 }
116         }
117         Timer<Time> StartTimer() {
118                 data.push_back(TimerData<Time>());
119                 return Timer<Time>(&data.back());
120         }
121         Timer<Time> StartCountdown(Time duration) {
122                 data.push_back(TimerData<Time>(duration, false));
123                 return Timer<Time>(&data.back());
124         }
125         Timer<Time> StartInterval(Time duration) {
126                 data.push_back(TimerData<Time>(duration, true));
127                 return Timer<Time>(&data.back());
128         }
129
130 private:
131         std::list<TimerData<Time> > data;
132
133 };
134
135 }
136
137 #endif /* APP_TIMER_H_ */