1 /** 2 Copyright: Copyright (c) 2013-2014 Andrey Penechko. 3 License: a$(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module anchovy.gui.utils.timer; 8 9 import core.time; 10 import std.math: isNaN, trunc; 11 12 import anchovy.gui; 13 14 /// Handler must number > 0 if custom repeat needed. 15 /// Timer will be added to queue again with nextTime set to number. 16 /// If number = 0 then nextTime will be set to Timer.delay. 17 /// If number < 0 or is nan, timer will be removed from queue. 18 alias double delegate(double dt) TimerHandler; 19 20 enum TimerTickType 21 { 22 PROCESS_ALL_UNORDERED, 23 PROCESS_ALL_ORDERED, 24 PROCESS_LAST, 25 } 26 27 /// Provides basic timer functionality. 28 /// Designed to be used with TimerManager. 29 class Timer 30 { 31 /// Used for initializing timer. 32 /// Params: 33 /// delay specifies the delay after which handler will be called. 34 /// handler specifies handler to be called when delay exceeds. 35 36 /// tickType sets processing method to be used with this timer. 37 void initialize(double _firstTime, double _currentTime, double _delay, TimerHandler _handler, TimerTickType _tickType = TimerTickType.init) 38 in 39 { 40 assert(_handler); 41 assert(_delay > 0); 42 assert(_firstTime > 0); 43 assert(_currentTime > 0); 44 } 45 body 46 { 47 delay = _delay; 48 lastUpdateTime = _currentTime; 49 handler = _handler; 50 tickType = _tickType; 51 nextUpdateTime = _firstTime; 52 } 53 54 /// The whole delta time will be provided if currentTime > nextTime even when dt % thisDelay > 1. 55 /// Timer will automaticaly decide to process only one period, or all. It can also process only the last update if needed. 56 /// This method will be called only when currentTime > nextTime. 57 void tick(double currentTime) 58 { 59 void updateNextTime(double newNextTime) 60 { 61 lastUpdateTime = nextUpdateTime; 62 63 if (newNextTime == 0) 64 nextUpdateTime += delay; 65 else if (newNextTime > 0) 66 nextUpdateTime += newNextTime; 67 else 68 nextUpdateTime = double.nan; 69 } 70 71 double newNextTime; 72 73 with(TimerTickType) 74 final switch(tickType) 75 { 76 case PROCESS_ALL_ORDERED: 77 { 78 newNextTime = handler(nextUpdateTime - lastUpdateTime); 79 updateNextTime(newNextTime); 80 break; 81 } 82 case PROCESS_ALL_UNORDERED: 83 { 84 while(currentTime > nextUpdateTime) 85 { 86 newNextTime = handler(nextUpdateTime - lastUpdateTime); 87 updateNextTime(newNextTime); 88 } 89 break; 90 } 91 case PROCESS_LAST: 92 { 93 uint timesUpdated = cast(uint)trunc((currentTime - nextUpdateTime) / delay) + 1; 94 nextUpdateTime += timesUpdated * delay; 95 96 newNextTime = handler(timesUpdated); 97 updateNextTime(newNextTime); 98 break; 99 } 100 } 101 } 102 103 TimerHandler handler; 104 105 TimerTickType tickType; 106 107 double lastUpdateTime; 108 double nextUpdateTime; 109 double delay; 110 }