add keyboard capturing to input
s-ol
3 years ago
0 | utf8 = require 'utf8' | |
0 | 1 | import vec2 from require 'cpml' |
1 | 2 | |
2 | 3 | class Input |
4 | NON_TEXT_KEYS = {k,true for k in *{'escape', 'return', 'clear'}} | |
3 | 5 | new: => |
4 | 6 | @last_keys = {} |
5 | 7 | @keys = {} |
7 | 9 | @last_mouse = vec2! |
8 | 10 | @mouse = @last_mouse\clone! |
9 | 11 | |
12 | @text = nil | |
13 | ||
10 | 14 | mouse_down: (button=1) => @key_down "mouse-#{button}" |
11 | 15 | mouse_up: (button=1) => @key_up "mouse-#{button}" |
12 | 16 | mouse_held: (button=1) => @key_held "mouse-#{button}" |
13 | mouse_event: (button=1) => @key_event "mouse-#{button}" | |
17 | mouse_event: (button=1) => (@key_event "mouse-#{button}") or 'hover' | |
14 | 18 | |
15 | 19 | key_down: (key) => @keys[key] and not @last_keys[key] |
16 | 20 | key_up: (key) => not @keys[key] and @last_keys[key] |
19 | 23 | return 'down' if @key_down key |
20 | 24 | return 'up' if @key_up key |
21 | 25 | return 'held' if @key_held key |
22 | return 'hover' | |
26 | ||
27 | text_capture: => | |
28 | assert not @text, "keyboard already captured!" | |
29 | @text = '' | |
30 | ||
31 | text_release: => | |
32 | with @text | |
33 | @text = nil | |
23 | 34 | |
24 | 35 | mouse_pos: => @mouse |
25 | 36 | mouse_delta: => @mouse - @last_mouse |
26 | 37 | |
27 | keypressed: (key) => @keys[key] = true | |
28 | 38 | keyreleased: (key) => @keys[key] = nil |
39 | keypressed: (key) => | |
40 | if @text and not NON_TEXT_KEYS[key] | |
41 | @textinput nil, key | |
42 | return | |
43 | ||
44 | @keys[key] = true | |
45 | ||
46 | textinput: (str, key) => | |
47 | return unless @text | |
48 | if str | |
49 | @text ..= str | |
50 | else | |
51 | switch key | |
52 | when 'backspace' | |
53 | offset = utf8.offset @text, -1 | |
54 | @text = string.sub @text, 1, offset - 1 if offset | |
29 | 55 | |
30 | 56 | mousemoved: (x, y) => @mouse.x, @mouse.y = x, y |
31 | 57 | mousepressed: (_, _, button) => @keys["mouse-#{button}"] = true |
8 | 8 | assert.is_falsy input\mouse_down! |
9 | 9 | assert.is_falsy input\mouse_up! |
10 | 10 | assert.is_falsy input\mouse_held! |
11 | assert.is_falsy input\mouse_event! | |
11 | assert.is_equal 'hover', input\mouse_event! | |
12 | 12 | assert.is_falsy input\key_down 'w' |
13 | 13 | assert.is_falsy input\key_up 'w' |
14 | 14 | assert.is_falsy input\key_held 'w' |
93 | 93 | assert.is_falsy input\key_held 'a' |
94 | 94 | assert.is_falsy input\key_down 'a' |
95 | 95 | assert.is_equal 'up', input\key_event 'a' |
96 | ||
97 | it "allows capturing the keyboard", -> | |
98 | input\text_capture! | |
99 | assert.has_error -> input\text_capture! | |
100 | ||
101 | input\textinput 'Helloo' | |
102 | input\keypressed 'backspace' | |
103 | assert.is_falsy input\key_down 'backspace' | |
104 | input\frame! | |
105 | ||
106 | assert.is_equal 'Hello', input.text | |
107 | input\textinput ' World' | |
108 | assert.is_equal 'Hello World', input.text | |
109 | assert.is_falsy input\key_down 'backspace' | |
110 | ||
111 | it "doesn't capture meta-keys (return and escape)", -> | |
112 | input\keypressed 'return' | |
113 | input\keypressed 'escape' | |
114 | ||
115 | assert.is_true input\key_down 'return' | |
116 | assert.is_true input\key_down 'escape' | |
117 | ||
118 | it "returns the input' text after releasing the keyboard", -> | |
119 | assert.is_equal 'Hello World', input\text_release! | |
120 | ||
121 | input\keypressed 'backspace' | |
122 | assert.is_true input\key_down 'backspace' |