From 50506e19a6fd0a8c692bab8e642a71dfa3ed26d2 Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Fri, 19 Aug 2022 15:19:34 -0300 Subject: [PATCH] Make `Menu/OptionButton` item auto-highlight behave better --- scene/gui/base_button.cpp | 7 +++++++ scene/gui/base_button.h | 3 +++ scene/gui/menu_button.cpp | 5 +---- scene/gui/option_button.cpp | 5 +---- scene/gui/popup_menu.cpp | 10 ++++++---- scene/gui/popup_menu.h | 4 +++- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index f51d423ad7f..4cdcdc0f77f 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -64,6 +64,8 @@ void BaseButton::_gui_input(Ref p_event) { bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) > 0; if (button_masked || ui_accept) { + was_mouse_pressed = button_masked; + on_action_event(p_event); return; } @@ -388,6 +390,10 @@ Ref BaseButton::get_button_group() const { return button_group; } +bool BaseButton::_was_pressed_by_mouse() const { + return was_mouse_pressed; +} + void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &BaseButton::_gui_input); ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input); @@ -449,6 +455,7 @@ BaseButton::BaseButton() { toggle_mode = false; shortcut_in_tooltip = true; keep_pressed_outside = false; + was_mouse_pressed = false; status.pressed = false; status.press_attempt = false; status.hovering = false; diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 9a7dc3c7e3b..f379e2d4966 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -49,6 +49,7 @@ private: bool toggle_mode; bool shortcut_in_tooltip; bool keep_pressed_outside; + bool was_mouse_pressed; FocusMode enabled_focus_mode; Ref shortcut; @@ -79,6 +80,8 @@ protected: virtual void _unhandled_input(Ref p_event); void _notification(int p_what); + bool _was_pressed_by_mouse() const; + public: enum DrawMode { DRAW_NORMAL, diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 2c9766cae01..268802cc2ea 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -29,7 +29,6 @@ /*************************************************************************/ #include "menu_button.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "scene/main/viewport.h" @@ -64,9 +63,7 @@ void MenuButton::pressed() { popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size())); // If not triggered by the mouse, start the popup with its first item selected. - if (popup->get_item_count() > 0 && - ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || - (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + if (popup->get_item_count() > 0 && !_was_pressed_by_mouse()) { popup->set_current_index(0); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 56f3d8ae6e0..248ccba9b5a 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -29,7 +29,6 @@ /*************************************************************************/ #include "option_button.h" -#include "core/os/input.h" #include "core/print_string.h" static const int NONE_SELECTED = -1; @@ -114,9 +113,7 @@ void OptionButton::pressed() { popup->set_scale(get_global_transform().get_scale()); // If not triggered by the mouse, start the popup with its first item selected. - if (popup->get_item_count() > 0 && - ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || - (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + if (popup->get_item_count() > 0 && !_was_pressed_by_mouse()) { popup->set_current_index(0); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 1b22b2b81aa..96f5ad5a187 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -145,7 +145,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { return -1; } -void PopupMenu::_activate_submenu(int over) { +void PopupMenu::_activate_submenu(int over, bool p_by_keyboard) { Node *n = get_node(items[over].submenu); ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[over].submenu + "."); Popup *pm = Object::cast_to(n); @@ -172,7 +172,7 @@ void PopupMenu::_activate_submenu(int over) { PopupMenu *pum = Object::cast_to(pm); if (pum) { // If not triggered by the mouse, start the popup with its first item selected. - if (pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) { + if (pum->get_item_count() > 0 && p_by_keyboard) { pum->set_current_index(0); } @@ -299,13 +299,13 @@ void PopupMenu::_gui_input(const Ref &p_event) { } } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + _activate_submenu(mouse_over, true); accept_event(); } } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + _activate_submenu(mouse_over, true); } else { activate_item(mouse_over); } @@ -1476,6 +1476,8 @@ void PopupMenu::popup(const Rect2 &p_bounds) { } PopupMenu::PopupMenu() { + activated_by_keyboard = false; + mouse_over = -1; submenu_over = -1; initial_button_mask = 0; diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index e2e367b9388..9f2e741bcdb 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -76,6 +76,8 @@ class PopupMenu : public Popup { } }; + bool activated_by_keyboard; + Timer *submenu_timer; List autohide_areas; Vector items; @@ -89,7 +91,7 @@ class PopupMenu : public Popup { virtual Size2 get_minimum_size() const; void _scroll(float p_factor, const Point2 &p_over); void _gui_input(const Ref &p_event); - void _activate_submenu(int over); + void _activate_submenu(int over, bool p_by_keyboard = false); void _submenu_timeout(); bool invalidated_click;