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