#include <algorithm>
#include <list>
+#include <cmath>
namespace app {
template<class Time>
struct TimerData {
- TimerData() : time(0), target(0), refCount(0) { }
- TimerData(Time target) : time(0), target(target), refCount(0) { }
+ TimerData() : time(0), target(0), refCount(0), justHit(false), repeat(false) { }
+ TimerData(Time target, bool repeat) : time(0), target(target), refCount(0), justHit(false), repeat(repeat) { }
Time time;
Time target;
int refCount;
+ bool justHit;
+ bool repeat;
};
}
public:
- bool Running() const {
+ bool Started() const {
return data;
}
bool Finished() const {
- return data ? data->time >= data->target : false;
+ return data && data->target != Time() && !data->repeat && data->time >= data->target;
+ }
+ bool Running() const {
+ return data && !Finished();
}
Time Elapsed() const {
return data ? data->time : Time();
Time Remaining() const {
return data ? (data->target - data->time) : Time();
}
+ int Iteration() const {
+ return (data && data->target > Time()) ? std::floor(data->time / data->target) : Time();
+ }
+ bool JustHit() const {
+ return data && data->justHit;
+ }
+
+ void Clear() {
+ if (data) {
+ --data->refCount;
+ data = 0;
+ }
+ }
+ void Reset() {
+ if (data) data->time = Time();
+ }
+ void Restart() {
+ if (data) {
+ if (data->target > Time() && data->justHit) {
+ data->time -= data->target;
+ } else {
+ data->time = Time();
+ }
+ }
+ }
private:
TimerData<Time> *data;
public:
void Update(Time delta) {
for (typename std::list<TimerData<Time> >::iterator i(data.begin()), end(data.end()); i != end;) {
+ if (i->target > 0) {
+ Time intervalTime(i->time);
+ if (i->repeat) while (intervalTime > i->target) intervalTime -= i->target;
+ i->justHit = intervalTime < i->target && intervalTime + delta >= i->target;
+ }
i->time += delta;
if (i->refCount <= 0) {
i = data.erase(i);
return Timer<Time>(&data.back());
}
Timer<Time> StartCountdown(Time duration) {
- data.push_back(TimerData<Time>(duration));
+ data.push_back(TimerData<Time>(duration, false));
+ return Timer<Time>(&data.back());
+ }
+ Timer<Time> StartInterval(Time duration) {
+ data.push_back(TimerData<Time>(duration, true));
return Timer<Time>(&data.back());
}