1/**************************************************************************/
2/* input_event.cpp */
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#include "input_event.h"
32
33#include "core/input/input_map.h"
34#include "core/input/shortcut.h"
35#include "core/os/keyboard.h"
36#include "core/os/os.h"
37
38const int InputEvent::DEVICE_ID_EMULATION = -1;
39const int InputEvent::DEVICE_ID_INTERNAL = -2;
40
41void InputEvent::set_device(int p_device) {
42 device = p_device;
43 emit_changed();
44}
45
46int InputEvent::get_device() const {
47 return device;
48}
49
50bool InputEvent::is_action(const StringName &p_action, bool p_exact_match) const {
51 return InputMap::get_singleton()->event_is_action(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match);
52}
53
54bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo, bool p_exact_match) const {
55 bool pressed_state;
56 bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, &pressed_state, nullptr, nullptr);
57 return valid && pressed_state && (p_allow_echo || !is_echo());
58}
59
60bool InputEvent::is_action_released(const StringName &p_action, bool p_exact_match) const {
61 bool pressed_state;
62 bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, &pressed_state, nullptr, nullptr);
63 return valid && !pressed_state;
64}
65
66float InputEvent::get_action_strength(const StringName &p_action, bool p_exact_match) const {
67 float strength;
68 bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, nullptr, &strength, nullptr);
69 return valid ? strength : 0.0f;
70}
71
72float InputEvent::get_action_raw_strength(const StringName &p_action, bool p_exact_match) const {
73 float raw_strength;
74 bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>(const_cast<InputEvent *>(this)), p_action, p_exact_match, nullptr, nullptr, &raw_strength);
75 return valid ? raw_strength : 0.0f;
76}
77
78bool InputEvent::is_canceled() const {
79 return canceled;
80}
81
82bool InputEvent::is_pressed() const {
83 return pressed && !canceled;
84}
85
86bool InputEvent::is_released() const {
87 return !pressed && !canceled;
88}
89
90bool InputEvent::is_echo() const {
91 return false;
92}
93
94Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
95 return Ref<InputEvent>(const_cast<InputEvent *>(this));
96}
97
98bool InputEvent::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 {
99 return false;
100}
101
102bool InputEvent::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
103 return false;
104}
105
106bool InputEvent::is_action_type() const {
107 return false;
108}
109
110void InputEvent::_bind_methods() {
111 ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
112 ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device);
113
114 ClassDB::bind_method(D_METHOD("is_action", "action", "exact_match"), &InputEvent::is_action, DEFVAL(false));
115 ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "allow_echo", "exact_match"), &InputEvent::is_action_pressed, DEFVAL(false), DEFVAL(false));
116 ClassDB::bind_method(D_METHOD("is_action_released", "action", "exact_match"), &InputEvent::is_action_released, DEFVAL(false));
117 ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &InputEvent::get_action_strength, DEFVAL(false));
118
119 ClassDB::bind_method(D_METHOD("is_canceled"), &InputEvent::is_canceled);
120 ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed);
121 ClassDB::bind_method(D_METHOD("is_released"), &InputEvent::is_released);
122 ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
123
124 ClassDB::bind_method(D_METHOD("as_text"), &InputEvent::as_text);
125
126 ClassDB::bind_method(D_METHOD("is_match", "event", "exact_match"), &InputEvent::is_match, DEFVAL(true));
127
128 ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type);
129
130 ClassDB::bind_method(D_METHOD("accumulate", "with_event"), &InputEvent::accumulate);
131
132 ClassDB::bind_method(D_METHOD("xformed_by", "xform", "local_ofs"), &InputEvent::xformed_by, DEFVAL(Vector2()));
133
134 ADD_PROPERTY(PropertyInfo(Variant::INT, "device"), "set_device", "get_device");
135}
136
137///////////////////////////////////
138
139void InputEventFromWindow::_bind_methods() {
140 ClassDB::bind_method(D_METHOD("set_window_id", "id"), &InputEventFromWindow::set_window_id);
141 ClassDB::bind_method(D_METHOD("get_window_id"), &InputEventFromWindow::get_window_id);
142 ADD_PROPERTY(PropertyInfo(Variant::INT, "window_id"), "set_window_id", "get_window_id");
143}
144
145void InputEventFromWindow::set_window_id(int64_t p_id) {
146 window_id = p_id;
147 emit_changed();
148}
149
150int64_t InputEventFromWindow::get_window_id() const {
151 return window_id;
152}
153
154///////////////////////////////////
155
156void InputEventWithModifiers::set_command_or_control_autoremap(bool p_enabled) {
157 command_or_control_autoremap = p_enabled;
158 if (command_or_control_autoremap) {
159 if (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) {
160 ctrl_pressed = false;
161 meta_pressed = true;
162 } else {
163 ctrl_pressed = true;
164 meta_pressed = false;
165 }
166 } else {
167 ctrl_pressed = false;
168 meta_pressed = false;
169 }
170 emit_changed();
171}
172
173bool InputEventWithModifiers::is_command_or_control_autoremap() const {
174 return command_or_control_autoremap;
175}
176
177bool InputEventWithModifiers::is_command_or_control_pressed() const {
178 if (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) {
179 return meta_pressed;
180 } else {
181 return ctrl_pressed;
182 }
183}
184
185void InputEventWithModifiers::set_shift_pressed(bool p_enabled) {
186 shift_pressed = p_enabled;
187 emit_changed();
188}
189
190bool InputEventWithModifiers::is_shift_pressed() const {
191 return shift_pressed;
192}
193
194void InputEventWithModifiers::set_alt_pressed(bool p_enabled) {
195 alt_pressed = p_enabled;
196 emit_changed();
197}
198
199bool InputEventWithModifiers::is_alt_pressed() const {
200 return alt_pressed;
201}
202
203void InputEventWithModifiers::set_ctrl_pressed(bool p_enabled) {
204 ERR_FAIL_COND_MSG(command_or_control_autoremap, "Command or Control autoremapping is enabled, cannot set Control directly!");
205 ctrl_pressed = p_enabled;
206 emit_changed();
207}
208
209bool InputEventWithModifiers::is_ctrl_pressed() const {
210 return ctrl_pressed;
211}
212
213void InputEventWithModifiers::set_meta_pressed(bool p_enabled) {
214 ERR_FAIL_COND_MSG(command_or_control_autoremap, "Command or Control autoremapping is enabled, cannot set Meta directly!");
215 meta_pressed = p_enabled;
216 emit_changed();
217}
218
219bool InputEventWithModifiers::is_meta_pressed() const {
220 return meta_pressed;
221}
222
223void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) {
224 set_alt_pressed(event->is_alt_pressed());
225 set_shift_pressed(event->is_shift_pressed());
226 set_ctrl_pressed(event->is_ctrl_pressed());
227 set_meta_pressed(event->is_meta_pressed());
228}
229
230BitField<KeyModifierMask> InputEventWithModifiers::get_modifiers_mask() const {
231 BitField<KeyModifierMask> mask;
232 if (is_ctrl_pressed()) {
233 mask.set_flag(KeyModifierMask::CTRL);
234 }
235 if (is_shift_pressed()) {
236 mask.set_flag(KeyModifierMask::SHIFT);
237 }
238 if (is_alt_pressed()) {
239 mask.set_flag(KeyModifierMask::ALT);
240 }
241 if (is_meta_pressed()) {
242 mask.set_flag(KeyModifierMask::META);
243 }
244 if (is_command_or_control_autoremap()) {
245 if (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) {
246 mask.set_flag(KeyModifierMask::META);
247 } else {
248 mask.set_flag(KeyModifierMask::CTRL);
249 }
250 }
251 return mask;
252}
253
254String InputEventWithModifiers::as_text() const {
255 Vector<String> mod_names;
256
257 if (is_ctrl_pressed()) {
258 mod_names.push_back(find_keycode_name(Key::CTRL));
259 }
260 if (is_shift_pressed()) {
261 mod_names.push_back(find_keycode_name(Key::SHIFT));
262 }
263 if (is_alt_pressed()) {
264 mod_names.push_back(find_keycode_name(Key::ALT));
265 }
266 if (is_meta_pressed()) {
267 mod_names.push_back(find_keycode_name(Key::META));
268 }
269
270 if (!mod_names.is_empty()) {
271 return String("+").join(mod_names);
272 } else {
273 return "";
274 }
275}
276
277String InputEventWithModifiers::to_string() {
278 return as_text();
279}
280
281void InputEventWithModifiers::_bind_methods() {
282 ClassDB::bind_method(D_METHOD("set_command_or_control_autoremap", "enable"), &InputEventWithModifiers::set_command_or_control_autoremap);
283 ClassDB::bind_method(D_METHOD("is_command_or_control_autoremap"), &InputEventWithModifiers::is_command_or_control_autoremap);
284
285 ClassDB::bind_method(D_METHOD("is_command_or_control_pressed"), &InputEventWithModifiers::is_command_or_control_pressed);
286
287 ClassDB::bind_method(D_METHOD("set_alt_pressed", "pressed"), &InputEventWithModifiers::set_alt_pressed);
288 ClassDB::bind_method(D_METHOD("is_alt_pressed"), &InputEventWithModifiers::is_alt_pressed);
289
290 ClassDB::bind_method(D_METHOD("set_shift_pressed", "pressed"), &InputEventWithModifiers::set_shift_pressed);
291 ClassDB::bind_method(D_METHOD("is_shift_pressed"), &InputEventWithModifiers::is_shift_pressed);
292
293 ClassDB::bind_method(D_METHOD("set_ctrl_pressed", "pressed"), &InputEventWithModifiers::set_ctrl_pressed);
294 ClassDB::bind_method(D_METHOD("is_ctrl_pressed"), &InputEventWithModifiers::is_ctrl_pressed);
295
296 ClassDB::bind_method(D_METHOD("set_meta_pressed", "pressed"), &InputEventWithModifiers::set_meta_pressed);
297 ClassDB::bind_method(D_METHOD("is_meta_pressed"), &InputEventWithModifiers::is_meta_pressed);
298
299 ClassDB::bind_method(D_METHOD("get_modifiers_mask"), &InputEventWithModifiers::get_modifiers_mask);
300
301 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command_or_control_autoremap"), "set_command_or_control_autoremap", "is_command_or_control_autoremap");
302 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt_pressed"), "set_alt_pressed", "is_alt_pressed");
303 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift_pressed"), "set_shift_pressed", "is_shift_pressed");
304 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ctrl_pressed"), "set_ctrl_pressed", "is_ctrl_pressed");
305 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_pressed"), "set_meta_pressed", "is_meta_pressed");
306}
307
308void InputEventWithModifiers::_validate_property(PropertyInfo &p_property) const {
309 if (command_or_control_autoremap) {
310 // Cannot be used with Meta/Command or Control!
311 if (p_property.name == "meta_pressed") {
312 p_property.usage ^= PROPERTY_USAGE_STORAGE;
313 }
314 if (p_property.name == "ctrl_pressed") {
315 p_property.usage ^= PROPERTY_USAGE_STORAGE;
316 }
317 } else {
318 if (p_property.name == "command_or_control_autoremap") {
319 p_property.usage ^= PROPERTY_USAGE_STORAGE;
320 }
321 }
322}
323
324///////////////////////////////////
325
326void InputEventKey::set_pressed(bool p_pressed) {
327 pressed = p_pressed;
328 emit_changed();
329}
330
331void InputEventKey::set_keycode(Key p_keycode) {
332 keycode = p_keycode;
333 emit_changed();
334}
335
336Key InputEventKey::get_keycode() const {
337 return keycode;
338}
339
340void InputEventKey::set_key_label(Key p_key_label) {
341 key_label = p_key_label;
342 emit_changed();
343}
344
345Key InputEventKey::get_key_label() const {
346 return key_label;
347}
348
349void InputEventKey::set_physical_keycode(Key p_keycode) {
350 physical_keycode = p_keycode;
351 emit_changed();
352}
353
354Key InputEventKey::get_physical_keycode() const {
355 return physical_keycode;
356}
357
358void InputEventKey::set_unicode(char32_t p_unicode) {
359 unicode = p_unicode;
360 emit_changed();
361}
362
363char32_t InputEventKey::get_unicode() const {
364 return unicode;
365}
366
367void InputEventKey::set_echo(bool p_enable) {
368 echo = p_enable;
369 emit_changed();
370}
371
372bool InputEventKey::is_echo() const {
373 return echo;
374}
375
376Key InputEventKey::get_keycode_with_modifiers() const {
377 return keycode | (int64_t)get_modifiers_mask();
378}
379
380Key InputEventKey::get_physical_keycode_with_modifiers() const {
381 return physical_keycode | (int64_t)get_modifiers_mask();
382}
383
384Key InputEventKey::get_key_label_with_modifiers() const {
385 return key_label | get_modifiers_mask();
386}
387
388String InputEventKey::as_text_physical_keycode() const {
389 String kc;
390
391 if (physical_keycode != Key::NONE) {
392 kc = keycode_get_string(physical_keycode);
393 } else {
394 kc = "(" + RTR("Unset") + ")";
395 }
396
397 if (kc.is_empty()) {
398 return kc;
399 }
400
401 String mods_text = InputEventWithModifiers::as_text();
402 return mods_text.is_empty() ? kc : mods_text + "+" + kc;
403}
404
405String InputEventKey::as_text_keycode() const {
406 String kc;
407
408 if (keycode != Key::NONE) {
409 kc = keycode_get_string(keycode);
410 } else {
411 kc = "(" + RTR("Unset") + ")";
412 }
413
414 if (kc.is_empty()) {
415 return kc;
416 }
417
418 String mods_text = InputEventWithModifiers::as_text();
419 return mods_text.is_empty() ? kc : mods_text + "+" + kc;
420}
421
422String InputEventKey::as_text_key_label() const {
423 String kc;
424
425 if (key_label != Key::NONE) {
426 kc = keycode_get_string(key_label);
427 } else {
428 kc = "(" + RTR("Unset") + ")";
429 }
430
431 if (kc.is_empty()) {
432 return kc;
433 }
434
435 String mods_text = InputEventWithModifiers::as_text();
436 return mods_text.is_empty() ? kc : mods_text + "+" + kc;
437}
438
439String InputEventKey::as_text() const {
440 String kc;
441
442 if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) {
443 kc = keycode_get_string(key_label) + " (Unicode)";
444 } else if (keycode != Key::NONE) {
445 kc = keycode_get_string(keycode);
446 } else if (physical_keycode != Key::NONE) {
447 kc = keycode_get_string(physical_keycode) + " (" + RTR("Physical") + ")";
448 } else {
449 kc = "(" + RTR("Unset") + ")";
450 }
451
452 if (kc.is_empty()) {
453 return kc;
454 }
455
456 String mods_text = InputEventWithModifiers::as_text();
457 return mods_text.is_empty() ? kc : mods_text + "+" + kc;
458}
459
460String InputEventKey::to_string() {
461 String p = is_pressed() ? "true" : "false";
462 String e = is_echo() ? "true" : "false";
463
464 String kc = "";
465 String physical = "false";
466
467 if (keycode == Key::NONE && physical_keycode == Key::NONE && unicode != 0) {
468 kc = "U+" + String::num_uint64(unicode, 16) + " (" + String::chr(unicode) + ")";
469 } else if (keycode != Key::NONE) {
470 kc = itos((int64_t)keycode) + " (" + keycode_get_string(keycode) + ")";
471 } else if (physical_keycode != Key::NONE) {
472 kc = itos((int64_t)physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")";
473 physical = "true";
474 } else {
475 kc = "(" + RTR("Unset") + ")";
476 }
477
478 String mods = InputEventWithModifiers::as_text();
479 mods = mods.is_empty() ? "none" : mods;
480
481 return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e);
482}
483
484Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode, bool p_physical) {
485 Ref<InputEventKey> ie;
486 ie.instantiate();
487 if (p_physical) {
488 ie->set_physical_keycode(p_keycode & KeyModifierMask::CODE_MASK);
489 } else {
490 ie->set_keycode(p_keycode & KeyModifierMask::CODE_MASK);
491 }
492
493 char32_t ch = char32_t(p_keycode & KeyModifierMask::CODE_MASK);
494 if (ch < 0xd800 || (ch > 0xdfff && ch <= 0x10ffff)) {
495 ie->set_unicode(ch);
496 }
497
498 if ((p_keycode & KeyModifierMask::SHIFT) != Key::NONE) {
499 ie->set_shift_pressed(true);
500 }
501 if ((p_keycode & KeyModifierMask::ALT) != Key::NONE) {
502 ie->set_alt_pressed(true);
503 }
504 if ((p_keycode & KeyModifierMask::CMD_OR_CTRL) != Key::NONE) {
505 ie->set_command_or_control_autoremap(true);
506 if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE || (p_keycode & KeyModifierMask::META) != Key::NONE) {
507 WARN_PRINT("Invalid Key Modifiers: Command or Control autoremapping is enabled, Meta and Control values are ignored!");
508 }
509 } else {
510 if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE) {
511 ie->set_ctrl_pressed(true);
512 }
513 if ((p_keycode & KeyModifierMask::META) != Key::NONE) {
514 ie->set_meta_pressed(true);
515 }
516 }
517
518 return ie;
519}
520
521bool InputEventKey::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 {
522 Ref<InputEventKey> key = p_event;
523 if (key.is_null()) {
524 return false;
525 }
526
527 bool match;
528 if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) {
529 match = key_label == key->key_label;
530 } else if (keycode != Key::NONE) {
531 match = keycode == key->keycode;
532 } else if (physical_keycode != Key::NONE) {
533 match = physical_keycode == key->physical_keycode;
534 } else {
535 match = false;
536 }
537
538 Key action_mask = (Key)(int64_t)get_modifiers_mask();
539 Key key_mask = (Key)(int64_t)key->get_modifiers_mask();
540 if (key->is_pressed()) {
541 match &= (action_mask & key_mask) == action_mask;
542 }
543 if (p_exact_match) {
544 match &= action_mask == key_mask;
545 }
546 if (match) {
547 bool key_pressed = key->is_pressed();
548 if (r_pressed != nullptr) {
549 *r_pressed = key_pressed;
550 }
551 float strength = key_pressed ? 1.0f : 0.0f;
552 if (r_strength != nullptr) {
553 *r_strength = strength;
554 }
555 if (r_raw_strength != nullptr) {
556 *r_raw_strength = strength;
557 }
558 }
559 return match;
560}
561
562bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
563 Ref<InputEventKey> key = p_event;
564 if (key.is_null()) {
565 return false;
566 }
567
568 if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) {
569 return (key_label == key->key_label) &&
570 (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
571 } else if (keycode != Key::NONE) {
572 return (keycode == key->keycode) &&
573 (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
574 } else if (physical_keycode != Key::NONE) {
575 return (physical_keycode == key->physical_keycode) &&
576 (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask());
577 } else {
578 return false;
579 }
580}
581
582void InputEventKey::_bind_methods() {
583 ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventKey::set_pressed);
584
585 ClassDB::bind_method(D_METHOD("set_keycode", "keycode"), &InputEventKey::set_keycode);
586 ClassDB::bind_method(D_METHOD("get_keycode"), &InputEventKey::get_keycode);
587
588 ClassDB::bind_method(D_METHOD("set_physical_keycode", "physical_keycode"), &InputEventKey::set_physical_keycode);
589 ClassDB::bind_method(D_METHOD("get_physical_keycode"), &InputEventKey::get_physical_keycode);
590
591 ClassDB::bind_method(D_METHOD("set_key_label", "key_label"), &InputEventKey::set_key_label);
592 ClassDB::bind_method(D_METHOD("get_key_label"), &InputEventKey::get_key_label);
593
594 ClassDB::bind_method(D_METHOD("set_unicode", "unicode"), &InputEventKey::set_unicode);
595 ClassDB::bind_method(D_METHOD("get_unicode"), &InputEventKey::get_unicode);
596
597 ClassDB::bind_method(D_METHOD("set_echo", "echo"), &InputEventKey::set_echo);
598
599 ClassDB::bind_method(D_METHOD("get_keycode_with_modifiers"), &InputEventKey::get_keycode_with_modifiers);
600 ClassDB::bind_method(D_METHOD("get_physical_keycode_with_modifiers"), &InputEventKey::get_physical_keycode_with_modifiers);
601 ClassDB::bind_method(D_METHOD("get_key_label_with_modifiers"), &InputEventKey::get_key_label_with_modifiers);
602
603 ClassDB::bind_method(D_METHOD("as_text_keycode"), &InputEventKey::as_text_keycode);
604 ClassDB::bind_method(D_METHOD("as_text_physical_keycode"), &InputEventKey::as_text_physical_keycode);
605 ClassDB::bind_method(D_METHOD("as_text_key_label"), &InputEventKey::as_text_key_label);
606
607 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
608 ADD_PROPERTY(PropertyInfo(Variant::INT, "keycode"), "set_keycode", "get_keycode");
609 ADD_PROPERTY(PropertyInfo(Variant::INT, "physical_keycode"), "set_physical_keycode", "get_physical_keycode");
610 ADD_PROPERTY(PropertyInfo(Variant::INT, "key_label"), "set_key_label", "get_key_label");
611 ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
612 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo");
613}
614
615///////////////////////////////////
616
617void InputEventMouse::set_button_mask(BitField<MouseButtonMask> p_mask) {
618 button_mask = p_mask;
619 emit_changed();
620}
621
622BitField<MouseButtonMask> InputEventMouse::get_button_mask() const {
623 return button_mask;
624}
625
626void InputEventMouse::set_position(const Vector2 &p_pos) {
627 pos = p_pos;
628}
629
630Vector2 InputEventMouse::get_position() const {
631 return pos;
632}
633
634void InputEventMouse::set_global_position(const Vector2 &p_global_pos) {
635 global_pos = p_global_pos;
636}
637
638Vector2 InputEventMouse::get_global_position() const {
639 return global_pos;
640}
641
642void InputEventMouse::_bind_methods() {
643 ClassDB::bind_method(D_METHOD("set_button_mask", "button_mask"), &InputEventMouse::set_button_mask);
644 ClassDB::bind_method(D_METHOD("get_button_mask"), &InputEventMouse::get_button_mask);
645
646 ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventMouse::set_position);
647 ClassDB::bind_method(D_METHOD("get_position"), &InputEventMouse::get_position);
648
649 ClassDB::bind_method(D_METHOD("set_global_position", "global_position"), &InputEventMouse::set_global_position);
650 ClassDB::bind_method(D_METHOD("get_global_position"), &InputEventMouse::get_global_position);
651
652 ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask"), "set_button_mask", "get_button_mask");
653 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
654 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px"), "set_global_position", "get_global_position");
655}
656
657///////////////////////////////////
658
659void InputEventMouseButton::set_factor(float p_factor) {
660 factor = p_factor;
661}
662
663float InputEventMouseButton::get_factor() const {
664 return factor;
665}
666
667void InputEventMouseButton::set_button_index(MouseButton p_index) {
668 button_index = p_index;
669 emit_changed();
670}
671
672MouseButton InputEventMouseButton::get_button_index() const {
673 return button_index;
674}
675
676void InputEventMouseButton::set_pressed(bool p_pressed) {
677 pressed = p_pressed;
678}
679
680void InputEventMouseButton::set_canceled(bool p_canceled) {
681 canceled = p_canceled;
682}
683
684void InputEventMouseButton::set_double_click(bool p_double_click) {
685 double_click = p_double_click;
686}
687
688bool InputEventMouseButton::is_double_click() const {
689 return double_click;
690}
691
692Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
693 Vector2 g = get_global_position();
694 Vector2 l = p_xform.xform(get_position() + p_local_ofs);
695
696 Ref<InputEventMouseButton> mb;
697 mb.instantiate();
698
699 mb->set_device(get_device());
700 mb->set_window_id(get_window_id());
701 mb->set_modifiers_from_event(this);
702
703 mb->set_position(l);
704 mb->set_global_position(g);
705
706 mb->set_button_mask(get_button_mask());
707 mb->set_pressed(pressed);
708 mb->set_canceled(canceled);
709 mb->set_double_click(double_click);
710 mb->set_factor(factor);
711 mb->set_button_index(button_index);
712
713 return mb;
714}
715
716bool InputEventMouseButton::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 {
717 Ref<InputEventMouseButton> mb = p_event;
718 if (mb.is_null()) {
719 return false;
720 }
721
722 bool match = button_index == mb->button_index;
723 Key action_modifiers_mask = (Key)(int64_t)get_modifiers_mask();
724 Key button_modifiers_mask = (Key)(int64_t)mb->get_modifiers_mask();
725 if (mb->is_pressed()) {
726 match &= (action_modifiers_mask & button_modifiers_mask) == action_modifiers_mask;
727 }
728 if (p_exact_match) {
729 match &= action_modifiers_mask == button_modifiers_mask;
730 }
731 if (match) {
732 bool mb_pressed = mb->is_pressed();
733 if (r_pressed != nullptr) {
734 *r_pressed = mb_pressed;
735 }
736 float strength = mb_pressed ? 1.0f : 0.0f;
737 if (r_strength != nullptr) {
738 *r_strength = strength;
739 }
740 if (r_raw_strength != nullptr) {
741 *r_raw_strength = strength;
742 }
743 }
744
745 return match;
746}
747
748bool InputEventMouseButton::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
749 Ref<InputEventMouseButton> mb = p_event;
750 if (mb.is_null()) {
751 return false;
752 }
753
754 return button_index == mb->button_index &&
755 (!p_exact_match || get_modifiers_mask() == mb->get_modifiers_mask());
756}
757
758static const char *_mouse_button_descriptions[9] = {
759 TTRC("Left Mouse Button"),
760 TTRC("Right Mouse Button"),
761 TTRC("Middle Mouse Button"),
762 TTRC("Mouse Wheel Up"),
763 TTRC("Mouse Wheel Down"),
764 TTRC("Mouse Wheel Left"),
765 TTRC("Mouse Wheel Right"),
766 TTRC("Mouse Thumb Button 1"),
767 TTRC("Mouse Thumb Button 2")
768};
769
770String InputEventMouseButton::as_text() const {
771 // Modifiers
772 String mods_text = InputEventWithModifiers::as_text();
773 String full_string = mods_text.is_empty() ? "" : mods_text + "+";
774
775 // Button
776 MouseButton idx = get_button_index();
777 switch (idx) {
778 case MouseButton::LEFT:
779 case MouseButton::RIGHT:
780 case MouseButton::MIDDLE:
781 case MouseButton::WHEEL_UP:
782 case MouseButton::WHEEL_DOWN:
783 case MouseButton::WHEEL_LEFT:
784 case MouseButton::WHEEL_RIGHT:
785 case MouseButton::MB_XBUTTON1:
786 case MouseButton::MB_XBUTTON2:
787 full_string += RTR(_mouse_button_descriptions[(size_t)idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1
788 break;
789 default:
790 full_string += RTR("Button") + " #" + itos((int64_t)idx);
791 break;
792 }
793
794 // Double Click
795 if (double_click) {
796 full_string += " (" + RTR("Double Click") + ")";
797 }
798
799 return full_string;
800}
801
802String InputEventMouseButton::to_string() {
803 String p = is_pressed() ? "true" : "false";
804 String canceled_state = is_canceled() ? "true" : "false";
805 String d = double_click ? "true" : "false";
806
807 MouseButton idx = get_button_index();
808 String button_string = itos((int64_t)idx);
809
810 switch (idx) {
811 case MouseButton::LEFT:
812 case MouseButton::RIGHT:
813 case MouseButton::MIDDLE:
814 case MouseButton::WHEEL_UP:
815 case MouseButton::WHEEL_DOWN:
816 case MouseButton::WHEEL_LEFT:
817 case MouseButton::WHEEL_RIGHT:
818 case MouseButton::MB_XBUTTON1:
819 case MouseButton::MB_XBUTTON2:
820 button_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)idx - 1])); // button index starts from 1, array index starts from 0, so subtract 1
821 break;
822 default:
823 break;
824 }
825
826 String mods = InputEventWithModifiers::as_text();
827 mods = mods.is_empty() ? "none" : mods;
828
829 // Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
830 String index_and_mods = vformat("button_index=%s, mods=%s", button_index, mods);
831 return vformat("InputEventMouseButton: %s, pressed=%s, canceled=%s, position=(%s), button_mask=%d, double_click=%s", index_and_mods, p, canceled_state, String(get_position()), get_button_mask(), d);
832}
833
834void InputEventMouseButton::_bind_methods() {
835 ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMouseButton::set_factor);
836 ClassDB::bind_method(D_METHOD("get_factor"), &InputEventMouseButton::get_factor);
837
838 ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventMouseButton::set_button_index);
839 ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventMouseButton::get_button_index);
840
841 ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventMouseButton::set_pressed);
842 ClassDB::bind_method(D_METHOD("set_canceled", "canceled"), &InputEventMouseButton::set_canceled);
843
844 ClassDB::bind_method(D_METHOD("set_double_click", "double_click"), &InputEventMouseButton::set_double_click);
845 ClassDB::bind_method(D_METHOD("is_double_click"), &InputEventMouseButton::is_double_click);
846
847 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "factor"), "set_factor", "get_factor");
848 ADD_PROPERTY(PropertyInfo(Variant::INT, "button_index"), "set_button_index", "get_button_index");
849 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "canceled"), "set_canceled", "is_canceled");
850 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
851 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "double_click"), "set_double_click", "is_double_click");
852}
853
854///////////////////////////////////
855
856void InputEventMouseMotion::set_tilt(const Vector2 &p_tilt) {
857 tilt = p_tilt;
858}
859
860Vector2 InputEventMouseMotion::get_tilt() const {
861 return tilt;
862}
863
864void InputEventMouseMotion::set_pressure(float p_pressure) {
865 pressure = p_pressure;
866}
867
868float InputEventMouseMotion::get_pressure() const {
869 return pressure;
870}
871
872void InputEventMouseMotion::set_pen_inverted(bool p_inverted) {
873 pen_inverted = p_inverted;
874}
875
876bool InputEventMouseMotion::get_pen_inverted() const {
877 return pen_inverted;
878}
879
880void InputEventMouseMotion::set_relative(const Vector2 &p_relative) {
881 relative = p_relative;
882}
883
884Vector2 InputEventMouseMotion::get_relative() const {
885 return relative;
886}
887
888void InputEventMouseMotion::set_velocity(const Vector2 &p_velocity) {
889 velocity = p_velocity;
890}
891
892Vector2 InputEventMouseMotion::get_velocity() const {
893 return velocity;
894}
895
896Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
897 Ref<InputEventMouseMotion> mm;
898 mm.instantiate();
899
900 mm->set_device(get_device());
901 mm->set_window_id(get_window_id());
902
903 mm->set_modifiers_from_event(this);
904
905 mm->set_position(p_xform.xform(get_position() + p_local_ofs));
906 mm->set_pressure(get_pressure());
907 mm->set_pen_inverted(get_pen_inverted());
908 mm->set_tilt(get_tilt());
909 mm->set_global_position(get_global_position());
910
911 mm->set_button_mask(get_button_mask());
912 mm->set_relative(p_xform.basis_xform(get_relative()));
913 mm->set_velocity(p_xform.basis_xform(get_velocity()));
914
915 return mm;
916}
917
918String InputEventMouseMotion::as_text() const {
919 return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
920}
921
922String InputEventMouseMotion::to_string() {
923 BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
924 String button_mask_string = itos((int64_t)mouse_button_mask);
925
926 if (mouse_button_mask.has_flag(MouseButtonMask::LEFT)) {
927 button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]));
928 }
929 if (mouse_button_mask.has_flag(MouseButtonMask::MIDDLE)) {
930 button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]));
931 }
932 if (mouse_button_mask.has_flag(MouseButtonMask::RIGHT)) {
933 button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]));
934 }
935 if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON1)) {
936 button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]));
937 }
938 if (mouse_button_mask.has_flag(MouseButtonMask::MB_XBUTTON2)) {
939 button_mask_string += vformat(" (%s)", TTRGET(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]));
940 }
941
942 // Work around the fact vformat can only take 5 substitutions but 7 need to be passed.
943 String mask_and_position_and_relative = vformat("button_mask=%s, position=(%s), relative=(%s)", button_mask_string, String(get_position()), String(get_relative()));
944 return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
945}
946
947bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
948 Ref<InputEventMouseMotion> motion = p_event;
949 if (motion.is_null()) {
950 return false;
951 }
952
953 if (get_window_id() != motion->get_window_id()) {
954 return false;
955 }
956
957 if (is_canceled() != motion->is_canceled()) {
958 return false;
959 }
960
961 if (is_pressed() != motion->is_pressed()) {
962 return false;
963 }
964
965 if (get_button_mask() != motion->get_button_mask()) {
966 return false;
967 }
968
969 if (is_shift_pressed() != motion->is_shift_pressed()) {
970 return false;
971 }
972
973 if (is_ctrl_pressed() != motion->is_ctrl_pressed()) {
974 return false;
975 }
976
977 if (is_alt_pressed() != motion->is_alt_pressed()) {
978 return false;
979 }
980
981 if (is_meta_pressed() != motion->is_meta_pressed()) {
982 return false;
983 }
984
985 set_position(motion->get_position());
986 set_global_position(motion->get_global_position());
987 set_velocity(motion->get_velocity());
988 relative += motion->get_relative();
989
990 return true;
991}
992
993void InputEventMouseMotion::_bind_methods() {
994 ClassDB::bind_method(D_METHOD("set_tilt", "tilt"), &InputEventMouseMotion::set_tilt);
995 ClassDB::bind_method(D_METHOD("get_tilt"), &InputEventMouseMotion::get_tilt);
996
997 ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMouseMotion::set_pressure);
998 ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMouseMotion::get_pressure);
999
1000 ClassDB::bind_method(D_METHOD("set_pen_inverted", "pen_inverted"), &InputEventMouseMotion::set_pen_inverted);
1001 ClassDB::bind_method(D_METHOD("get_pen_inverted"), &InputEventMouseMotion::get_pen_inverted);
1002
1003 ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
1004 ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
1005
1006 ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMouseMotion::set_velocity);
1007 ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMouseMotion::get_velocity);
1008
1009 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
1010 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
1011 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
1012 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
1013 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
1014}
1015
1016///////////////////////////////////
1017
1018void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
1019 ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
1020
1021 axis = p_axis;
1022 emit_changed();
1023}
1024
1025JoyAxis InputEventJoypadMotion::get_axis() const {
1026 return axis;
1027}
1028
1029void InputEventJoypadMotion::set_axis_value(float p_value) {
1030 axis_value = p_value;
1031 pressed = Math::abs(axis_value) >= 0.5f;
1032 emit_changed();
1033}
1034
1035float InputEventJoypadMotion::get_axis_value() const {
1036 return axis_value;
1037}
1038
1039bool InputEventJoypadMotion::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 {
1040 Ref<InputEventJoypadMotion> jm = p_event;
1041 if (jm.is_null()) {
1042 return false;
1043 }
1044
1045 // Matches even if not in the same direction, but returns a "not pressed" event.
1046 bool match = axis == jm->axis;
1047 if (p_exact_match) {
1048 match &= (axis_value < 0) == (jm->axis_value < 0);
1049 }
1050 if (match) {
1051 float jm_abs_axis_value = Math::abs(jm->get_axis_value());
1052 bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0);
1053 bool pressed_state = same_direction && jm_abs_axis_value >= p_deadzone;
1054 if (r_pressed != nullptr) {
1055 *r_pressed = pressed_state;
1056 }
1057 if (r_strength != nullptr) {
1058 if (pressed_state) {
1059 if (p_deadzone == 1.0f) {
1060 *r_strength = 1.0f;
1061 } else {
1062 *r_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
1063 }
1064 } else {
1065 *r_strength = 0.0f;
1066 }
1067 }
1068 if (r_raw_strength != nullptr) {
1069 if (same_direction) { // NOT pressed, because we want to ignore the deadzone.
1070 *r_raw_strength = jm_abs_axis_value;
1071 } else {
1072 *r_raw_strength = 0.0f;
1073 }
1074 }
1075 }
1076 return match;
1077}
1078
1079bool InputEventJoypadMotion::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
1080 Ref<InputEventJoypadMotion> jm = p_event;
1081 if (jm.is_null()) {
1082 return false;
1083 }
1084
1085 return axis == jm->axis &&
1086 (!p_exact_match || ((axis_value < 0) == (jm->axis_value < 0)));
1087}
1088
1089static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX] = {
1090 TTRC("Left Stick X-Axis, Joystick 0 X-Axis"),
1091 TTRC("Left Stick Y-Axis, Joystick 0 Y-Axis"),
1092 TTRC("Right Stick X-Axis, Joystick 1 X-Axis"),
1093 TTRC("Right Stick Y-Axis, Joystick 1 Y-Axis"),
1094 TTRC("Joystick 2 X-Axis, Left Trigger, Sony L2, Xbox LT"),
1095 TTRC("Joystick 2 Y-Axis, Right Trigger, Sony R2, Xbox RT"),
1096 TTRC("Joystick 3 X-Axis"),
1097 TTRC("Joystick 3 Y-Axis"),
1098 TTRC("Joystick 4 X-Axis"),
1099 TTRC("Joystick 4 Y-Axis"),
1100};
1101
1102String InputEventJoypadMotion::as_text() const {
1103 String desc = axis < JoyAxis::MAX ? TTRGET(_joy_axis_descriptions[(size_t)axis]) : RTR("Unknown Joypad Axis");
1104
1105 return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
1106}
1107
1108String InputEventJoypadMotion::to_string() {
1109 return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
1110}
1111
1112Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value) {
1113 Ref<InputEventJoypadMotion> ie;
1114 ie.instantiate();
1115 ie->set_axis(p_axis);
1116 ie->set_axis_value(p_value);
1117
1118 return ie;
1119}
1120
1121void InputEventJoypadMotion::_bind_methods() {
1122 ClassDB::bind_method(D_METHOD("set_axis", "axis"), &InputEventJoypadMotion::set_axis);
1123 ClassDB::bind_method(D_METHOD("get_axis"), &InputEventJoypadMotion::get_axis);
1124
1125 ClassDB::bind_method(D_METHOD("set_axis_value", "axis_value"), &InputEventJoypadMotion::set_axis_value);
1126 ClassDB::bind_method(D_METHOD("get_axis_value"), &InputEventJoypadMotion::get_axis_value);
1127
1128 ADD_PROPERTY(PropertyInfo(Variant::INT, "axis"), "set_axis", "get_axis");
1129 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "axis_value"), "set_axis_value", "get_axis_value");
1130}
1131
1132///////////////////////////////////
1133
1134void InputEventJoypadButton::set_button_index(JoyButton p_index) {
1135 button_index = p_index;
1136 emit_changed();
1137}
1138
1139JoyButton InputEventJoypadButton::get_button_index() const {
1140 return button_index;
1141}
1142
1143void InputEventJoypadButton::set_pressed(bool p_pressed) {
1144 pressed = p_pressed;
1145}
1146
1147void InputEventJoypadButton::set_pressure(float p_pressure) {
1148 pressure = p_pressure;
1149}
1150
1151float InputEventJoypadButton::get_pressure() const {
1152 return pressure;
1153}
1154
1155bool InputEventJoypadButton::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 {
1156 Ref<InputEventJoypadButton> jb = p_event;
1157 if (jb.is_null()) {
1158 return false;
1159 }
1160
1161 bool match = button_index == jb->button_index;
1162 if (match) {
1163 bool jb_pressed = jb->is_pressed();
1164 if (r_pressed != nullptr) {
1165 *r_pressed = jb_pressed;
1166 }
1167 float strength = jb_pressed ? 1.0f : 0.0f;
1168 if (r_strength != nullptr) {
1169 *r_strength = strength;
1170 }
1171 if (r_raw_strength != nullptr) {
1172 *r_raw_strength = strength;
1173 }
1174 }
1175
1176 return match;
1177}
1178
1179bool InputEventJoypadButton::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
1180 Ref<InputEventJoypadButton> button = p_event;
1181 if (button.is_null()) {
1182 return false;
1183 }
1184
1185 return button_index == button->button_index;
1186}
1187
1188static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = {
1189 TTRC("Bottom Action, Sony Cross, Xbox A, Nintendo B"),
1190 TTRC("Right Action, Sony Circle, Xbox B, Nintendo A"),
1191 TTRC("Left Action, Sony Square, Xbox X, Nintendo Y"),
1192 TTRC("Top Action, Sony Triangle, Xbox Y, Nintendo X"),
1193 TTRC("Back, Sony Select, Xbox Back, Nintendo -"),
1194 TTRC("Guide, Sony PS, Xbox Home"),
1195 TTRC("Start, Xbox Menu, Nintendo +"),
1196 TTRC("Left Stick, Sony L3, Xbox L/LS"),
1197 TTRC("Right Stick, Sony R3, Xbox R/RS"),
1198 TTRC("Left Shoulder, Sony L1, Xbox LB"),
1199 TTRC("Right Shoulder, Sony R1, Xbox RB"),
1200 TTRC("D-pad Up"),
1201 TTRC("D-pad Down"),
1202 TTRC("D-pad Left"),
1203 TTRC("D-pad Right"),
1204 TTRC("Xbox Share, PS5 Microphone, Nintendo Capture"),
1205 TTRC("Xbox Paddle 1"),
1206 TTRC("Xbox Paddle 2"),
1207 TTRC("Xbox Paddle 3"),
1208 TTRC("Xbox Paddle 4"),
1209 TTRC("PS4/5 Touchpad"),
1210};
1211
1212String InputEventJoypadButton::as_text() const {
1213 String text = vformat(RTR("Joypad Button %d"), (int64_t)button_index);
1214
1215 if (button_index > JoyButton::INVALID && button_index < JoyButton::SDL_MAX) {
1216 text += vformat(" (%s)", TTRGET(_joy_button_descriptions[(size_t)button_index]));
1217 }
1218
1219 if (pressure != 0) {
1220 text += ", " + RTR("Pressure:") + " " + String(Variant(pressure));
1221 }
1222
1223 return text;
1224}
1225
1226String InputEventJoypadButton::to_string() {
1227 String p = is_pressed() ? "true" : "false";
1228 return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
1229}
1230
1231Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index) {
1232 Ref<InputEventJoypadButton> ie;
1233 ie.instantiate();
1234 ie->set_button_index(p_btn_index);
1235
1236 return ie;
1237}
1238
1239void InputEventJoypadButton::_bind_methods() {
1240 ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventJoypadButton::set_button_index);
1241 ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventJoypadButton::get_button_index);
1242
1243 ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventJoypadButton::set_pressure);
1244 ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventJoypadButton::get_pressure);
1245
1246 ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventJoypadButton::set_pressed);
1247
1248 ADD_PROPERTY(PropertyInfo(Variant::INT, "button_index"), "set_button_index", "get_button_index");
1249 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
1250 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
1251}
1252
1253///////////////////////////////////
1254
1255void InputEventScreenTouch::set_index(int p_index) {
1256 index = p_index;
1257}
1258
1259int InputEventScreenTouch::get_index() const {
1260 return index;
1261}
1262
1263void InputEventScreenTouch::set_position(const Vector2 &p_pos) {
1264 pos = p_pos;
1265}
1266
1267Vector2 InputEventScreenTouch::get_position() const {
1268 return pos;
1269}
1270
1271void InputEventScreenTouch::set_pressed(bool p_pressed) {
1272 pressed = p_pressed;
1273}
1274
1275void InputEventScreenTouch::set_canceled(bool p_canceled) {
1276 canceled = p_canceled;
1277}
1278
1279void InputEventScreenTouch::set_double_tap(bool p_double_tap) {
1280 double_tap = p_double_tap;
1281}
1282bool InputEventScreenTouch::is_double_tap() const {
1283 return double_tap;
1284}
1285
1286Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
1287 Ref<InputEventScreenTouch> st;
1288 st.instantiate();
1289 st->set_device(get_device());
1290 st->set_window_id(get_window_id());
1291 st->set_index(index);
1292 st->set_position(p_xform.xform(pos + p_local_ofs));
1293 st->set_pressed(pressed);
1294 st->set_canceled(canceled);
1295 st->set_double_tap(double_tap);
1296
1297 return st;
1298}
1299
1300String InputEventScreenTouch::as_text() const {
1301 String status = canceled ? RTR("canceled") : (pressed ? RTR("touched") : RTR("released"));
1302
1303 return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
1304}
1305
1306String InputEventScreenTouch::to_string() {
1307 String p = pressed ? "true" : "false";
1308 String canceled_state = canceled ? "true" : "false";
1309 String double_tap_string = double_tap ? "true" : "false";
1310 return vformat("InputEventScreenTouch: index=%d, pressed=%s, canceled=%s, position=(%s), double_tap=%s", index, p, canceled_state, String(get_position()), double_tap_string);
1311}
1312
1313void InputEventScreenTouch::_bind_methods() {
1314 ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenTouch::set_index);
1315 ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenTouch::get_index);
1316
1317 ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventScreenTouch::set_position);
1318 ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenTouch::get_position);
1319
1320 ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventScreenTouch::set_pressed);
1321 ClassDB::bind_method(D_METHOD("set_canceled", "canceled"), &InputEventScreenTouch::set_canceled);
1322
1323 ClassDB::bind_method(D_METHOD("set_double_tap", "double_tap"), &InputEventScreenTouch::set_double_tap);
1324 ClassDB::bind_method(D_METHOD("is_double_tap"), &InputEventScreenTouch::is_double_tap);
1325
1326 ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
1327 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
1328 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "canceled"), "set_canceled", "is_canceled");
1329 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
1330 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "double_tap"), "set_double_tap", "is_double_tap");
1331}
1332
1333///////////////////////////////////
1334
1335void InputEventScreenDrag::set_index(int p_index) {
1336 index = p_index;
1337}
1338
1339int InputEventScreenDrag::get_index() const {
1340 return index;
1341}
1342
1343void InputEventScreenDrag::set_tilt(const Vector2 &p_tilt) {
1344 tilt = p_tilt;
1345}
1346
1347Vector2 InputEventScreenDrag::get_tilt() const {
1348 return tilt;
1349}
1350
1351void InputEventScreenDrag::set_pressure(float p_pressure) {
1352 pressure = p_pressure;
1353}
1354
1355float InputEventScreenDrag::get_pressure() const {
1356 return pressure;
1357}
1358
1359void InputEventScreenDrag::set_pen_inverted(bool p_inverted) {
1360 pen_inverted = p_inverted;
1361}
1362
1363bool InputEventScreenDrag::get_pen_inverted() const {
1364 return pen_inverted;
1365}
1366
1367void InputEventScreenDrag::set_position(const Vector2 &p_pos) {
1368 pos = p_pos;
1369}
1370
1371Vector2 InputEventScreenDrag::get_position() const {
1372 return pos;
1373}
1374
1375void InputEventScreenDrag::set_relative(const Vector2 &p_relative) {
1376 relative = p_relative;
1377}
1378
1379Vector2 InputEventScreenDrag::get_relative() const {
1380 return relative;
1381}
1382
1383void InputEventScreenDrag::set_velocity(const Vector2 &p_velocity) {
1384 velocity = p_velocity;
1385}
1386
1387Vector2 InputEventScreenDrag::get_velocity() const {
1388 return velocity;
1389}
1390
1391Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
1392 Ref<InputEventScreenDrag> sd;
1393
1394 sd.instantiate();
1395
1396 sd->set_device(get_device());
1397 sd->set_window_id(get_window_id());
1398
1399 sd->set_index(index);
1400 sd->set_pressure(get_pressure());
1401 sd->set_pen_inverted(get_pen_inverted());
1402 sd->set_tilt(get_tilt());
1403 sd->set_position(p_xform.xform(pos + p_local_ofs));
1404 sd->set_relative(p_xform.basis_xform(relative));
1405 sd->set_velocity(p_xform.basis_xform(velocity));
1406
1407 return sd;
1408}
1409
1410String InputEventScreenDrag::as_text() const {
1411 return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
1412}
1413
1414String InputEventScreenDrag::to_string() {
1415 return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
1416}
1417
1418bool InputEventScreenDrag::accumulate(const Ref<InputEvent> &p_event) {
1419 Ref<InputEventScreenDrag> drag = p_event;
1420 if (drag.is_null()) {
1421 return false;
1422 }
1423
1424 if (get_index() != drag->get_index()) {
1425 return false;
1426 }
1427
1428 set_position(drag->get_position());
1429 set_velocity(drag->get_velocity());
1430 relative += drag->get_relative();
1431
1432 return true;
1433}
1434
1435void InputEventScreenDrag::_bind_methods() {
1436 ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenDrag::set_index);
1437 ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenDrag::get_index);
1438
1439 ClassDB::bind_method(D_METHOD("set_tilt", "tilt"), &InputEventScreenDrag::set_tilt);
1440 ClassDB::bind_method(D_METHOD("get_tilt"), &InputEventScreenDrag::get_tilt);
1441
1442 ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventScreenDrag::set_pressure);
1443 ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventScreenDrag::get_pressure);
1444
1445 ClassDB::bind_method(D_METHOD("set_pen_inverted", "pen_inverted"), &InputEventScreenDrag::set_pen_inverted);
1446 ClassDB::bind_method(D_METHOD("get_pen_inverted"), &InputEventScreenDrag::get_pen_inverted);
1447
1448 ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventScreenDrag::set_position);
1449 ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenDrag::get_position);
1450
1451 ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventScreenDrag::set_relative);
1452 ClassDB::bind_method(D_METHOD("get_relative"), &InputEventScreenDrag::get_relative);
1453
1454 ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventScreenDrag::set_velocity);
1455 ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventScreenDrag::get_velocity);
1456
1457 ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
1458 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
1459 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
1460 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
1461 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
1462 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
1463 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
1464}
1465
1466///////////////////////////////////
1467
1468void InputEventAction::set_action(const StringName &p_action) {
1469 action = p_action;
1470}
1471
1472StringName InputEventAction::get_action() const {
1473 return action;
1474}
1475
1476void InputEventAction::set_pressed(bool p_pressed) {
1477 pressed = p_pressed;
1478}
1479
1480void InputEventAction::set_strength(float p_strength) {
1481 strength = CLAMP(p_strength, 0.0f, 1.0f);
1482}
1483
1484float InputEventAction::get_strength() const {
1485 return strength;
1486}
1487
1488bool InputEventAction::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const {
1489 if (p_event.is_null()) {
1490 return false;
1491 }
1492
1493 return p_event->is_action(action, p_exact_match);
1494}
1495
1496bool InputEventAction::is_action(const StringName &p_action) const {
1497 return action == p_action;
1498}
1499
1500bool InputEventAction::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 {
1501 Ref<InputEventAction> act = p_event;
1502 if (act.is_null()) {
1503 return false;
1504 }
1505
1506 bool match = action == act->action;
1507 if (match) {
1508 bool act_pressed = act->is_pressed();
1509 if (r_pressed != nullptr) {
1510 *r_pressed = act_pressed;
1511 }
1512 float act_strength = act_pressed ? 1.0f : 0.0f;
1513 if (r_strength != nullptr) {
1514 *r_strength = act_strength;
1515 }
1516 if (r_raw_strength != nullptr) {
1517 *r_raw_strength = act_strength;
1518 }
1519 }
1520 return match;
1521}
1522
1523String InputEventAction::as_text() const {
1524 const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(action);
1525 if (!events) {
1526 return String();
1527 }
1528
1529 for (const Ref<InputEvent> &E : *events) {
1530 if (E.is_valid()) {
1531 return E->as_text();
1532 }
1533 }
1534
1535 return String();
1536}
1537
1538String InputEventAction::to_string() {
1539 String p = is_pressed() ? "true" : "false";
1540 return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
1541}
1542
1543void InputEventAction::_bind_methods() {
1544 ClassDB::bind_method(D_METHOD("set_action", "action"), &InputEventAction::set_action);
1545 ClassDB::bind_method(D_METHOD("get_action"), &InputEventAction::get_action);
1546
1547 ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventAction::set_pressed);
1548
1549 ClassDB::bind_method(D_METHOD("set_strength", "strength"), &InputEventAction::set_strength);
1550 ClassDB::bind_method(D_METHOD("get_strength"), &InputEventAction::get_strength);
1551
1552 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "action"), "set_action", "get_action");
1553 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
1554 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength");
1555}
1556
1557///////////////////////////////////
1558
1559void InputEventGesture::set_position(const Vector2 &p_pos) {
1560 pos = p_pos;
1561}
1562
1563void InputEventGesture::_bind_methods() {
1564 ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventGesture::set_position);
1565 ClassDB::bind_method(D_METHOD("get_position"), &InputEventGesture::get_position);
1566
1567 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
1568}
1569
1570Vector2 InputEventGesture::get_position() const {
1571 return pos;
1572}
1573
1574///////////////////////////////////
1575
1576void InputEventMagnifyGesture::set_factor(real_t p_factor) {
1577 factor = p_factor;
1578}
1579
1580real_t InputEventMagnifyGesture::get_factor() const {
1581 return factor;
1582}
1583
1584Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
1585 Ref<InputEventMagnifyGesture> ev;
1586 ev.instantiate();
1587
1588 ev->set_device(get_device());
1589 ev->set_window_id(get_window_id());
1590
1591 ev->set_modifiers_from_event(this);
1592
1593 ev->set_position(p_xform.xform(get_position() + p_local_ofs));
1594 ev->set_factor(get_factor());
1595
1596 return ev;
1597}
1598
1599String InputEventMagnifyGesture::as_text() const {
1600 return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
1601}
1602
1603String InputEventMagnifyGesture::to_string() {
1604 return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
1605}
1606
1607void InputEventMagnifyGesture::_bind_methods() {
1608 ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMagnifyGesture::set_factor);
1609 ClassDB::bind_method(D_METHOD("get_factor"), &InputEventMagnifyGesture::get_factor);
1610
1611 ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "factor"), "set_factor", "get_factor");
1612}
1613
1614///////////////////////////////////
1615
1616void InputEventPanGesture::set_delta(const Vector2 &p_delta) {
1617 delta = p_delta;
1618}
1619
1620Vector2 InputEventPanGesture::get_delta() const {
1621 return delta;
1622}
1623
1624Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
1625 Ref<InputEventPanGesture> ev;
1626 ev.instantiate();
1627
1628 ev->set_device(get_device());
1629 ev->set_window_id(get_window_id());
1630
1631 ev->set_modifiers_from_event(this);
1632
1633 ev->set_position(p_xform.xform(get_position() + p_local_ofs));
1634 ev->set_delta(get_delta());
1635
1636 return ev;
1637}
1638
1639String InputEventPanGesture::as_text() const {
1640 return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
1641}
1642
1643String InputEventPanGesture::to_string() {
1644 return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
1645}
1646
1647void InputEventPanGesture::_bind_methods() {
1648 ClassDB::bind_method(D_METHOD("set_delta", "delta"), &InputEventPanGesture::set_delta);
1649 ClassDB::bind_method(D_METHOD("get_delta"), &InputEventPanGesture::get_delta);
1650
1651 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "delta"), "set_delta", "get_delta");
1652}
1653
1654///////////////////////////////////
1655
1656void InputEventMIDI::set_channel(const int p_channel) {
1657 channel = p_channel;
1658}
1659
1660int InputEventMIDI::get_channel() const {
1661 return channel;
1662}
1663
1664void InputEventMIDI::set_message(const MIDIMessage p_message) {
1665 message = p_message;
1666}
1667
1668MIDIMessage InputEventMIDI::get_message() const {
1669 return message;
1670}
1671
1672void InputEventMIDI::set_pitch(const int p_pitch) {
1673 pitch = p_pitch;
1674}
1675
1676int InputEventMIDI::get_pitch() const {
1677 return pitch;
1678}
1679
1680void InputEventMIDI::set_velocity(const int p_velocity) {
1681 velocity = p_velocity;
1682}
1683
1684int InputEventMIDI::get_velocity() const {
1685 return velocity;
1686}
1687
1688void InputEventMIDI::set_instrument(const int p_instrument) {
1689 instrument = p_instrument;
1690}
1691
1692int InputEventMIDI::get_instrument() const {
1693 return instrument;
1694}
1695
1696void InputEventMIDI::set_pressure(const int p_pressure) {
1697 pressure = p_pressure;
1698}
1699
1700int InputEventMIDI::get_pressure() const {
1701 return pressure;
1702}
1703
1704void InputEventMIDI::set_controller_number(const int p_controller_number) {
1705 controller_number = p_controller_number;
1706}
1707
1708int InputEventMIDI::get_controller_number() const {
1709 return controller_number;
1710}
1711
1712void InputEventMIDI::set_controller_value(const int p_controller_value) {
1713 controller_value = p_controller_value;
1714}
1715
1716int InputEventMIDI::get_controller_value() const {
1717 return controller_value;
1718}
1719
1720String InputEventMIDI::as_text() const {
1721 return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
1722}
1723
1724String InputEventMIDI::to_string() {
1725 String ret;
1726 switch (message) {
1727 case MIDIMessage::NOTE_ON:
1728 ret = vformat("Note On: channel=%d, pitch=%d, velocity=%d", channel, pitch, velocity);
1729 break;
1730 case MIDIMessage::NOTE_OFF:
1731 ret = vformat("Note Off: channel=%d, pitch=%d, velocity=%d", channel, pitch, velocity);
1732 break;
1733 case MIDIMessage::PITCH_BEND:
1734 ret = vformat("Pitch Bend: channel=%d, pitch=%d", channel, pitch);
1735 break;
1736 case MIDIMessage::CHANNEL_PRESSURE:
1737 ret = vformat("Channel Pressure: channel=%d, pressure=%d", channel, pressure);
1738 break;
1739 case MIDIMessage::CONTROL_CHANGE:
1740 ret = vformat("Control Change: channel=%d, controller_number=%d, controller_value=%d", channel, controller_number, controller_value);
1741 break;
1742 default:
1743 ret = vformat("channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d, controller_number=%d, controller_value=%d, instrument=%d", channel, message, pitch, velocity, pressure, controller_number, controller_value, instrument);
1744 }
1745 return "InputEventMIDI: " + ret;
1746}
1747
1748void InputEventMIDI::_bind_methods() {
1749 ClassDB::bind_method(D_METHOD("set_channel", "channel"), &InputEventMIDI::set_channel);
1750 ClassDB::bind_method(D_METHOD("get_channel"), &InputEventMIDI::get_channel);
1751 ClassDB::bind_method(D_METHOD("set_message", "message"), &InputEventMIDI::set_message);
1752 ClassDB::bind_method(D_METHOD("get_message"), &InputEventMIDI::get_message);
1753 ClassDB::bind_method(D_METHOD("set_pitch", "pitch"), &InputEventMIDI::set_pitch);
1754 ClassDB::bind_method(D_METHOD("get_pitch"), &InputEventMIDI::get_pitch);
1755 ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMIDI::set_velocity);
1756 ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMIDI::get_velocity);
1757 ClassDB::bind_method(D_METHOD("set_instrument", "instrument"), &InputEventMIDI::set_instrument);
1758 ClassDB::bind_method(D_METHOD("get_instrument"), &InputEventMIDI::get_instrument);
1759 ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMIDI::set_pressure);
1760 ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMIDI::get_pressure);
1761 ClassDB::bind_method(D_METHOD("set_controller_number", "controller_number"), &InputEventMIDI::set_controller_number);
1762 ClassDB::bind_method(D_METHOD("get_controller_number"), &InputEventMIDI::get_controller_number);
1763 ClassDB::bind_method(D_METHOD("set_controller_value", "controller_value"), &InputEventMIDI::set_controller_value);
1764 ClassDB::bind_method(D_METHOD("get_controller_value"), &InputEventMIDI::get_controller_value);
1765
1766 ADD_PROPERTY(PropertyInfo(Variant::INT, "channel"), "set_channel", "get_channel");
1767 ADD_PROPERTY(PropertyInfo(Variant::INT, "message"), "set_message", "get_message");
1768 ADD_PROPERTY(PropertyInfo(Variant::INT, "pitch"), "set_pitch", "get_pitch");
1769 ADD_PROPERTY(PropertyInfo(Variant::INT, "velocity"), "set_velocity", "get_velocity");
1770 ADD_PROPERTY(PropertyInfo(Variant::INT, "instrument"), "set_instrument", "get_instrument");
1771 ADD_PROPERTY(PropertyInfo(Variant::INT, "pressure"), "set_pressure", "get_pressure");
1772 ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_number"), "set_controller_number", "get_controller_number");
1773 ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_value"), "set_controller_value", "get_controller_value");
1774}
1775
1776///////////////////////////////////
1777
1778void InputEventShortcut::set_shortcut(Ref<Shortcut> p_shortcut) {
1779 shortcut = p_shortcut;
1780 emit_changed();
1781}
1782
1783Ref<Shortcut> InputEventShortcut::get_shortcut() {
1784 return shortcut;
1785}
1786
1787void InputEventShortcut::_bind_methods() {
1788 ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &InputEventShortcut::set_shortcut);
1789 ClassDB::bind_method(D_METHOD("get_shortcut"), &InputEventShortcut::get_shortcut);
1790
1791 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
1792}
1793
1794String InputEventShortcut::as_text() const {
1795 ERR_FAIL_COND_V(shortcut.is_null(), "None");
1796
1797 return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
1798}
1799
1800String InputEventShortcut::to_string() {
1801 ERR_FAIL_COND_V(shortcut.is_null(), "None");
1802
1803 return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
1804}
1805