Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button shortcuts no longer "press" the Button. #71328

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/classes/BaseButton.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
[Shortcut] associated to the button.
</member>
<member name="shortcut_feedback" type="bool" setter="set_shortcut_feedback" getter="is_shortcut_feedback" default="true">
If [code]true[/code], the button will appear pressed when its shortcut is activated. If [code]false[/code] and [member toggle_mode] is [code]false[/code], the shortcut will activate the button without appearing to press the button.
If [code]true[/code], the button will highlight for a short amount of time when its shortcut is activated. If [code]false[/code] and [member toggle_mode] is [code]false[/code], the shortcut will activate without any visual feedback.
</member>
<member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled" default="true">
If [code]true[/code], the button will add information about its shortcut in the tooltip.
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,9 @@
<member name="gui/theme/lcd_subpixel_layout" type="int" setter="" getter="" default="1">
LCD subpixel layout used for font anti-aliasing. See [enum TextServer.FontLCDSubpixelLayout].
</member>
<member name="gui/timers/button_shortcut_feedback_highlight_time" type="float" setter="" getter="" default="0.2">
When [member BaseButton.shortcut_feedback] is enabled, this is the time the [BaseButton] will remain highlighted after a shortcut.
</member>
<member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000">
Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds).
</member>
Expand Down
75 changes: 53 additions & 22 deletions scene/gui/base_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "base_button.h"

#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
Expand Down Expand Up @@ -127,7 +128,6 @@ void BaseButton::_notification(int p_what) {
status.hovering = false;
status.press_attempt = false;
status.pressing_inside = false;
status.shortcut_press = false;
} break;
}
}
Expand All @@ -154,14 +154,10 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
if (status.press_attempt && status.pressing_inside) {
if (toggle_mode) {
bool is_pressed = p_event->is_pressed();
if (Object::cast_to<InputEventShortcut>(*p_event)) {
is_pressed = false;
}
if ((is_pressed && action_mode == ACTION_MODE_BUTTON_PRESS) || (!is_pressed && action_mode == ACTION_MODE_BUTTON_RELEASE)) {
if (action_mode == ACTION_MODE_BUTTON_PRESS) {
status.press_attempt = false;
status.pressing_inside = false;
status.shortcut_press = false;
}
status.pressed = !status.pressed;
_unpress_group();
Expand All @@ -187,7 +183,6 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
}
status.press_attempt = false;
status.pressing_inside = false;
status.shortcut_press = false;
emit_signal(SNAME("button_up"));
}

Expand All @@ -212,7 +207,6 @@ void BaseButton::set_disabled(bool p_disabled) {
}
status.press_attempt = false;
status.pressing_inside = false;
status.shortcut_press = false;
}
queue_redraw();
}
Expand Down Expand Up @@ -267,6 +261,10 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const {
return DRAW_DISABLED;
}

if (in_shortcut_feedback) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be replaced by

