1 /*************************************************************************/
2 /* input_event.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "input_event.h"
31 #include "input_map.h"
32 #include "os/keyboard.h"
33 /**
34 *
35 */
36
operator ==(const InputEvent & p_event) const37 bool InputEvent::operator==(const InputEvent &p_event) const {
38 if (type != p_event.type) {
39 return false;
40 }
41
42 switch (type) {
43 /** Current clang-format style doesn't play well with the aligned return values of that switch. */
44 /* clang-format off */
45 case NONE:
46 return true;
47 case KEY:
48 return key.unicode == p_event.key.unicode
49 && key.scancode == p_event.key.scancode
50 && key.echo == p_event.key.echo
51 && key.pressed == p_event.key.pressed
52 && key.mod == p_event.key.mod;
53 case MOUSE_MOTION:
54 return mouse_motion.x == p_event.mouse_motion.x
55 && mouse_motion.y == p_event.mouse_motion.y
56 && mouse_motion.relative_x == p_event.mouse_motion.relative_x
57 && mouse_motion.relative_y == p_event.mouse_motion.relative_y
58 && mouse_motion.button_mask == p_event.mouse_motion.button_mask
59 && key.mod == p_event.key.mod;
60 case MOUSE_BUTTON:
61 return mouse_button.pressed == p_event.mouse_button.pressed
62 && mouse_button.x == p_event.mouse_button.x
63 && mouse_button.y == p_event.mouse_button.y
64 && mouse_button.button_index == p_event.mouse_button.button_index
65 && mouse_button.button_mask == p_event.mouse_button.button_mask
66 && key.mod == p_event.key.mod;
67 case JOYSTICK_MOTION:
68 return joy_motion.axis == p_event.joy_motion.axis
69 && joy_motion.axis_value == p_event.joy_motion.axis_value;
70 case JOYSTICK_BUTTON:
71 return joy_button.pressed == p_event.joy_button.pressed
72 && joy_button.button_index == p_event.joy_button.button_index
73 && joy_button.pressure == p_event.joy_button.pressure;
74 case SCREEN_TOUCH:
75 return screen_touch.pressed == p_event.screen_touch.pressed
76 && screen_touch.index == p_event.screen_touch.index
77 && screen_touch.x == p_event.screen_touch.x
78 && screen_touch.y == p_event.screen_touch.y;
79 case SCREEN_DRAG:
80 return screen_drag.index == p_event.screen_drag.index
81 && screen_drag.x == p_event.screen_drag.x
82 && screen_drag.y == p_event.screen_drag.y;
83 case ACTION:
84 return action.action == p_event.action.action
85 && action.pressed == p_event.action.pressed;
86 /* clang-format on */
87 default:
88 ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen.");
89 }
90
91 return false;
92 }
operator String() const93 InputEvent::operator String() const {
94
95 String str = "Device " + itos(device) + " ID " + itos(ID) + " ";
96
97 switch (type) {
98
99 case NONE: {
100
101 return "Event: None";
102 } break;
103 case KEY: {
104
105 str += "Event: Key ";
106 str = str + "Unicode: " + String::chr(key.unicode) + " Scan: " + itos(key.scancode) + " Echo: " + String(key.echo ? "True" : "False") + " Pressed" + String(key.pressed ? "True" : "False") + " Mod: ";
107 if (key.mod.shift)
108 str += "S";
109 if (key.mod.control)
110 str += "C";
111 if (key.mod.alt)
112 str += "A";
113 if (key.mod.meta)
114 str += "M";
115
116 return str;
117 } break;
118 case MOUSE_MOTION: {
119
120 str += "Event: Motion ";
121 str = str + " Pos: " + itos(mouse_motion.x) + "," + itos(mouse_motion.y) + " Rel: " + itos(mouse_motion.relative_x) + "," + itos(mouse_motion.relative_y) + " Mask: ";
122 for (int i = 0; i < 8; i++) {
123
124 if ((1 << i) & mouse_motion.button_mask)
125 str += itos(i + 1);
126 }
127 str += " Mod: ";
128 if (key.mod.shift)
129 str += "S";
130 if (key.mod.control)
131 str += "C";
132 if (key.mod.alt)
133 str += "A";
134 if (key.mod.meta)
135 str += "M";
136
137 return str;
138 } break;
139 case MOUSE_BUTTON: {
140 str += "Event: Button ";
141 str = str + "Pressed: " + itos(mouse_button.pressed) + " Pos: " + itos(mouse_button.x) + "," + itos(mouse_button.y) + " Button: " + itos(mouse_button.button_index) + " Mask: ";
142 for (int i = 0; i < 8; i++) {
143
144 if ((1 << i) & mouse_button.button_mask)
145 str += itos(i + 1);
146 }
147 str += " Mod: ";
148 if (key.mod.shift)
149 str += "S";
150 if (key.mod.control)
151 str += "C";
152 if (key.mod.alt)
153 str += "A";
154 if (key.mod.meta)
155 str += "M";
156
157 str += String(" DoubleClick: ") + (mouse_button.doubleclick ? "Yes" : "No");
158
159 return str;
160
161 } break;
162 case JOYSTICK_MOTION: {
163 str += "Event: JoystickMotion ";
164 str = str + "Axis: " + itos(joy_motion.axis) + " Value: " + rtos(joy_motion.axis_value);
165 return str;
166
167 } break;
168 case JOYSTICK_BUTTON: {
169 str += "Event: JoystickButton ";
170 str = str + "Pressed: " + itos(joy_button.pressed) + " Index: " + itos(joy_button.button_index) + " pressure " + rtos(joy_button.pressure);
171 return str;
172
173 } break;
174 case SCREEN_TOUCH: {
175 str += "Event: ScreenTouch ";
176 str = str + "Pressed: " + itos(screen_touch.pressed) + " Index: " + itos(screen_touch.index) + " pos " + rtos(screen_touch.x) + "," + rtos(screen_touch.y);
177 return str;
178
179 } break;
180 case SCREEN_DRAG: {
181 str += "Event: ScreenDrag ";
182 str = str + " Index: " + itos(screen_drag.index) + " pos " + rtos(screen_drag.x) + "," + rtos(screen_drag.y);
183 return str;
184
185 } break;
186 case ACTION: {
187 str += "Event: Action: " + InputMap::get_singleton()->get_action_from_id(action.action) + " Pressed: " + itos(action.pressed);
188 return str;
189
190 } break;
191 }
192
193 return "";
194 }
195
set_as_action(const String & p_action,bool p_pressed)196 void InputEvent::set_as_action(const String &p_action, bool p_pressed) {
197
198 type = ACTION;
199 action.action = InputMap::get_singleton()->get_action_id(p_action);
200 action.pressed = p_pressed;
201 }
202
is_pressed() const203 bool InputEvent::is_pressed() const {
204
205 switch (type) {
206
207 case KEY: return key.pressed;
208 case MOUSE_BUTTON: return mouse_button.pressed;
209 case JOYSTICK_BUTTON: return joy_button.pressed;
210 case SCREEN_TOUCH: return screen_touch.pressed;
211 case JOYSTICK_MOTION: return ABS(joy_motion.axis_value) > 0.5;
212 case ACTION: return action.pressed;
213 default: {}
214 }
215
216 return false;
217 }
218
is_echo() const219 bool InputEvent::is_echo() const {
220
221 return (type == KEY && key.echo);
222 }
223
is_action(const String & p_action) const224 bool InputEvent::is_action(const String &p_action) const {
225
226 return InputMap::get_singleton()->event_is_action(*this, p_action);
227 }
228
is_action_pressed(const String & p_action) const229 bool InputEvent::is_action_pressed(const String &p_action) const {
230
231 return is_action(p_action) && is_pressed() && !is_echo();
232 }
233
is_action_released(const String & p_action) const234 bool InputEvent::is_action_released(const String &p_action) const {
235
236 return is_action(p_action) && !is_pressed();
237 }
238
get_scancode_with_modifiers() const239 uint32_t InputEventKey::get_scancode_with_modifiers() const {
240
241 uint32_t sc = scancode;
242 if (mod.control)
243 sc |= KEY_MASK_CTRL;
244 if (mod.alt)
245 sc |= KEY_MASK_ALT;
246 if (mod.shift)
247 sc |= KEY_MASK_SHIFT;
248 if (mod.meta)
249 sc |= KEY_MASK_META;
250
251 return sc;
252 }
253
xform_by(const Matrix32 & p_xform) const254 InputEvent InputEvent::xform_by(const Matrix32 &p_xform) const {
255
256 InputEvent ev = *this;
257
258 switch (ev.type) {
259
260 case InputEvent::MOUSE_BUTTON: {
261
262 Vector2 g = p_xform.xform(Vector2(ev.mouse_button.global_x, ev.mouse_button.global_y));
263 Vector2 l = p_xform.xform(Vector2(ev.mouse_button.x, ev.mouse_button.y));
264 ev.mouse_button.x = l.x;
265 ev.mouse_button.y = l.y;
266 ev.mouse_button.global_x = g.x;
267 ev.mouse_button.global_y = g.y;
268
269 } break;
270 case InputEvent::MOUSE_MOTION: {
271
272 Vector2 g = p_xform.xform(Vector2(ev.mouse_motion.global_x, ev.mouse_motion.global_y));
273 Vector2 l = p_xform.xform(Vector2(ev.mouse_motion.x, ev.mouse_motion.y));
274 Vector2 r = p_xform.basis_xform(Vector2(ev.mouse_motion.relative_x, ev.mouse_motion.relative_y));
275 Vector2 s = p_xform.basis_xform(Vector2(ev.mouse_motion.speed_x, ev.mouse_motion.speed_y));
276 ev.mouse_motion.x = l.x;
277 ev.mouse_motion.y = l.y;
278 ev.mouse_motion.global_x = g.x;
279 ev.mouse_motion.global_y = g.y;
280 ev.mouse_motion.relative_x = r.x;
281 ev.mouse_motion.relative_y = r.y;
282 ev.mouse_motion.speed_x = s.x;
283 ev.mouse_motion.speed_y = s.y;
284
285 } break;
286 case InputEvent::SCREEN_TOUCH: {
287
288 Vector2 t = p_xform.xform(Vector2(ev.screen_touch.x, ev.screen_touch.y));
289 ev.screen_touch.x = t.x;
290 ev.screen_touch.y = t.y;
291
292 } break;
293 case InputEvent::SCREEN_DRAG: {
294
295 Vector2 t = p_xform.xform(Vector2(ev.screen_drag.x, ev.screen_drag.y));
296 Vector2 r = p_xform.basis_xform(Vector2(ev.screen_drag.relative_x, ev.screen_drag.relative_y));
297 Vector2 s = p_xform.basis_xform(Vector2(ev.screen_drag.speed_x, ev.screen_drag.speed_y));
298 ev.screen_drag.x = t.x;
299 ev.screen_drag.y = t.y;
300 ev.screen_drag.relative_x = r.x;
301 ev.screen_drag.relative_y = r.y;
302 ev.screen_drag.speed_x = s.x;
303 ev.screen_drag.speed_y = s.y;
304 } break;
305 }
306
307 return ev;
308 }
309