2
-- This records the user's inputs for playback at a later time,
3
-- or saving to a file. You must start recording *after* all input
4
-- objects are set up, and you should only run one recorder at a time.
9
Recorder = Sprite:extend{
10
-- private property: elapsed
11
-- either time elapsed while recording or playing back, in seconds
14
-- private property: mousePosTimer
15
-- used to make sure mouse motions are recorded even if no other event occurs
19
-- The recorder is currently doing nothing.
22
-- Constant: RECORDING
23
-- The recorder is currently recording user input.
24
RECORDING = 'recording',
27
-- The recorder is currently playing back user input.
30
-- Property: mousePosInterval
31
-- How often, in seconds, we should capture the mouse position.
32
-- This records the mouse position when other events occur, too, so
33
-- it's possible the interval will be even higher in reality.
34
-- Setting this number lower will burn memory.
35
mousePosInterval = 0.05,
38
-- One of the state constants, indicates what the recorder is currently doing.
41
-- A table of inputs with timing information.
43
new = function (self, obj)
44
obj = self:extend(obj)
45
obj.state = Recorder.IDLE
51
-- Method: startRecording
52
-- Begins recording user inputs. If the recorder is already recording,
53
-- this has no effect.
56
-- record - Record to use. Any existing data is appended to.
57
-- If omitted, the current record is used. If the current
58
-- record is unset, this creates a new record.
63
startRecording = function (self, record)
64
if self.state ~= Recorder.IDLE then return end
67
self.record = record or self.record or {}
68
self.state = Recorder.RECORDING
70
self._mousePosTimer = 0
72
-- insert ourselves into event handlers
76
-- Method: stopRecording
77
-- Stops recording user inputs. If the recorder wasn't recording anyway,
86
stopRecording = function (self)
87
if self.state ~= Recorder.RECORDING then return end
89
self.state = Recorder.IDLE
91
love.keypressed = self.origKeyPressed
92
love.keyreleased = self.origKeyReleased
95
-- Method: startPlaying
96
-- Starts playing back user inputs. If this is already playing
97
-- a recording, this restarts it.
100
-- record - Record to play back. If omitted, this uses
101
-- the recorder's record property.
106
startPlaying = function (self, record)
107
record = record or self.record
109
-- if we are currently recording, ignore the request
111
if self.state == Recorder.RECORDING then return end
115
if self.state == Recorder.PLAYING then
119
self.state = Recorder.PLAYING
122
self.playbackIndex = 1
126
-- Method: stopPlaying
127
-- Stops playing back user inputs.
135
stopPlaying = function (self)
136
if not self.state == Recorder.PLAYING then return end
137
self.state = Recorder.IDLE
141
stealInputs = function (self)
144
self.origKeyPressed = love.keypressed
145
love.keypressed = function (key, code) this:recordKeyPress(key, code) end
146
self.origKeyReleased = love.keyreleased
147
love.keyreleased = function (key, code) this:recordKeyRelease(key, code) end
148
self.origMousePressed = love.mousepressed
149
love.mousepressed = function (x, y, button) this:recordMousePress(x, y, button) end
150
self.origMouseReleased = love.mousereleased
151
love.mousereleased = function (x, y, button) this:recordMouseRelease(x, y, button) end
154
restoreInputs = function (self)
155
love.keypressed = self.origKeyPressed
156
love.keyreleased = self.origKeyReleased
157
love.mousepressed = self.origMousePressed
158
love.mousereleased = self.origMouseReleased
161
recordKeyPress = function (self, key, unicode)
162
table.insert(self.record, { self._elapsed, the.mouse.x, the.mouse.y, 'keypress', key, unicode })
163
self._mousePosTimer = 0
165
if self.origKeyPressed then
166
self.origKeyPressed(key, unicode)
170
recordKeyRelease = function (self, key, unicode)
171
table.insert(self.record, { self._elapsed, the.mouse.x, the.mouse.y, 'keyrelease', key, unicode })
172
self._mousePosTimer = 0
174
if self.origKeyReleased then
175
self.origKeyReleased(key, unicode)
179
recordMousePress = function (self, x, y, button)
180
table.insert(self.record, { self._elapsed, x, y, 'mousepress', button })
181
self._mousePosTimer = 0
183
if self.origMousePressed then
184
self.origMousePressed(x, y, button)
188
recordMouseRelease = function (self, x, y, button)
189
table.insert(self.record, { self._elapsed, x, y, 'mouserelease', button })
190
self._mousePosTimer = 0
192
if self.origMouseReleased then
193
self.origMouseReleased(x, y, button)
197
update = function (self, elapsed)
200
if self.state ~= Recorder.IDLE then
201
self._elapsed = self._elapsed + elapsed
204
-- record mouse position if the timer has expired
206
if self.state == Recorder.RECORDING then
207
self._mousePosTimer = self._mousePosTimer + elapsed
209
if self._mousePosTimer > self.mousePosInterval then
210
table.insert(self.record, { self._elapsed, the.mouse.x, the.mouse.y })
212
self._mousePosTimer = 0
218
if self.state == Recorder.PLAYING and self._elapsed >= self.record[self.playbackIndex][1] then
219
local event = self.record[self.playbackIndex]
221
love.mouse.setPosition(event[2], event[3])
223
if event[4] == 'keypress' and self.origKeyPressed then
224
self.origKeyPressed(event[5], event[6])
225
elseif event[4] == 'keyrelease' and self.origKeyReleased then
226
self.origKeyReleased(event[5], event[6])
227
elseif event[4] == 'mousepress' and self.origMousePressed then
228
self.origMousePressed(event[2], event[3], event[5])
229
elseif event[4] == 'mouserelease' and self.origMouseReleased then
230
self.origMouseReleased(event[2], event[3], event[5])
233
self.playbackIndex = self.playbackIndex + 1
235
if self.playbackIndex > #self.record then