Suggested change
if (in_shortcut_feedback) {
if (shortcut_feedback_timer && !shortcut_feedback_timer->is_stopped()) {

to avoid extra bool flag, but it's not important I guess.

return DRAW_HOVER_PRESSED;
}

if (!status.press_attempt && status.hovering) {
if (status.pressed) {
return DRAW_HOVER_PRESSED;
Expand All @@ -285,7 +283,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const {
pressing = status.pressed;
}

if ((shortcut_feedback || !status.shortcut_press) && pressing) {
if (pressing) {
return DRAW_PRESSED;
} else {
return DRAW_NORMAL;
Expand Down Expand Up @@ -339,6 +337,14 @@ bool BaseButton::is_keep_pressed_outside() const {
return keep_pressed_outside;
}

void BaseButton::set_shortcut_feedback(bool p_enable) {
shortcut_feedback = p_enable;
}

bool BaseButton::is_shortcut_feedback() const {
return shortcut_feedback;
}

void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) {
shortcut = p_shortcut;
set_process_shortcut_input(shortcut.is_valid());
Expand All @@ -348,13 +354,45 @@ Ref<Shortcut> BaseButton::get_shortcut() const {
return shortcut;
}

void BaseButton::_shortcut_feedback_timeout() {
in_shortcut_feedback = false;
queue_redraw();
}

void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());

if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) {
status.shortcut_press = true;
on_action_event(p_event);
if (!is_disabled() && p_event->is_pressed() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) {
if (toggle_mode) {
status.pressed = !status.pressed;

if (status.pressed) {
_unpress_group();
if (button_group.is_valid()) {
button_group->emit_signal(SNAME("pressed"), this);
}
}

_toggled(status.pressed);
_pressed();

} else {
_pressed();
}
queue_redraw();
accept_event();

if (shortcut_feedback) {
if (shortcut_feedback_timer == nullptr) {
shortcut_feedback_timer = memnew(Timer);
add_child(shortcut_feedback_timer);
shortcut_feedback_timer->set_wait_time(GLOBAL_GET("gui/timers/button_shortcut_feedback_highlight_time"));
shortcut_feedback_timer->connect("timeout", callable_mp(this, &BaseButton::_shortcut_feedback_timeout));
}

in_shortcut_feedback = true;
shortcut_feedback_timer->start();
}
}
}

Expand Down Expand Up @@ -393,14 +431,6 @@ bool BaseButton::_was_pressed_by_mouse() const {
return was_mouse_pressed;
}

void BaseButton::set_shortcut_feedback(bool p_feedback) {
shortcut_feedback = p_feedback;
}

bool BaseButton::is_shortcut_feedback() const {
return shortcut_feedback;
}

PackedStringArray BaseButton::get_configuration_warnings() const {
PackedStringArray warnings = Control::get_configuration_warnings();

Expand Down Expand Up @@ -429,16 +459,15 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_draw_mode"), &BaseButton::get_draw_mode);
ClassDB::bind_method(D_METHOD("set_keep_pressed_outside", "enabled"), &BaseButton::set_keep_pressed_outside);
ClassDB::bind_method(D_METHOD("is_keep_pressed_outside"), &BaseButton::is_keep_pressed_outside);
ClassDB::bind_method(D_METHOD("set_shortcut_feedback", "enabled"), &BaseButton::set_shortcut_feedback);
ClassDB::bind_method(D_METHOD("is_shortcut_feedback"), &BaseButton::is_shortcut_feedback);

ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &BaseButton::set_shortcut);
ClassDB::bind_method(D_METHOD("get_shortcut"), &BaseButton::get_shortcut);

ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group);
ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);

ClassDB::bind_method(D_METHOD("set_shortcut_feedback", "enabled"), &BaseButton::set_shortcut_feedback);
ClassDB::bind_method(D_METHOD("is_shortcut_feedback"), &BaseButton::is_shortcut_feedback);

GDVIRTUAL_BIND(_pressed);
GDVIRTUAL_BIND(_toggled, "button_pressed");

Expand Down Expand Up @@ -466,6 +495,8 @@ void BaseButton::_bind_methods() {

BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_PRESS);
BIND_ENUM_CONSTANT(ACTION_MODE_BUTTON_RELEASE);

GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/button_shortcut_feedback_highlight_time", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), 0.2);
}

BaseButton::BaseButton() {
Expand Down
13 changes: 8 additions & 5 deletions scene/gui/base_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,16 @@ class BaseButton : public Control {
bool shortcut_in_tooltip = true;
bool was_mouse_pressed = false;
bool keep_pressed_outside = false;
bool shortcut_feedback = true;
Ref<Shortcut> shortcut;
ObjectID shortcut_context;
bool shortcut_feedback = true;

ActionMode action_mode = ACTION_MODE_BUTTON_RELEASE;
struct Status {
bool pressed = false;
bool hovering = false;
bool press_attempt = false;
bool pressing_inside = false;
bool shortcut_press = false;

bool disabled = false;

Expand All @@ -75,6 +74,10 @@ class BaseButton : public Control {

void on_action_event(Ref<InputEvent> p_event);

Timer *shortcut_feedback_timer = nullptr;
bool in_shortcut_feedback = false;
void _shortcut_feedback_timeout();

protected:
virtual void pressed();
virtual void toggled(bool p_pressed);
Expand Down Expand Up @@ -122,6 +125,9 @@ class BaseButton : public Control {
void set_keep_pressed_outside(bool p_on);
bool is_keep_pressed_outside() const;

void set_shortcut_feedback(bool p_enable);
bool is_shortcut_feedback() const;

void set_button_mask(BitField<MouseButtonMask> p_mask);
BitField<MouseButtonMask> get_button_mask() const;

Expand All @@ -133,9 +139,6 @@ class BaseButton : public Control {
void set_button_group(const Ref<ButtonGroup> &p_group);
Ref<ButtonGroup> get_button_group() const;

void set_shortcut_feedback(bool p_feedback);
bool is_shortcut_feedback() const;

PackedStringArray get_configuration_warnings() const override;

BaseButton();
Expand Down