]> git.localhorst.tv Git - l2e.git/blob - src/app/Timer.h
13f48f3d7d38ec884c38234fc4fdc7355e1f990c
[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 Started() const {
52                 return data;
53         }
54         bool Finished() const {
55                 return data && data->target != Time() && !data->repeat && data->time >= data->target;
56         }
57         bool Running() const {
58                 return data && !Finished();
59         }
60         Time Elapsed() const {
61                 return data ? data->time : Time();
62         }
63         Time Remaining() const {
64                 return data ? (data->target - data->time) : Time();
65         }
66         int Iteration() const {
67                 return (data && data->target > Time()) ? std::floor(data->time / data->target) : Time();
68         }
69         bool JustHit() const {
70                 return data && data->justHit;
71         }
72
73         void Clear() {
74                 if (data) {
75                         --data->refCount;
76                         data = 0;
77                 }
78         }
79         void Reset() {
80                 if (data) data->time = Time();
81         }
82         void Restart() {
83                 if (data) {
84                         if (data->target > Time() && data->justHit) {
85                                 data->time -= data->target;
86                         } else {
87                                 data->time = Time();
88                         }
89                 }
90         }
91
92 private:
93         TimerData<Time> *data;
94
95 };
96
97
98 template<class Time>
99 class Timers {
100
101 public:
102         Timers() { }
103
104 public:
105         void Update(Time delta) {
106                 for (typename std::list<TimerData<Time> >::iterator i(data.begin()), end(data.end()); i != end;) {
107                         if (i->target > 0) {
108                                 Time intervalTime(i->time);
109                                 if (i->repeat) while (intervalTime > i->target) intervalTime -= i->target;
110                                 i->justHit = intervalTime < i->target && intervalTime + delta >= i->target;
111                         }
112                         i->time += delta;
113                         if (i->refCount <= 0) {
114                                 i = data.erase(i);
115                         } else {
116                                 ++i;
117                         }
118                 }
119         }
120         Timer<Time> StartTimer() {
121                 data.push_back(TimerData<Time>());
122                 return Timer<Time>(&data.back());
123         }
124         Timer<Time> StartCountdown(Time duration) {
125                 data.push_back(TimerData<Time>(duration, false));
126                 return Timer<Time>(&data.back());
127         }
128         Timer<Time> StartInterval(Time duration) {
129                 data.push_back(TimerData<Time>(duration, true));
130                 return Timer<Time>(&data.back());
131         }
132
133 private:
134         std::list<TimerData<Time> > data;
135
136 };
137
138 }
139
140 #endif /* APP_TIMER_H_ */