Blame


1 a0b1acd8 2022-12-18 op --
2 a0b1acd8 2022-12-18 op -- tick
3 a0b1acd8 2022-12-18 op --
4 a0b1acd8 2022-12-18 op -- Copyright (c) 2015 rxi
5 a0b1acd8 2022-12-18 op --
6 a0b1acd8 2022-12-18 op -- This library is free software; you can redistribute it and/or modify it
7 a0b1acd8 2022-12-18 op -- under the terms of the MIT license. See LICENSE for details.
8 a0b1acd8 2022-12-18 op --
9 a0b1acd8 2022-12-18 op
10 a0b1acd8 2022-12-18 op local tick = { _version = "0.1.1" }
11 a0b1acd8 2022-12-18 op tick.__index = tick
12 a0b1acd8 2022-12-18 op
13 a0b1acd8 2022-12-18 op
14 a0b1acd8 2022-12-18 op local iscallable = function(x)
15 a0b1acd8 2022-12-18 op if type(x) == "function" then return true end
16 a0b1acd8 2022-12-18 op local mt = getmetatable(x)
17 a0b1acd8 2022-12-18 op return mt and mt.__call ~= nil
18 a0b1acd8 2022-12-18 op end
19 a0b1acd8 2022-12-18 op
20 a0b1acd8 2022-12-18 op local noop = function()
21 a0b1acd8 2022-12-18 op end
22 a0b1acd8 2022-12-18 op
23 a0b1acd8 2022-12-18 op
24 a0b1acd8 2022-12-18 op local event = {}
25 a0b1acd8 2022-12-18 op event.__index = event
26 a0b1acd8 2022-12-18 op
27 a0b1acd8 2022-12-18 op function event.new(parent, fn, delay, recur, err)
28 a0b1acd8 2022-12-18 op err = err or 0
29 a0b1acd8 2022-12-18 op -- Create and return event
30 a0b1acd8 2022-12-18 op return setmetatable({
31 a0b1acd8 2022-12-18 op parent = parent,
32 a0b1acd8 2022-12-18 op delay = delay,
33 a0b1acd8 2022-12-18 op timer = delay + err,
34 a0b1acd8 2022-12-18 op fn = fn,
35 a0b1acd8 2022-12-18 op recur = recur,
36 a0b1acd8 2022-12-18 op }, event)
37 a0b1acd8 2022-12-18 op end
38 a0b1acd8 2022-12-18 op
39 a0b1acd8 2022-12-18 op
40 a0b1acd8 2022-12-18 op function event:after(fn, delay)
41 a0b1acd8 2022-12-18 op -- Error check
42 a0b1acd8 2022-12-18 op if self.recur then
43 a0b1acd8 2022-12-18 op error("cannot chain a recurring event")
44 a0b1acd8 2022-12-18 op end
45 a0b1acd8 2022-12-18 op -- Chain event
46 a0b1acd8 2022-12-18 op local oldfn = self.fn
47 a0b1acd8 2022-12-18 op local e = event.new(self.parent, fn, delay, false)
48 a0b1acd8 2022-12-18 op self.fn = function()
49 a0b1acd8 2022-12-18 op oldfn()
50 a0b1acd8 2022-12-18 op e.timer = e.timer + self.parent.err
51 a0b1acd8 2022-12-18 op self.parent:add(e)
52 a0b1acd8 2022-12-18 op end
53 a0b1acd8 2022-12-18 op return e
54 a0b1acd8 2022-12-18 op end
55 a0b1acd8 2022-12-18 op
56 a0b1acd8 2022-12-18 op
57 a0b1acd8 2022-12-18 op function event:stop()
58 a0b1acd8 2022-12-18 op tick.remove(self.parent, self)
59 a0b1acd8 2022-12-18 op end
60 a0b1acd8 2022-12-18 op
61 a0b1acd8 2022-12-18 op
62 a0b1acd8 2022-12-18 op
63 a0b1acd8 2022-12-18 op function tick.group()
64 a0b1acd8 2022-12-18 op return setmetatable({ err = 0 }, tick)
65 a0b1acd8 2022-12-18 op end
66 a0b1acd8 2022-12-18 op
67 a0b1acd8 2022-12-18 op
68 a0b1acd8 2022-12-18 op function tick:add(e)
69 a0b1acd8 2022-12-18 op self[e] = true
70 a0b1acd8 2022-12-18 op table.insert(self, e)
71 a0b1acd8 2022-12-18 op return e
72 a0b1acd8 2022-12-18 op end
73 a0b1acd8 2022-12-18 op
74 a0b1acd8 2022-12-18 op
75 a0b1acd8 2022-12-18 op function tick:remove(e)
76 a0b1acd8 2022-12-18 op if type(e) == "number" then
77 a0b1acd8 2022-12-18 op -- Remove and return event
78 a0b1acd8 2022-12-18 op local idx = e
79 a0b1acd8 2022-12-18 op e = self[idx]
80 a0b1acd8 2022-12-18 op self[e] = nil
81 a0b1acd8 2022-12-18 op self[idx] = self[#self]
82 a0b1acd8 2022-12-18 op table.remove(self)
83 a0b1acd8 2022-12-18 op return e
84 a0b1acd8 2022-12-18 op end
85 a0b1acd8 2022-12-18 op self[e] = false
86 a0b1acd8 2022-12-18 op for i, v in ipairs(self) do
87 a0b1acd8 2022-12-18 op if v == e then
88 a0b1acd8 2022-12-18 op return self:remove(i)
89 a0b1acd8 2022-12-18 op end
90 a0b1acd8 2022-12-18 op end
91 a0b1acd8 2022-12-18 op end
92 a0b1acd8 2022-12-18 op
93 a0b1acd8 2022-12-18 op
94 a0b1acd8 2022-12-18 op function tick:update(dt)
95 a0b1acd8 2022-12-18 op for i = #self, 1, -1 do
96 a0b1acd8 2022-12-18 op local e = self[i]
97 a0b1acd8 2022-12-18 op e.timer = e.timer - dt
98 a0b1acd8 2022-12-18 op while e.timer <= 0 do
99 a0b1acd8 2022-12-18 op if e.recur then
100 a0b1acd8 2022-12-18 op e.timer = e.timer + e.delay
101 a0b1acd8 2022-12-18 op else
102 a0b1acd8 2022-12-18 op self:remove(i)
103 a0b1acd8 2022-12-18 op end
104 a0b1acd8 2022-12-18 op self.err = e.timer
105 a0b1acd8 2022-12-18 op e.fn()
106 a0b1acd8 2022-12-18 op if not e.recur then
107 a0b1acd8 2022-12-18 op break
108 a0b1acd8 2022-12-18 op end
109 a0b1acd8 2022-12-18 op end
110 a0b1acd8 2022-12-18 op end
111 a0b1acd8 2022-12-18 op self.err = 0
112 a0b1acd8 2022-12-18 op end
113 a0b1acd8 2022-12-18 op
114 a0b1acd8 2022-12-18 op
115 a0b1acd8 2022-12-18 op function tick:event(fn, delay, recur)
116 a0b1acd8 2022-12-18 op delay = tonumber(delay)
117 a0b1acd8 2022-12-18 op -- Error check
118 a0b1acd8 2022-12-18 op if not iscallable(fn) then
119 a0b1acd8 2022-12-18 op error("expected `fn` to be callable")
120 a0b1acd8 2022-12-18 op end
121 a0b1acd8 2022-12-18 op if type(delay) ~= "number" then
122 a0b1acd8 2022-12-18 op error("expected `delay` to be a number")
123 a0b1acd8 2022-12-18 op end
124 a0b1acd8 2022-12-18 op if delay < 0 then
125 a0b1acd8 2022-12-18 op error("expected `delay` of zero or greater")
126 a0b1acd8 2022-12-18 op end
127 a0b1acd8 2022-12-18 op -- If, factoring in the timing error, the event should happen *now* the
128 a0b1acd8 2022-12-18 op -- function is immediately called and the error is temporarily carried
129 a0b1acd8 2022-12-18 op -- through. This assures nested events with delays shorter than the update()
130 a0b1acd8 2022-12-18 op -- delta-time do not accumulate error; several nested events with very small
131 a0b1acd8 2022-12-18 op -- delays may end up being called on the same frame. A dummy event is created
132 a0b1acd8 2022-12-18 op -- and returned so :after() still functions correctly.
133 a0b1acd8 2022-12-18 op local d = delay + self.err
134 a0b1acd8 2022-12-18 op if d < 0 then
135 a0b1acd8 2022-12-18 op local err = self.err
136 a0b1acd8 2022-12-18 op self.err = d
137 a0b1acd8 2022-12-18 op fn()
138 a0b1acd8 2022-12-18 op self.err = err
139 a0b1acd8 2022-12-18 op return self:add(event.new(self, noop, delay, recur, self.err))
140 a0b1acd8 2022-12-18 op end
141 a0b1acd8 2022-12-18 op -- Create, add and return a normal event
142 a0b1acd8 2022-12-18 op return self:add(event.new(self, fn, delay, recur, self.err))
143 a0b1acd8 2022-12-18 op end
144 a0b1acd8 2022-12-18 op
145 a0b1acd8 2022-12-18 op
146 a0b1acd8 2022-12-18 op function tick:delay(fn, delay)
147 a0b1acd8 2022-12-18 op return self:event(fn, delay, false)
148 a0b1acd8 2022-12-18 op end
149 a0b1acd8 2022-12-18 op
150 a0b1acd8 2022-12-18 op
151 a0b1acd8 2022-12-18 op function tick:recur(fn, delay)
152 a0b1acd8 2022-12-18 op return self:event(fn, delay, true)
153 a0b1acd8 2022-12-18 op end
154 a0b1acd8 2022-12-18 op
155 a0b1acd8 2022-12-18 op
156 a0b1acd8 2022-12-18 op local group = tick.group()
157 a0b1acd8 2022-12-18 op
158 a0b1acd8 2022-12-18 op local bound = {
159 a0b1acd8 2022-12-18 op update = function(...) return tick.update(group, ...) end,
160 a0b1acd8 2022-12-18 op delay = function(...) return tick.delay (group, ...) end,
161 a0b1acd8 2022-12-18 op recur = function(...) return tick.recur (group, ...) end,
162 a0b1acd8 2022-12-18 op remove = function(...) return tick.remove(group, ...) end,
163 a0b1acd8 2022-12-18 op }
164 a0b1acd8 2022-12-18 op setmetatable(bound, tick)
165 a0b1acd8 2022-12-18 op
166 a0b1acd8 2022-12-18 op return bound