Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/gui/base_button.cpp
9903 views
1
/**************************************************************************/
2
/* base_button.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 "base_button.h"
32
33
#include "core/config/project_settings.h"
34
#include "scene/gui/label.h"
35
#include "scene/main/window.h"
36
37
void BaseButton::_unpress_group() {
38
if (button_group.is_null()) {
39
return;
40
}
41
42
if (toggle_mode && !button_group->is_allow_unpress()) {
43
status.pressed = true;
44
queue_accessibility_update();
45
}
46
47
for (BaseButton *E : button_group->buttons) {
48
if (E == this) {
49
continue;
50
}
51
52
E->set_pressed(false);
53
}
54
}
55
56
void BaseButton::gui_input(const Ref<InputEvent> &p_event) {
57
ERR_FAIL_COND(p_event.is_null());
58
59
if (status.disabled) { // no interaction with disabled button
60
return;
61
}
62
63
Ref<InputEventMouseButton> mouse_button = p_event;
64
bool ui_accept = p_event->is_action("ui_accept", true) && !p_event->is_echo();
65
66
bool button_masked = mouse_button.is_valid() && button_mask.has_flag(mouse_button_to_mask(mouse_button->get_button_index()));
67
if (button_masked || ui_accept) {
68
was_mouse_pressed = button_masked;
69
on_action_event(p_event);
70
was_mouse_pressed = false;
71
72
return;
73
}
74
75
Ref<InputEventMouseMotion> mouse_motion = p_event;
76
if (mouse_motion.is_valid()) {
77
if (status.press_attempt) {
78
bool last_press_inside = status.pressing_inside;
79
status.pressing_inside = has_point(mouse_motion->get_position());
80
if (last_press_inside != status.pressing_inside) {
81
queue_redraw();
82
}
83
}
84
}
85
}
86
87
void BaseButton::_accessibility_action_click(const Variant &p_data) {
88
if (toggle_mode) {
89
status.pressed = !status.pressed;
90
91
if (status.pressed) {
92
_unpress_group();
93
if (button_group.is_valid()) {
94
button_group->emit_signal(SceneStringName(pressed), this);
95
}
96
}
97
98
_toggled(status.pressed);
99
_pressed();
100
} else {
101
_pressed();
102
}
103
queue_accessibility_update();
104
queue_redraw();
105
}
106
107
void BaseButton::_notification(int p_what) {
108
switch (p_what) {
109
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
110
RID ae = get_accessibility_element();
111
ERR_FAIL_COND(ae.is_null());
112
113
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
114
115
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_CLICK, callable_mp(this, &BaseButton::_accessibility_action_click));
116
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_DISABLED, status.disabled);
117
if (toggle_mode) {
118
DisplayServer::get_singleton()->accessibility_update_set_checked(ae, status.pressed);
119
}
120
if (button_group.is_valid()) {
121
for (const BaseButton *btn : button_group->buttons) {
122
if (btn->is_part_of_edited_scene()) {
123
continue;
124
}
125
DisplayServer::get_singleton()->accessibility_update_add_related_radio_group(ae, btn->get_accessibility_element());
126
}
127
}
128
if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->has_valid_event()) {
129
String text = atr(shortcut->get_name()) + " (" + shortcut->get_as_text() + ")";
130
String tooltip = get_tooltip_text();
131
if (!tooltip.is_empty() && shortcut->get_name().nocasecmp_to(tooltip) != 0) {
132
text += "\n" + atr(tooltip);
133
}
134
DisplayServer::get_singleton()->accessibility_update_set_tooltip(ae, text);
135
}
136
} break;
137
138
case NOTIFICATION_MOUSE_ENTER: {
139
status.hovering = true;
140
queue_accessibility_update();
141
queue_redraw();
142
} break;
143
144
case NOTIFICATION_MOUSE_EXIT: {
145
status.hovering = false;
146
queue_accessibility_update();
147
queue_redraw();
148
} break;
149
150
case NOTIFICATION_DRAG_BEGIN:
151
case NOTIFICATION_SCROLL_BEGIN: {
152
if (status.press_attempt) {
153
status.press_attempt = false;
154
queue_redraw();
155
}
156
} break;
157
158
case NOTIFICATION_FOCUS_ENTER: {
159
queue_redraw();
160
} break;
161
162
case NOTIFICATION_FOCUS_EXIT: {
163
if (status.press_attempt) {
164
status.press_attempt = false;
165
queue_redraw();
166
} else if (status.hovering) {
167
queue_redraw();
168
}
169
170
if (status.pressed_down_with_focus) {
171
status.pressed_down_with_focus = false;
172
emit_signal(SNAME("button_up"));
173
}
174
} break;
175
176
case NOTIFICATION_VISIBILITY_CHANGED:
177
case NOTIFICATION_EXIT_TREE: {
178
if (p_what == NOTIFICATION_VISIBILITY_CHANGED && is_visible_in_tree()) {
179
break;
180
}
181
if (!toggle_mode) {
182
status.pressed = false;
183
}
184
status.hovering = false;
185
status.press_attempt = false;
186
status.pressing_inside = false;
187
} break;
188
}
189
}
190
191
void BaseButton::_pressed() {
192
GDVIRTUAL_CALL(_pressed);
193
pressed();
194
emit_signal(SceneStringName(pressed));
195
}
196
197
void BaseButton::_toggled(bool p_pressed) {
198
GDVIRTUAL_CALL(_toggled, p_pressed);
199
toggled(p_pressed);
200
emit_signal(SceneStringName(toggled), p_pressed);
201
}
202
203
void BaseButton::on_action_event(Ref<InputEvent> p_event) {
204
Ref<InputEventMouseButton> mouse_button = p_event;
205
206
if (p_event->is_pressed() && (mouse_button.is_null() || status.hovering)) {
207
status.press_attempt = true;
208
status.pressing_inside = true;
209
if (!status.pressed_down_with_focus) {
210
status.pressed_down_with_focus = true;
211
emit_signal(SNAME("button_down"));
212
}
213
}
214
215
if (status.press_attempt && status.pressing_inside) {
216
if (toggle_mode) {
217
bool is_pressed = p_event->is_pressed();
218
if ((is_pressed && action_mode == ACTION_MODE_BUTTON_PRESS) || (!is_pressed && action_mode == ACTION_MODE_BUTTON_RELEASE)) {
219
if (action_mode == ACTION_MODE_BUTTON_PRESS) {
220
status.press_attempt = false;
221
status.pressing_inside = false;
222
}
223
status.pressed = !status.pressed;
224
_unpress_group();
225
if (button_group.is_valid()) {
226
button_group->emit_signal(SceneStringName(pressed), this);
227
}
228
_toggled(status.pressed);
229
_pressed();
230
queue_accessibility_update();
231
}
232
} else {
233
if ((p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_PRESS) || (!p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_RELEASE)) {
234
_pressed();
235
}
236
}
237
}
238
239
if (!p_event->is_pressed()) {
240
status.press_attempt = false;
241
status.pressing_inside = false;
242
if (status.pressed_down_with_focus) {
243
status.pressed_down_with_focus = false;
244
emit_signal(SNAME("button_up"));
245
}
246
}
247
248
queue_redraw();
249
}
250
251
void BaseButton::pressed() {
252
}
253
254
void BaseButton::toggled(bool p_pressed) {
255
}
256
257
void BaseButton::set_disabled(bool p_disabled) {
258
if (status.disabled == p_disabled) {
259
return;
260
}
261
262
status.disabled = p_disabled;
263
if (p_disabled) {
264
if (!toggle_mode) {
265
status.pressed = false;
266
}
267
status.press_attempt = false;
268
status.pressing_inside = false;
269
if (status.pressed_down_with_focus) {
270
status.pressed_down_with_focus = false;
271
emit_signal(SNAME("button_up"));
272
}
273
}
274
queue_accessibility_update();
275
queue_redraw();
276
update_minimum_size();
277
}
278
279
bool BaseButton::is_disabled() const {
280
return status.disabled;
281
}
282
283
void BaseButton::set_pressed(bool p_pressed) {
284
bool prev_pressed = status.pressed;
285
set_pressed_no_signal(p_pressed);
286
287
if (status.pressed == prev_pressed) {
288
return;
289
}
290
291
if (p_pressed) {
292
_unpress_group();
293
if (button_group.is_valid()) {
294
button_group->emit_signal(SceneStringName(pressed), this);
295
}
296
}
297
_toggled(status.pressed);
298
}
299
300
void BaseButton::set_pressed_no_signal(bool p_pressed) {
301
if (!toggle_mode) {
302
return;
303
}
304
if (status.pressed == p_pressed) {
305
return;
306
}
307
status.pressed = p_pressed;
308
queue_accessibility_update();
309
queue_redraw();
310
}
311
312
bool BaseButton::is_pressing() const {
313
return status.press_attempt;
314
}
315
316
bool BaseButton::is_pressed() const {
317
return toggle_mode ? status.pressed : status.press_attempt;
318
}
319
320
bool BaseButton::is_hovered() const {
321
return status.hovering;
322
}
323
324
BaseButton::DrawMode BaseButton::get_draw_mode() const {
325
if (status.disabled) {
326
return DRAW_DISABLED;
327
}
328
329
if (in_shortcut_feedback) {
330
return DRAW_HOVER_PRESSED;
331
}
332
333
if (!status.press_attempt && status.hovering) {
334
if (status.pressed) {
335
return DRAW_HOVER_PRESSED;
336
}
337
338
return DRAW_HOVER;
339
} else {
340
// Determine if pressed or not.
341
bool pressing;
342
if (status.press_attempt) {
343
pressing = (status.pressing_inside || keep_pressed_outside);
344
if (status.pressed) {
345
pressing = !pressing;
346
}
347
} else {
348
pressing = status.pressed;
349
}
350
351
if (pressing) {
352
return DRAW_PRESSED;
353
} else {
354
return DRAW_NORMAL;
355
}
356
}
357
}
358
359
void BaseButton::set_toggle_mode(bool p_on) {
360
// Make sure to set 'pressed' to false if we are not in toggle mode
361
if (!p_on) {
362
set_pressed(false);
363
}
364
queue_accessibility_update();
365
366
toggle_mode = p_on;
367
update_configuration_warnings();
368
}
369
370
bool BaseButton::is_toggle_mode() const {
371
return toggle_mode;
372
}
373
374
void BaseButton::set_shortcut_in_tooltip(bool p_on) {
375
if (shortcut_in_tooltip != p_on) {
376
shortcut_in_tooltip = p_on;
377
queue_accessibility_update();
378
}
379
}
380
381
bool BaseButton::is_shortcut_in_tooltip_enabled() const {
382
return shortcut_in_tooltip;
383
}
384
385
void BaseButton::set_action_mode(ActionMode p_mode) {
386
action_mode = p_mode;
387
}
388
389
BaseButton::ActionMode BaseButton::get_action_mode() const {
390
return action_mode;
391
}
392
393
void BaseButton::set_button_mask(BitField<MouseButtonMask> p_mask) {
394
button_mask = p_mask;
395
}
396
397
BitField<MouseButtonMask> BaseButton::get_button_mask() const {
398
return button_mask;
399
}
400
401
void BaseButton::set_keep_pressed_outside(bool p_on) {
402
keep_pressed_outside = p_on;
403
}
404
405
bool BaseButton::is_keep_pressed_outside() const {
406
return keep_pressed_outside;
407
}
408
409
void BaseButton::set_shortcut_feedback(bool p_enable) {
410
shortcut_feedback = p_enable;
411
}
412
413
bool BaseButton::is_shortcut_feedback() const {
414
return shortcut_feedback;
415
}
416
417
void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) {
418
if (shortcut != p_shortcut) {
419
shortcut = p_shortcut;
420
set_process_shortcut_input(shortcut.is_valid());
421
queue_accessibility_update();
422
}
423
}
424
425
Ref<Shortcut> BaseButton::get_shortcut() const {
426
return shortcut;
427
}
428
429
void BaseButton::_shortcut_feedback_timeout() {
430
in_shortcut_feedback = false;
431
queue_redraw();
432
}
433
434
void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
435
ERR_FAIL_COND(p_event.is_null());
436
437
if (!is_disabled() && p_event->is_pressed() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) {
438
if (toggle_mode) {
439
status.pressed = !status.pressed;
440
441
_unpress_group();
442
if (button_group.is_valid()) {
443
button_group->emit_signal(SceneStringName(pressed), this);
444
}
445
446
_toggled(status.pressed);
447
_pressed();
448
queue_accessibility_update();
449
} else {
450
_pressed();
451
}
452
queue_redraw();
453
accept_event();
454
455
if (shortcut_feedback && is_inside_tree()) {
456
if (shortcut_feedback_timer == nullptr) {
457
shortcut_feedback_timer = memnew(Timer);
458
shortcut_feedback_timer->set_one_shot(true);
459
add_child(shortcut_feedback_timer, false, INTERNAL_MODE_BACK);
460
shortcut_feedback_timer->set_wait_time(GLOBAL_GET_CACHED(double, "gui/timers/button_shortcut_feedback_highlight_time"));
461
shortcut_feedback_timer->connect("timeout", callable_mp(this, &BaseButton::_shortcut_feedback_timeout));
462
}
463
464
in_shortcut_feedback = true;
465
shortcut_feedback_timer->start();
466
}
467
}
468
}
469
470
Control *BaseButton::make_custom_tooltip(const String &p_text) const {
471
Control *control = Control::make_custom_tooltip(p_text);
472
if (control) {
473
return control;
474
}
475
if (!shortcut_in_tooltip || shortcut.is_null() || !shortcut->has_valid_event()) {
476
return nullptr; // Use the default tooltip label.
477
}
478
479
String text = atr(shortcut->get_name()) + " (" + shortcut->get_as_text() + ")";
480
if (!p_text.is_empty() && shortcut->get_name().nocasecmp_to(p_text) != 0) {
481
text += "\n" + atr(p_text);
482
}
483
484
// Make a label similar to the default tooltip label.
485
// Auto translation is disabled because we already did that manually above.
486
//
487
// We can't customize the tooltip text by overriding `get_tooltip()`
488
// because otherwise user-defined `_make_custom_tooltip()` would receive
489
// the translated and annotated text.
490
Label *label = memnew(Label(text));
491
label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
492
label->set_theme_type_variation(SNAME("TooltipLabel"));
493
494
return label;
495
}
496
497
void BaseButton::set_button_group(const Ref<ButtonGroup> &p_group) {
498
if (button_group.is_valid()) {
499
button_group->buttons.erase(this);
500
}
501
502
button_group = p_group;
503
504
if (button_group.is_valid()) {
505
button_group->buttons.insert(this);
506
}
507
508
queue_accessibility_update();
509
queue_redraw(); //checkbox changes to radio if set a buttongroup
510
update_configuration_warnings();
511
}
512
513
Ref<ButtonGroup> BaseButton::get_button_group() const {
514
return button_group;
515
}
516
517
bool BaseButton::_was_pressed_by_mouse() const {
518
return was_mouse_pressed;
519
}
520
521
PackedStringArray BaseButton::get_configuration_warnings() const {
522
PackedStringArray warnings = Control::get_configuration_warnings();
523
524
if (get_button_group().is_valid() && !is_toggle_mode()) {
525
warnings.push_back(RTR("ButtonGroup is intended to be used only with buttons that have toggle_mode set to true."));
526
}
527
528
return warnings;
529
}
530
531
void BaseButton::_bind_methods() {
532
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
533
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
534
ClassDB::bind_method(D_METHOD("set_pressed_no_signal", "pressed"), &BaseButton::set_pressed_no_signal);
535
ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered);
536
ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode);
537
ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode);
538
ClassDB::bind_method(D_METHOD("set_shortcut_in_tooltip", "enabled"), &BaseButton::set_shortcut_in_tooltip);
539
ClassDB::bind_method(D_METHOD("is_shortcut_in_tooltip_enabled"), &BaseButton::is_shortcut_in_tooltip_enabled);
540
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &BaseButton::set_disabled);
541
ClassDB::bind_method(D_METHOD("is_disabled"), &BaseButton::is_disabled);
542
ClassDB::bind_method(D_METHOD("set_action_mode", "mode"), &BaseButton::set_action_mode);
543
ClassDB::bind_method(D_METHOD("get_action_mode"), &BaseButton::get_action_mode);
544
ClassDB::bind_method(D_METHOD("set_button_mask", "mask"), &BaseButton::set_button_mask);
545
ClassDB::bind_method(D_METHOD("get_button_mask"), &BaseButton::get_button_mask);
546
ClassDB::bind_method(D_METHOD("get_draw_mode"), &BaseButton::get_draw_mode);
547
ClassDB::bind_method(D_METHOD("set_keep_pressed_outside", "enabled"), &BaseButton::set_keep_pressed_outside);
548
ClassDB::bind_method(D_METHOD("is_keep_pressed_outside"), &BaseButton::is_keep_pressed_outside);
549
ClassDB::bind_method(D_METHOD("set_shortcut_feedback", "enabled"), &BaseButton::set_shortcut_feedback);
550
ClassDB::bind_method(D_METHOD("is_shortcut_feedback"), &BaseButton::is_shortcut_feedback);
551
552
ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &BaseButton::set_shortcut);
553
ClassDB::bind_method(D_METHOD("get_shortcut"), &BaseButton::get_shortcut);
554
555
ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group);
556
ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);
557
558
GDVIRTUAL_BIND(_pressed);
559
GDVIRTUAL_BIND(_toggled, "toggled_on");
560
561
ADD_SIGNAL(MethodInfo("pressed"));
562
ADD_SIGNAL(MethodInfo("button_up"));
563
ADD_SIGNAL(MethodInfo("button_down"));
564
ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "toggled_on")));
565
566
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
567
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
568
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "button_pressed"), "set_pressed", "is_pressed");
569
ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode");
570
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask");
571
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside");
572
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "button_group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group");
573
574
ADD_GROUP("Shortcut", "");
575
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
576
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_feedback"), "set_shortcut_feedback", "is_shortcut_feedback");
577
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled");
578
579
BIND_ENUM_CONSTANT(DRAW_NORMAL);
580
BIND_ENUM_CONSTANT(DRAW_PRESSED);
581
BIND_ENUM_CONSTANT(DRAW_HOVER);
582
BIND_ENUM_CONSTANT(DRAW_DISABLED);
583
BIND_ENUM_CONSTANT(DRAW_HOVER_PRESSED);
584
585
BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_PRESS);
586
BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_RELEASE);
587
588
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/button_shortcut_feedback_highlight_time", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), 0.2);
589
}
590
591
BaseButton::BaseButton() {
592
set_focus_mode(FOCUS_ALL);
593
}
594
595
BaseButton::~BaseButton() {
596
if (button_group.is_valid()) {
597
button_group->buttons.erase(this);
598
}
599
}
600
601
void ButtonGroup::get_buttons(List<BaseButton *> *r_buttons) {
602
for (BaseButton *E : buttons) {
603
r_buttons->push_back(E);
604
}
605
}
606
607
TypedArray<BaseButton> ButtonGroup::_get_buttons() {
608
TypedArray<BaseButton> btns;
609
for (const BaseButton *E : buttons) {
610
btns.push_back(E);
611
}
612
613
return btns;
614
}
615
616
BaseButton *ButtonGroup::get_pressed_button() {
617
for (BaseButton *E : buttons) {
618
if (E->is_pressed()) {
619
return E;
620
}
621
}
622
623
return nullptr;
624
}
625
626
void ButtonGroup::set_allow_unpress(bool p_enabled) {
627
allow_unpress = p_enabled;
628
}
629
bool ButtonGroup::is_allow_unpress() {
630
return allow_unpress;
631
}
632
633
void ButtonGroup::_bind_methods() {
634
ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button);
635
ClassDB::bind_method(D_METHOD("get_buttons"), &ButtonGroup::_get_buttons);
636
ClassDB::bind_method(D_METHOD("set_allow_unpress", "enabled"), &ButtonGroup::set_allow_unpress);
637
ClassDB::bind_method(D_METHOD("is_allow_unpress"), &ButtonGroup::is_allow_unpress);
638
639
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_unpress"), "set_allow_unpress", "is_allow_unpress");
640
641
ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::OBJECT, "button", PROPERTY_HINT_RESOURCE_TYPE, "BaseButton")));
642
}
643
644
ButtonGroup::ButtonGroup() {
645
set_local_to_scene(true);
646
}
647
648