1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
-- Class: Timer
-- A timer allows delayed or periodic execution of a function according
-- to elapsed time in an app. In order for it to work properly, it must
-- receive update events, so it must be added somewhere in the current
-- view or app. If you are using the <View> class, then this is already
-- done for you; one is created as the View's timer property.
Timer = Sprite:extend{
timers = {},
visible = false,
active = false,
solid = false,
-- Method: wait
-- Method: after
-- Delays a function call after a certain a mount of time.
--
-- Arguments:
-- * delay - how long to wait, in seconds
-- * func - function to call
--
-- Returns:
-- A <Promise> that is fulfilled after the function is called
after = function (self, delay, func)
if STRICT then
assert(type(func) == 'function', 'func property of timer must be a function')
assert(type(delay) == 'number', 'delay must be a number')
if delay <= 0 then
local info = debug.getinfo(2, 'Sl')
print('Warning: timer delay is ' .. delay .. ', will be triggered immediately (' ..
info.short_src .. ', line ' .. info.currentline .. ')')
end
end
self.active = true
local promise = Promise:new()
table.insert(self.timers, { func = func, timeLeft = delay, promise = promise })
return promise
end,
-- Method: every
-- Repeatedly makes a function call. To stop these calls from
-- happening in the future, you must call stop().
--
-- Arguments:
-- * delay - how often to make the function call, in seconds
-- * func - function to call
--
-- Returns:
-- nothing
every = function (self, delay, func)
if STRICT then
assert(type(func) == 'function', 'func property of timer must be a function')
assert(type(delay) == 'number', 'delay must be a number')
if delay <= 0 then
local info = debug.getinfo(2, 'Sl')
print('Warning: timer delay is ' .. delay .. ', will be triggered immediately (' ..
info.short_src .. ', line ' .. info.currentline .. ')')
end
end
self.active = true
table.insert(self.timers, { func = func, timeLeft = delay, interval = delay })
end,
-- Method: status
-- Returns how much time is left before a function call is scheduled.
--
-- Arguments:
-- func - the function that is queued
--
-- Returns:
-- the time left until the soonest call matching these arguments,
-- or nil if there is no call scheduled
status = function (self, func, bind, arg)
local result
for _, t in pairs(self.timers) do
if t.func == func and (not result or result < t.timeLeft) then
result = t.timeLeft
end
end
return result
end,
-- Method: stop
-- Stops a timer from executing. The promise belonging to it is failed.
-- If there is no function associated with this timer, then this has no effect.
--
-- Arguments:
-- func - function to stop; if omitted, stops all timers
--
-- Returns:
-- nothing
stop = function (self, func, bind)
local found = false
for i, timer in ipairs(self.timers) do
if not func or timer.func == func then
if timer.promise then
timer.promise:fail('Timer stopped')
end
table.remove(self.timers, i)
found = true
end
end
if STRICT and not found then
local info = debug.getinfo(2, 'Sl')
print('Warning: asked to stop a timer on a function that was not queued (' ..
info.short_src .. ', line ' .. info.currentline .. ')')
end
end,
update = function (self, elapsed)
for i, timer in ipairs(self.timers) do
timer.timeLeft = timer.timeLeft - elapsed
if timer.timeLeft <= 0 then
if timer.promise then
timer.promise:fulfill(timer.func())
else
timer.func()
end
if timer.interval then
timer.timeLeft = timer.interval
keepActive = true
else
table.remove(self.timers, i)
end
else
keepActive = true
end
end
self.active = (#self.timers > 0)
end,
__tostring = function (self)
local result = 'Timer ('
if self.active then
result = result .. 'active, '
result = result .. #self.timers .. ' timers running'
else
result = result .. 'inactive'
end
return result .. ')'
end
}
|