1 | /**************************************************************************/ |
2 | /* input_event.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
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 | |
31 | #ifndef INPUT_EVENT_H |
32 | #define INPUT_EVENT_H |
33 | |
34 | #include "core/input/input_enums.h" |
35 | #include "core/io/resource.h" |
36 | #include "core/math/transform_2d.h" |
37 | #include "core/os/keyboard.h" |
38 | #include "core/string/ustring.h" |
39 | #include "core/typedefs.h" |
40 | |
41 | /** |
42 | * Input Event classes. These are used in the main loop. |
43 | * The events are pretty obvious. |
44 | */ |
45 | |
46 | class Shortcut; |
47 | |
48 | /** |
49 | * Input Modifier Status |
50 | * for keyboard/mouse events. |
51 | */ |
52 | |
53 | class InputEvent : public Resource { |
54 | GDCLASS(InputEvent, Resource); |
55 | |
56 | int device = 0; |
57 | |
58 | protected: |
59 | bool canceled = false; |
60 | bool pressed = false; |
61 | |
62 | static void _bind_methods(); |
63 | |
64 | public: |
65 | static const int DEVICE_ID_EMULATION; |
66 | static const int DEVICE_ID_INTERNAL; |
67 | |
68 | void set_device(int p_device); |
69 | int get_device() const; |
70 | |
71 | bool is_action(const StringName &p_action, bool p_exact_match = false) const; |
72 | bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false, bool p_exact_match = false) const; |
73 | bool is_action_released(const StringName &p_action, bool p_exact_match = false) const; |
74 | float get_action_strength(const StringName &p_action, bool p_exact_match = false) const; |
75 | float get_action_raw_strength(const StringName &p_action, bool p_exact_match = false) const; |
76 | |
77 | bool is_canceled() const; |
78 | bool is_pressed() const; |
79 | bool is_released() const; |
80 | virtual bool is_echo() const; |
81 | |
82 | virtual String as_text() const = 0; |
83 | |
84 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; |
85 | |
86 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const; |
87 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const; |
88 | |
89 | virtual bool is_action_type() const; |
90 | |
91 | virtual bool accumulate(const Ref<InputEvent> &p_event) { return false; } |
92 | |
93 | InputEvent() {} |
94 | }; |
95 | |
96 | class InputEventFromWindow : public InputEvent { |
97 | GDCLASS(InputEventFromWindow, InputEvent); |
98 | |
99 | int64_t window_id = 0; |
100 | |
101 | protected: |
102 | static void _bind_methods(); |
103 | |
104 | public: |
105 | void set_window_id(int64_t p_id); |
106 | int64_t get_window_id() const; |
107 | |
108 | InputEventFromWindow() {} |
109 | }; |
110 | |
111 | class InputEventWithModifiers : public InputEventFromWindow { |
112 | GDCLASS(InputEventWithModifiers, InputEventFromWindow); |
113 | |
114 | bool command_or_control_autoremap = false; |
115 | |
116 | bool shift_pressed = false; |
117 | bool alt_pressed = false; |
118 | bool meta_pressed = false; // "Command" on macOS, "Meta/Win" key on other platforms. |
119 | bool ctrl_pressed = false; |
120 | |
121 | protected: |
122 | static void _bind_methods(); |
123 | void _validate_property(PropertyInfo &p_property) const; |
124 | |
125 | public: |
126 | void set_command_or_control_autoremap(bool p_enabled); |
127 | bool is_command_or_control_autoremap() const; |
128 | |
129 | bool is_command_or_control_pressed() const; |
130 | |
131 | void set_shift_pressed(bool p_pressed); |
132 | bool is_shift_pressed() const; |
133 | |
134 | void set_alt_pressed(bool p_pressed); |
135 | bool is_alt_pressed() const; |
136 | |
137 | void set_ctrl_pressed(bool p_pressed); |
138 | bool is_ctrl_pressed() const; |
139 | |
140 | void set_meta_pressed(bool p_pressed); |
141 | bool is_meta_pressed() const; |
142 | |
143 | void set_modifiers_from_event(const InputEventWithModifiers *event); |
144 | |
145 | BitField<KeyModifierMask> get_modifiers_mask() const; |
146 | |
147 | virtual String as_text() const override; |
148 | virtual String to_string() override; |
149 | |
150 | InputEventWithModifiers() {} |
151 | }; |
152 | |
153 | class InputEventKey : public InputEventWithModifiers { |
154 | GDCLASS(InputEventKey, InputEventWithModifiers); |
155 | |
156 | Key keycode = Key::NONE; // Key enum, without modifier masks. |
157 | Key physical_keycode = Key::NONE; |
158 | Key key_label = Key::NONE; |
159 | uint32_t unicode = 0; ///unicode |
160 | |
161 | bool echo = false; /// true if this is an echo key |
162 | |
163 | protected: |
164 | static void _bind_methods(); |
165 | |
166 | public: |
167 | void set_pressed(bool p_pressed); |
168 | |
169 | void set_keycode(Key p_keycode); |
170 | Key get_keycode() const; |
171 | |
172 | void set_physical_keycode(Key p_keycode); |
173 | Key get_physical_keycode() const; |
174 | |
175 | void set_key_label(Key p_key_label); |
176 | Key get_key_label() const; |
177 | |
178 | void set_unicode(char32_t p_unicode); |
179 | char32_t get_unicode() const; |
180 | |
181 | void set_echo(bool p_enable); |
182 | virtual bool is_echo() const override; |
183 | |
184 | Key get_keycode_with_modifiers() const; |
185 | Key get_physical_keycode_with_modifiers() const; |
186 | Key get_key_label_with_modifiers() const; |
187 | |
188 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; |
189 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; |
190 | |
191 | virtual bool is_action_type() const override { return true; } |
192 | |
193 | virtual String as_text_physical_keycode() const; |
194 | virtual String as_text_keycode() const; |
195 | virtual String as_text_key_label() const; |
196 | virtual String as_text() const override; |
197 | virtual String to_string() override; |
198 | |
199 | static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false); |
200 | |
201 | InputEventKey() {} |
202 | }; |
203 | |
204 | class InputEventMouse : public InputEventWithModifiers { |
205 | GDCLASS(InputEventMouse, InputEventWithModifiers); |
206 | |
207 | BitField<MouseButtonMask> button_mask; |
208 | |
209 | Vector2 pos; |
210 | Vector2 global_pos; |
211 | |
212 | protected: |
213 | static void _bind_methods(); |
214 | |
215 | public: |
216 | void set_button_mask(BitField<MouseButtonMask> p_mask); |
217 | BitField<MouseButtonMask> get_button_mask() const; |
218 | |
219 | void set_position(const Vector2 &p_pos); |
220 | Vector2 get_position() const; |
221 | |
222 | void set_global_position(const Vector2 &p_global_pos); |
223 | Vector2 get_global_position() const; |
224 | |
225 | InputEventMouse() {} |
226 | }; |
227 | |
228 | class InputEventMouseButton : public InputEventMouse { |
229 | GDCLASS(InputEventMouseButton, InputEventMouse); |
230 | |
231 | float factor = 1; |
232 | MouseButton button_index = MouseButton::NONE; |
233 | bool double_click = false; //last even less than double click time |
234 | |
235 | protected: |
236 | static void _bind_methods(); |
237 | |
238 | public: |
239 | void set_factor(float p_factor); |
240 | float get_factor() const; |
241 | |
242 | void set_button_index(MouseButton p_index); |
243 | MouseButton get_button_index() const; |
244 | |
245 | void set_pressed(bool p_pressed); |
246 | void set_canceled(bool p_canceled); |
247 | |
248 | void set_double_click(bool p_double_click); |
249 | bool is_double_click() const; |
250 | |
251 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
252 | |
253 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; |
254 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; |
255 | |
256 | virtual bool is_action_type() const override { return true; } |
257 | virtual String as_text() const override; |
258 | virtual String to_string() override; |
259 | |
260 | InputEventMouseButton() {} |
261 | }; |
262 | |
263 | class InputEventMouseMotion : public InputEventMouse { |
264 | GDCLASS(InputEventMouseMotion, InputEventMouse); |
265 | |
266 | Vector2 tilt; |
267 | float pressure = 0; |
268 | Vector2 relative; |
269 | Vector2 velocity; |
270 | bool pen_inverted = false; |
271 | |
272 | protected: |
273 | static void _bind_methods(); |
274 | |
275 | public: |
276 | void set_tilt(const Vector2 &p_tilt); |
277 | Vector2 get_tilt() const; |
278 | |
279 | void set_pressure(float p_pressure); |
280 | float get_pressure() const; |
281 | |
282 | void set_pen_inverted(bool p_inverted); |
283 | bool get_pen_inverted() const; |
284 | |
285 | void set_relative(const Vector2 &p_relative); |
286 | Vector2 get_relative() const; |
287 | |
288 | void set_velocity(const Vector2 &p_velocity); |
289 | Vector2 get_velocity() const; |
290 | |
291 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
292 | virtual String as_text() const override; |
293 | virtual String to_string() override; |
294 | |
295 | virtual bool accumulate(const Ref<InputEvent> &p_event) override; |
296 | |
297 | InputEventMouseMotion() {} |
298 | }; |
299 | |
300 | class InputEventJoypadMotion : public InputEvent { |
301 | GDCLASS(InputEventJoypadMotion, InputEvent); |
302 | JoyAxis axis = (JoyAxis)0; ///< Joypad axis |
303 | float axis_value = 0; ///< -1 to 1 |
304 | |
305 | protected: |
306 | static void _bind_methods(); |
307 | |
308 | public: |
309 | void set_axis(JoyAxis p_axis); |
310 | JoyAxis get_axis() const; |
311 | |
312 | void set_axis_value(float p_value); |
313 | float get_axis_value() const; |
314 | |
315 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; |
316 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; |
317 | |
318 | virtual bool is_action_type() const override { return true; } |
319 | virtual String as_text() const override; |
320 | virtual String to_string() override; |
321 | |
322 | static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value); |
323 | |
324 | InputEventJoypadMotion() {} |
325 | }; |
326 | |
327 | class InputEventJoypadButton : public InputEvent { |
328 | GDCLASS(InputEventJoypadButton, InputEvent); |
329 | |
330 | JoyButton button_index = (JoyButton)0; |
331 | float pressure = 0; //0 to 1 |
332 | protected: |
333 | static void _bind_methods(); |
334 | |
335 | public: |
336 | void set_button_index(JoyButton p_index); |
337 | JoyButton get_button_index() const; |
338 | |
339 | void set_pressed(bool p_pressed); |
340 | |
341 | void set_pressure(float p_pressure); |
342 | float get_pressure() const; |
343 | |
344 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; |
345 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; |
346 | |
347 | virtual bool is_action_type() const override { return true; } |
348 | |
349 | virtual String as_text() const override; |
350 | virtual String to_string() override; |
351 | |
352 | static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index); |
353 | |
354 | InputEventJoypadButton() {} |
355 | }; |
356 | |
357 | class InputEventScreenTouch : public InputEventFromWindow { |
358 | GDCLASS(InputEventScreenTouch, InputEventFromWindow); |
359 | int index = 0; |
360 | Vector2 pos; |
361 | bool double_tap = false; |
362 | |
363 | protected: |
364 | static void _bind_methods(); |
365 | |
366 | public: |
367 | void set_index(int p_index); |
368 | int get_index() const; |
369 | |
370 | void set_position(const Vector2 &p_pos); |
371 | Vector2 get_position() const; |
372 | |
373 | void set_pressed(bool p_pressed); |
374 | void set_canceled(bool p_canceled); |
375 | |
376 | void set_double_tap(bool p_double_tap); |
377 | bool is_double_tap() const; |
378 | |
379 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
380 | virtual String as_text() const override; |
381 | virtual String to_string() override; |
382 | |
383 | InputEventScreenTouch() {} |
384 | }; |
385 | |
386 | class InputEventScreenDrag : public InputEventFromWindow { |
387 | GDCLASS(InputEventScreenDrag, InputEventFromWindow); |
388 | int index = 0; |
389 | Vector2 pos; |
390 | Vector2 relative; |
391 | Vector2 velocity; |
392 | Vector2 tilt; |
393 | float pressure = 0; |
394 | bool pen_inverted = false; |
395 | |
396 | protected: |
397 | static void _bind_methods(); |
398 | |
399 | public: |
400 | void set_index(int p_index); |
401 | int get_index() const; |
402 | |
403 | void set_tilt(const Vector2 &p_tilt); |
404 | Vector2 get_tilt() const; |
405 | |
406 | void set_pressure(float p_pressure); |
407 | float get_pressure() const; |
408 | |
409 | void set_pen_inverted(bool p_inverted); |
410 | bool get_pen_inverted() const; |
411 | |
412 | void set_position(const Vector2 &p_pos); |
413 | Vector2 get_position() const; |
414 | |
415 | void set_relative(const Vector2 &p_relative); |
416 | Vector2 get_relative() const; |
417 | |
418 | void set_velocity(const Vector2 &p_velocity); |
419 | Vector2 get_velocity() const; |
420 | |
421 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
422 | virtual String as_text() const override; |
423 | virtual String to_string() override; |
424 | |
425 | virtual bool accumulate(const Ref<InputEvent> &p_event) override; |
426 | |
427 | InputEventScreenDrag() {} |
428 | }; |
429 | |
430 | class InputEventAction : public InputEvent { |
431 | GDCLASS(InputEventAction, InputEvent); |
432 | |
433 | StringName action; |
434 | float strength = 1.0f; |
435 | |
436 | protected: |
437 | static void _bind_methods(); |
438 | |
439 | public: |
440 | void set_action(const StringName &p_action); |
441 | StringName get_action() const; |
442 | |
443 | void set_pressed(bool p_pressed); |
444 | |
445 | void set_strength(float p_strength); |
446 | float get_strength() const; |
447 | |
448 | virtual bool is_action(const StringName &p_action) const; |
449 | |
450 | virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; |
451 | virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; |
452 | |
453 | virtual bool is_action_type() const override { return true; } |
454 | |
455 | virtual String as_text() const override; |
456 | virtual String to_string() override; |
457 | |
458 | InputEventAction() {} |
459 | }; |
460 | |
461 | class InputEventGesture : public InputEventWithModifiers { |
462 | GDCLASS(InputEventGesture, InputEventWithModifiers); |
463 | |
464 | Vector2 pos; |
465 | |
466 | protected: |
467 | static void _bind_methods(); |
468 | |
469 | public: |
470 | void set_position(const Vector2 &p_pos); |
471 | Vector2 get_position() const; |
472 | }; |
473 | |
474 | class InputEventMagnifyGesture : public InputEventGesture { |
475 | GDCLASS(InputEventMagnifyGesture, InputEventGesture); |
476 | real_t factor = 1.0; |
477 | |
478 | protected: |
479 | static void _bind_methods(); |
480 | |
481 | public: |
482 | void set_factor(real_t p_factor); |
483 | real_t get_factor() const; |
484 | |
485 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
486 | virtual String as_text() const override; |
487 | virtual String to_string() override; |
488 | |
489 | InputEventMagnifyGesture() {} |
490 | }; |
491 | |
492 | class InputEventPanGesture : public InputEventGesture { |
493 | GDCLASS(InputEventPanGesture, InputEventGesture); |
494 | Vector2 delta; |
495 | |
496 | protected: |
497 | static void _bind_methods(); |
498 | |
499 | public: |
500 | void set_delta(const Vector2 &p_delta); |
501 | Vector2 get_delta() const; |
502 | |
503 | virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; |
504 | virtual String as_text() const override; |
505 | virtual String to_string() override; |
506 | |
507 | InputEventPanGesture() {} |
508 | }; |
509 | |
510 | class InputEventMIDI : public InputEvent { |
511 | GDCLASS(InputEventMIDI, InputEvent); |
512 | |
513 | int channel = 0; |
514 | MIDIMessage message = MIDIMessage::NONE; |
515 | int pitch = 0; |
516 | int velocity = 0; |
517 | int instrument = 0; |
518 | int pressure = 0; |
519 | int controller_number = 0; |
520 | int controller_value = 0; |
521 | |
522 | protected: |
523 | static void _bind_methods(); |
524 | |
525 | public: |
526 | void set_channel(const int p_channel); |
527 | int get_channel() const; |
528 | |
529 | void set_message(const MIDIMessage p_message); |
530 | MIDIMessage get_message() const; |
531 | |
532 | void set_pitch(const int p_pitch); |
533 | int get_pitch() const; |
534 | |
535 | void set_velocity(const int p_velocity); |
536 | int get_velocity() const; |
537 | |
538 | void set_instrument(const int p_instrument); |
539 | int get_instrument() const; |
540 | |
541 | void set_pressure(const int p_pressure); |
542 | int get_pressure() const; |
543 | |
544 | void set_controller_number(const int p_controller_number); |
545 | int get_controller_number() const; |
546 | |
547 | void set_controller_value(const int p_controller_value); |
548 | int get_controller_value() const; |
549 | |
550 | virtual String as_text() const override; |
551 | virtual String to_string() override; |
552 | |
553 | InputEventMIDI() {} |
554 | }; |
555 | |
556 | class InputEventShortcut : public InputEvent { |
557 | GDCLASS(InputEventShortcut, InputEvent); |
558 | |
559 | Ref<Shortcut> shortcut; |
560 | |
561 | protected: |
562 | static void _bind_methods(); |
563 | |
564 | public: |
565 | void set_shortcut(Ref<Shortcut> p_shortcut); |
566 | Ref<Shortcut> get_shortcut(); |
567 | |
568 | virtual String as_text() const override; |
569 | virtual String to_string() override; |
570 | }; |
571 | |
572 | #endif // INPUT_EVENT_H |
573 | |