/ld27

To get this branch, use:
bzr branch http://9ix.org/bzr/ld27
1 by Josh C
zoetrope 1.4
1
-- Class: Keys
2
-- This tracks the state of the keyboard, i.e. if a key
3
-- was just pressed or released this frame. You can look
4
-- up a key either by its name or its Unicode number.
5
-- Not all keys sensed have Unicode equivalents (e.g. modifiers
6
-- like Control or Alt).
7
--
8
-- Only one Keys object can be active at one time. The one currently
9
-- listening to the keyboard can be accessed globally via <the>.keys.
10
--
11
-- See http://love2d.org/wiki/KeyConstant for a list of key names.
12
-- This class aliases modifiers for you, so that if you want to check
13
-- whether either the left or right Control key is pressed, you can check
14
-- on 'ctrl' instead of both 'lctrl' and 'rctrl'.
15
--
16
-- Extends:
17
--		<Sprite>
18
19
Keys = Sprite:extend
20
{
21
	visible = false,
22
23
	-- Property: typed
24
	-- This is literally what is being typed during the current frame.
25
	-- e.g. if the user holds the shift key and presses the 'a' key,
26
	-- this will be set to 'A'. Consult <allPressed()> if you
27
	-- want to know what specific keys are being pressed.
28
29
	typed = '',
30
31
	-- private property: _thisFrame
32
	-- what keys are pressed this frame
33
	-- if you are interested in this, use allPressed() instead
34
35
	_thisFrame = {},
36
35 by Josh C
cluke009 zoetrope + my spritebatch changes
37
	-- private property: _alreadyHandled
38
	-- was the key already processed by the user code since it was pressed?
39
	-- Useful for handling repeated keys, check <pressed> and then you can see
40
	-- if the key was repeated.
41
42
	_alreadyHandled = {},
43
1 by Josh C
zoetrope 1.4
44
	-- private property: _lastFrame
45
	-- what keys were pressed last frame
46
	
47
	_lastFrame = {},
48
	
49
	new = function (self, obj)
50
		obj = self:extend(obj)
51
		the.keys = obj
52
		love.keypressed = function (key, unicode) obj:keyPressed(key, unicode) end
53
		love.keyreleased = function (key, unicode) obj:keyReleased(key, unicode) end
35 by Josh C
cluke009 zoetrope + my spritebatch changes
54
		love.textinput = function (text) obj:textInput(text) end
1 by Josh C
zoetrope 1.4
55
		if obj.onNew then obj:onNew() end
56
		return obj
57
	end,
58
	
59
	-- Method: pressed
60
	-- Are *any* of the keys passed held down this frame?
61
	--
62
	-- Arguments:
63
	--		string key descriptions passed as individual arguments
64
	--
65
	-- Returns:
66
	-- 		boolean
67
68
	pressed = function (self, ...)
69
		local keys = {...}
70
		for _, value in pairs(keys) do
71
			if STRICT then
72
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
73
			end
74
75
			if self._thisFrame[value] then
76
				return true
77
			end
78
		end
79
		
80
		return false
81
	end,
82
83
	-- Method: justPressed
84
	-- Are *any* of the keys passed pressed for the first time this frame?
85
	--
86
	-- Arguments:
87
	--		string key descriptions passed as individual arguments
88
	--
89
	-- Returns:
90
	-- 		boolean
91
92
	justPressed = function (self, ...)
93
		local keys = {...}
94
95
		for _, value in pairs(keys) do
96
			if STRICT then
97
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
98
			end
99
100
			if self._thisFrame[value] and not self._lastFrame[value] then
101
				return true
102
			end
103
		end
104
		
105
		return false
106
	end,
107
108
	-- Method: released
109
	-- Are *all* of the keys passed not held down this frame?
110
	-- 
111
	-- Arguments:
112
	--		string key descriptions passed as individual arguments
113
	--
114
	-- Returns:
115
	-- 		boolean
116
117
	released = function (self, ...)
118
		local keys = {...}
119
120
		for _, value in pairs(keys) do
121
			if STRICT then
122
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
123
			end
124
125
			if self._thisFrame[value] then
126
				return false
127
			end
128
		end
129
		
130
		return true
131
	end,
132
133
	-- Method: justReleased
134
	-- Are *any* of the keys passed released after being held last frame?
135
	--
136
	-- Arguments:
137
	--		string key descriptions passed as individual arguments
138
	--
139
	-- Returns:
140
	-- 		boolean
141
142
	justReleased = function (self, ...)
143
		local keys = {...}
144
145
		for _, value in pairs(keys) do
146
			if STRICT then
147
				assert(type(value) == 'string', 'all keys are strings; asked to check a ' .. type(value))
148
			end
149
150
			if self._lastFrame[value] and not self._thisFrame[value] then
151
				return true
152
			end
153
		end
154
		
155
		return false
156
	end,
157
158
	-- Method: allPressed
159
	-- Returns all buttons currently pressed this frame.
160
	--
161
	-- Arguments:
162
	--		none
163
	--
164
	-- Returns:
165
	--		string key descriptions; if nothing is pressed, nil
166
167
	allPressed = function (self)
168
		local result = {}
169
170
		for key, value in pairs(self._thisFrame) do
171
			if value then table.insert(result, key) end
172
		end
173
		
174
		return unpack(result)
175
	end,
176
177
	-- Method: allJustPressed
178
	-- Returns all keys just pressed this frame.
179
	--
180
	-- Arguments:
181
	--		none
182
	--
183
	-- Returns:
184
	--		string key descriptions; if nothing is just pressed, nil
185
186
	allJustPressed = function (self)
187
		local result = {}
188
189
		for key, value in pairs(self._thisFrame) do
190
			if value and not self._lastFrame[key] then table.insert(result, key) end
191
		end
192
		
193
		return unpack(result)
194
	end,
195
196
	-- Method: allJustReleased
197
	-- Returns all keys just released this frame.
198
	--
199
	-- Arguments:
200
	--		none
201
	--
202
	-- Returns:
203
	--		string key descriptions; if nothing is just pressed, nil
204
205
	allJustReleased = function (self)
206
		local result = {}
207
208
		for key, value in pairs(self._thisFrame) do
209
			if not value and self._lastFrame[key] then table.insert(result, key) end
210
		end
211
		
212
		return unpack(result)
213
	end,
214
35 by Josh C
cluke009 zoetrope + my spritebatch changes
215
	-- Method: alreadyHandled
216
	-- Returns whether this key was already handled since it was pressed.
217
	-- Also sets the flag that something was handled, when calling.
218
219
	alreadyHandled = function (self, key)
220
		if not self._alreadyHandled[key] then
221
			-- mark preemptively as handled
222
			self._alreadyHandled[key] = true
223
			-- return false, because we need to handle it
224
			return false
225
		end
226
		return true
227
	end,
228
1 by Josh C
zoetrope 1.4
229
	-- Converts a character code to a Unicode string
230
	-- see http://stackoverflow.com/questions/7780179/what-is-the-way-to-represent-a-unichar-in-lua/7799843
231
232
	unicodeChar = function (self, code)
233
		if code == nil then return nil end
234
		if code < 32 then return string.format('\\x%02x', code) end
235
		if code < 126 then return string.char(code) end
236
		if code < 65539 then return string.format("\\u%04x", code) end
237
		if code < 1114111 then return string.format("\\u%08x", code) end
238
	end,
239
240
	-- Connects to the love.keypressed callback
241
35 by Josh C
cluke009 zoetrope + my spritebatch changes
242
	keyPressed = function (self, key, isrepeat)
1 by Josh C
zoetrope 1.4
243
		self._thisFrame[key] = true
35 by Josh C
cluke009 zoetrope + my spritebatch changes
244
245
		self._alreadyHandled[key] = false
246
		--if unicode and unicode >= 0x20 and unicode ~= 127 and unicode < 0x3000 then
247
		--	self.typed = self.typed .. self:unicodeChar(unicode)
248
		--end
1 by Josh C
zoetrope 1.4
249
250
		-- aliases for modifiers
251
252
		if key == 'rshift' or key == 'lshift' or
253
		   key == 'rctrl' or key == 'lctrl' or
254
		   key == 'ralt' or key == 'lalt' or
255
		   key == 'rmeta' or key == 'lmeta' or
256
		   key == 'rsuper' or key == 'lsuper' then
257
			self._thisFrame[string.sub(key, 2)] = true
258
		end
259
	end,
260
35 by Josh C
cluke009 zoetrope + my spritebatch changes
261
	-- Connects to the love.textinput callback
262
263
	textInput = function (self, text)
264
		self.typed = self.typed .. text
265
	end,
266
1 by Josh C
zoetrope 1.4
267
	-- Connects to the love.keyreleased callback
268
269
	keyReleased = function (self, key, unicode)
270
		self._thisFrame[key] = false
271
272
		-- aliases for modifiers
273
274
		if key == 'rshift' or key == 'lshift' or
275
		   key == 'rctrl' or key == 'lctrl' or
276
		   key == 'ralt' or key == 'lalt' or
277
		   key == 'rmeta' or key == 'lmeta' or
278
		   key == 'rsuper' or key == 'lsuper' then
279
			self._thisFrame[string.sub(key, 2)] = false
280
		end
281
	end,
282
283
	endFrame = function (self, elapsed)
284
		for key, value in pairs(self._thisFrame) do
285
			self._lastFrame[key] = value
286
		end
287
288
		self.typed = ''
289
		Sprite.endFrame(self, elapsed)
290
	end,
291
292
	update = function() end
293
}