]> git.localhorst.tv Git - l2e.git/blobdiff - src/app/Timer.h
better handling of nested state changes
[l2e.git] / src / app / Timer.h
index 465ed64e45edc14a13faa7f462b70e35275e83a1..13f48f3d7d38ec884c38234fc4fdc7355e1f990c 100644 (file)
 
 #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;
 
 };
 
@@ -45,11 +48,14 @@ public:
        }
 
 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();
@@ -57,6 +63,31 @@ public:
        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;
@@ -73,6 +104,11 @@ public:
 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);
@@ -86,7 +122,11 @@ public:
                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());
        }