20
|
1 /* LICENSE BLOCK
|
|
2 Part of mde: a Modular D game-oriented Engine
|
|
3 Copyright © 2007-2008 Diggory Hardy
|
|
4
|
|
5 This program is free software; you can redistribute it and/or modify it under the terms of
|
|
6 the GNU General Public License, version 2, as published by the Free Software Foundation.
|
|
7
|
|
8 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
9 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
10 See the GNU General Public License for more details.
|
|
11
|
|
12 You should have received a copy of the GNU General Public License along
|
|
13 with this program; if not, write to the Free Software Foundation, Inc.,
|
|
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
15
|
|
16 /** Scheduler
|
|
17 */
|
|
18 module mde.scheduler.runTime;
|
|
19
|
|
20 import tango.time.Time;
|
|
21
|
|
22 // NOTE: Currently has no support for removing functions. To fix, assign ID and store fct pointers
|
|
23 // in an associative array, returning the ID [on adding fct pointer].
|
|
24 // FIXME: support delegates or not?
|
|
25 /// This class can run scheduled functions per frame or every t seconds (sim-time).
|
|
26 abstract class Scheduler
|
|
27 {
|
|
28 /** The type of function pointer to be passed to the scheduler.
|
|
29 *
|
|
30 * The double $(I time) parameter gives the number of (sim) seconds since the function was last
|
|
31 * called, or zero on the first run. */
|
|
32 alias void function (double time) scheduleFct;
|
|
33
|
|
34 /** Add a function to be called per frame. */
|
|
35 static void perFrame (scheduleFct fct) {
|
|
36 frameFcts ~= fct;
|
|
37 }
|
|
38
|
|
39 /** Add a function to be called per t secs or n 100-nano-sec intevals.
|
|
40 *
|
|
41 * Since the scheduler cannot guarantee a maximum time between calls, the interval at which
|
|
42 * functions are called is always greater than or equal to the inverval specified here. Of
|
|
43 * course, the actual inteval is given when the function is run.
|
|
44 */
|
|
45 static void perTime (double t, scheduleFct fct) {
|
|
46 perTime (TimeSpan.interval(t), fct);
|
|
47 }
|
|
48 /** ditto */
|
|
49 static void perTime (TimeSpan n, scheduleFct fct)
|
|
50 in { assert (n > TimeSpan (0L)); }
|
|
51 body {
|
|
52 timeFcts ~= TimeFct (fct, n);
|
|
53 }
|
|
54
|
|
55 /** This function should get called by the main loop, once per frame.
|
|
56 *
|
|
57 * The parameter time should be the current sim-time, using the tango.core.Types.Time enum; all
|
|
58 * time evaluations will use this.
|
|
59 */
|
|
60 static void run (Time time) {
|
|
61 double interval;
|
|
62
|
|
63 // Call all per-frame functions:
|
|
64 if (lastTime == Time (0L)) interval = 0.0; // 0 interval for first loop
|
|
65 else interval = (time-lastTime).interval();
|
|
66
|
|
67 foreach (fct; frameFcts) fct(interval);
|
|
68
|
|
69 // Call all per-interval functions:
|
|
70 foreach (fct; timeFcts) if (time >= fct.nextCall) {
|
|
71 if (fct.nextCall == Time (0L)) interval = 0.0; // 0 interval for first call
|
|
72 else interval = (time - (fct.nextCall - fct.interval)).interval();
|
|
73 fct.nextCall = time + fct.interval; // when to call next
|
|
74
|
|
75 fct.fct (interval); // call
|
|
76 }
|
|
77 }
|
|
78
|
|
79 /* Holds details for functions called per time interval. */
|
|
80 private struct TimeFct {
|
|
81 scheduleFct fct; // function to call
|
|
82
|
|
83 TimeSpan interval; // interval to call at
|
|
84 // Storing nextCall is more efficient than storing lastCall since only this number has to
|
|
85 // be compared to time every frame where fct is not called:
|
|
86 Time nextCall = Time (0L);
|
|
87
|
|
88 static TimeFct opCall (scheduleFct f, TimeSpan t) { // static CTOR
|
|
89 TimeFct ret;
|
|
90 ret.fct = f;
|
|
91 ret.interval = t;
|
|
92 return ret;
|
|
93 }
|
|
94 }
|
|
95
|
|
96 private static Time lastTime = Time (0L);
|
|
97 private static scheduleFct[] frameFcts;
|
|
98 private static TimeFct[] timeFcts;
|
|
99 }
|